Skip to content

switch not recognized as equivalent to sext #54561

@scottmcm

Description

@scottmcm

Opt transformation showing suboptimal current result on trunk: https://llvm.godbolt.org/z/jj6vcv5q3
Alive2 demonstration that the proposed transformation is correct: https://alive2.llvm.org/ce/z/hAAoh_
Original motivating example in rust-lang/rust#95313: https://rust.godbolt.org/z/dvYe9r78c

The following code:

define i32 @src(i8 noundef %0) {
start:
  %1 = alloca i32, align 4
  %order = alloca i8, align 1
  store i8 %0, i8* %order, align 1
  %_2 = load i8, i8* %order, align 1, !range !2, !noundef !3
  switch i8 %_2, label %bb2 [
    i8 -1, label %bb3
    i8 0, label %bb4
    i8 1, label %bb1
  ]

bb2:                                              ; preds = %start
  unreachable

bb3:                                              ; preds = %start
  store i32 -1, i32* %1, align 4
  br label %bb5

bb4:                                              ; preds = %start
  store i32 0, i32* %1, align 4
  br label %bb5

bb1:                                              ; preds = %start
  store i32 1, i32* %1, align 4
  br label %bb5

bb5:                                              ; preds = %bb3, %bb4, %bb1
  %2 = load i32, i32* %1, align 4
  ret i32 %2
}

!2 = !{i8 -1, i8 2}
!3 = !{}

Optimizes to this slightly suboptimal IR:

define i32 @src(i8 noundef %0) local_unnamed_addr #0 {
  %switch.tableidx = add i8 %0, 1
  %switch.idx.cast = zext i8 %switch.tableidx to i32
  %switch.offset = add nsw i32 %switch.idx.cast, -1
  ret i32 %switch.offset
}

But as Alive confirms, it could just be a sext:

define i32 @tgt(i8 noundef %0) {
%start:
  %1 = sext i8 noundef %0 to i32
  ret i32 %1
}
// Transformation seems to be correct!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions