diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 93ace4d50cbdc..84a838b48eadd 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -612,6 +612,15 @@ struct ConstantComparesGatherer { /// If CompValue is already set, the function is expected to fail if a match /// is found but the value compared to is different. bool matchInstruction(Instruction *I, bool isEQ) { + Value *Val; + if (match(I, m_NUWTrunc(m_Value(Val)))) { + // If we already have a value for the switch, it has to match! + if (!setValueOnce(Val)) + return false; + UsedICmps++; + Vals.push_back(ConstantInt::get(cast(Val->getType()), isEQ)); + return true; + } // If this is an icmp against a constant, handle this as one of the cases. ICmpInst *ICI; ConstantInt *C; diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll index a06e64f74b3ac..6d2a404203d02 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll @@ -1192,3 +1192,76 @@ if.end: ret void } + +define void @and_chain_trunc_nuw_i1_condition(i8 %x) { +; CHECK-LABEL: @and_chain_trunc_nuw_i1_condition( +; CHECK-NEXT: switch i8 [[X:%.*]], label [[IF_THEN:%.*]] [ +; CHECK-NEXT: i8 4, label [[COMMON_RET:%.*]] +; CHECK-NEXT: i8 3, label [[COMMON_RET]] +; CHECK-NEXT: i8 2, label [[COMMON_RET]] +; CHECK-NEXT: i8 0, label [[COMMON_RET]] +; CHECK-NEXT: ] +; CHECK: common.ret: +; CHECK-NEXT: ret void +; CHECK: if.then: +; CHECK-NEXT: tail call void @foo1() +; CHECK-NEXT: br label [[COMMON_RET]] +; + %add = add nsw i8 %x, -2 + %icmp = icmp ugt i8 %add, 2 + %trunc = trunc nuw i8 %x to i1 + %and = select i1 %icmp, i1 %trunc, i1 false + br i1 %and, label %if.then, label %if.end +if.then: + tail call void @foo1() + ret void +if.end: + ret void +} + +define void @or_chain_trunc_nuw_i1_condition(i8 %x) { +; CHECK-LABEL: @or_chain_trunc_nuw_i1_condition( +; CHECK-NEXT: [[X_OFF:%.*]] = add i8 [[X:%.*]], -1 +; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[X_OFF]], 2 +; CHECK-NEXT: br i1 [[SWITCH]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]] +; CHECK: common.ret: +; CHECK-NEXT: ret void +; CHECK: if.then: +; CHECK-NEXT: tail call void @foo1() +; CHECK-NEXT: br label [[COMMON_RET]] +; + %icmp = icmp eq i8 %x, 2 + %trunc = trunc nuw i8 %x to i1 + %or = select i1 %icmp, i1 true, i1 %trunc + br i1 %or, label %if.then, label %if.end +if.then: + tail call void @foo1() + ret void +if.end: + ret void +} + +define void @neg_and_chain_trunc_i1_condition(i8 %x) { +; CHECK-LABEL: @neg_and_chain_trunc_i1_condition( +; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X:%.*]], -2 +; CHECK-NEXT: [[ICMP:%.*]] = icmp ugt i8 [[ADD]], 2 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X]] to i1 +; CHECK-NEXT: [[AND:%.*]] = select i1 [[ICMP]], i1 [[TRUNC]], i1 false +; CHECK-NEXT: br i1 [[AND]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]] +; CHECK: common.ret: +; CHECK-NEXT: ret void +; CHECK: if.then: +; CHECK-NEXT: tail call void @foo1() +; CHECK-NEXT: br label [[COMMON_RET]] +; + %add = add nsw i8 %x, -2 + %icmp = icmp ugt i8 %add, 2 + %trunc = trunc i8 %x to i1 + %and = select i1 %icmp, i1 %trunc, i1 false + br i1 %and, label %if.then, label %if.end +if.then: + tail call void @foo1() + ret void +if.end: + ret void +}