Skip to content

Commit c5f0b8b

Browse files
authored
[SimplifyCFG] Support trunc nuw in chain of comparisons. (#155087)
proof: https://alive2.llvm.org/ce/z/5PNCds
1 parent bfc8411 commit c5f0b8b

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,15 @@ struct ConstantComparesGatherer {
612612
/// If CompValue is already set, the function is expected to fail if a match
613613
/// is found but the value compared to is different.
614614
bool matchInstruction(Instruction *I, bool isEQ) {
615+
Value *Val;
616+
if (match(I, m_NUWTrunc(m_Value(Val)))) {
617+
// If we already have a value for the switch, it has to match!
618+
if (!setValueOnce(Val))
619+
return false;
620+
UsedICmps++;
621+
Vals.push_back(ConstantInt::get(cast<IntegerType>(Val->getType()), isEQ));
622+
return true;
623+
}
615624
// If this is an icmp against a constant, handle this as one of the cases.
616625
ICmpInst *ICI;
617626
ConstantInt *C;

llvm/test/Transforms/SimplifyCFG/switch_create.ll

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,3 +1192,76 @@ if.end:
11921192
ret void
11931193

11941194
}
1195+
1196+
define void @and_chain_trunc_nuw_i1_condition(i8 %x) {
1197+
; CHECK-LABEL: @and_chain_trunc_nuw_i1_condition(
1198+
; CHECK-NEXT: switch i8 [[X:%.*]], label [[IF_THEN:%.*]] [
1199+
; CHECK-NEXT: i8 4, label [[COMMON_RET:%.*]]
1200+
; CHECK-NEXT: i8 3, label [[COMMON_RET]]
1201+
; CHECK-NEXT: i8 2, label [[COMMON_RET]]
1202+
; CHECK-NEXT: i8 0, label [[COMMON_RET]]
1203+
; CHECK-NEXT: ]
1204+
; CHECK: common.ret:
1205+
; CHECK-NEXT: ret void
1206+
; CHECK: if.then:
1207+
; CHECK-NEXT: tail call void @foo1()
1208+
; CHECK-NEXT: br label [[COMMON_RET]]
1209+
;
1210+
%add = add nsw i8 %x, -2
1211+
%icmp = icmp ugt i8 %add, 2
1212+
%trunc = trunc nuw i8 %x to i1
1213+
%and = select i1 %icmp, i1 %trunc, i1 false
1214+
br i1 %and, label %if.then, label %if.end
1215+
if.then:
1216+
tail call void @foo1()
1217+
ret void
1218+
if.end:
1219+
ret void
1220+
}
1221+
1222+
define void @or_chain_trunc_nuw_i1_condition(i8 %x) {
1223+
; CHECK-LABEL: @or_chain_trunc_nuw_i1_condition(
1224+
; CHECK-NEXT: [[X_OFF:%.*]] = add i8 [[X:%.*]], -1
1225+
; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[X_OFF]], 2
1226+
; CHECK-NEXT: br i1 [[SWITCH]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]]
1227+
; CHECK: common.ret:
1228+
; CHECK-NEXT: ret void
1229+
; CHECK: if.then:
1230+
; CHECK-NEXT: tail call void @foo1()
1231+
; CHECK-NEXT: br label [[COMMON_RET]]
1232+
;
1233+
%icmp = icmp eq i8 %x, 2
1234+
%trunc = trunc nuw i8 %x to i1
1235+
%or = select i1 %icmp, i1 true, i1 %trunc
1236+
br i1 %or, label %if.then, label %if.end
1237+
if.then:
1238+
tail call void @foo1()
1239+
ret void
1240+
if.end:
1241+
ret void
1242+
}
1243+
1244+
define void @neg_and_chain_trunc_i1_condition(i8 %x) {
1245+
; CHECK-LABEL: @neg_and_chain_trunc_i1_condition(
1246+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X:%.*]], -2
1247+
; CHECK-NEXT: [[ICMP:%.*]] = icmp ugt i8 [[ADD]], 2
1248+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X]] to i1
1249+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[ICMP]], i1 [[TRUNC]], i1 false
1250+
; CHECK-NEXT: br i1 [[AND]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]]
1251+
; CHECK: common.ret:
1252+
; CHECK-NEXT: ret void
1253+
; CHECK: if.then:
1254+
; CHECK-NEXT: tail call void @foo1()
1255+
; CHECK-NEXT: br label [[COMMON_RET]]
1256+
;
1257+
%add = add nsw i8 %x, -2
1258+
%icmp = icmp ugt i8 %add, 2
1259+
%trunc = trunc i8 %x to i1
1260+
%and = select i1 %icmp, i1 %trunc, i1 false
1261+
br i1 %and, label %if.then, label %if.end
1262+
if.then:
1263+
tail call void @foo1()
1264+
ret void
1265+
if.end:
1266+
ret void
1267+
}

0 commit comments

Comments
 (0)