diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp index 02420fa8abd97..38a312a3715c9 100644 --- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp +++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp @@ -370,6 +370,8 @@ void PredicateInfoBuilder::processAssume( Values.push_back(Cond); if (auto *Cmp = dyn_cast(Cond)) collectCmpOps(Cmp, Values); + else if (match(Cond, m_NUWTrunc(m_Value(Op0)))) + Values.push_back(Op0); for (Value *V : Values) { if (shouldRename(V)) { @@ -416,6 +418,8 @@ void PredicateInfoBuilder::processBranch( Values.push_back(Cond); if (auto *Cmp = dyn_cast(Cond)) collectCmpOps(Cmp, Values); + else if (match(Cond, m_NUWTrunc(m_Value(Op0)))) + Values.push_back(Op0); for (Value *V : Values) { if (shouldRename(V)) { @@ -709,6 +713,11 @@ std::optional PredicateBase::getConstraint() const { : ConstantInt::getFalse(Condition->getType())}}; } + if (match(Condition, m_NUWTrunc(m_Specific(RenamedOp)))) { + return {{TrueEdge ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ, + ConstantInt::getNullValue(RenamedOp->getType())}}; + } + CmpInst *Cmp = dyn_cast(Condition); if (!Cmp) { // TODO: Make this an assertion once RenamedOp is fully accurate. diff --git a/llvm/test/Transforms/SCCP/assume.ll b/llvm/test/Transforms/SCCP/assume.ll index 8146d58d9a897..9beee934bb509 100644 --- a/llvm/test/Transforms/SCCP/assume.ll +++ b/llvm/test/Transforms/SCCP/assume.ll @@ -69,3 +69,53 @@ define void @nonnull(ptr %v) { call void @use(i1 %c4) ret void } + +define void @trunc_nuw(i8 %v) { +; CHECK-LABEL: @trunc_nuw( +; CHECK-NEXT: [[A:%.*]] = trunc nuw i8 [[V:%.*]] to i1 +; CHECK-NEXT: call void @llvm.assume(i1 [[A]]) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: ret void +; + %a = trunc nuw i8 %v to i1 + call void @llvm.assume(i1 %a) + %c1 = icmp eq i8 %v, 0 + call void @use(i1 %c1) + %c2 = icmp ne i8 %v, 0 + call void @use(i1 %c2) + %c3 = icmp eq i8 0, %v + call void @use(i1 %c3) + %c4 = icmp ne i8 0, %v + call void @use(i1 %c4) + ret void +} + +define void @neg_trunc(i8 %v) { +; CHECK-LABEL: @neg_trunc( +; CHECK-NEXT: [[A:%.*]] = trunc i8 [[V:%.*]] to i1 +; CHECK-NEXT: call void @llvm.assume(i1 [[A]]) +; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: call void @use(i1 [[C1]]) +; CHECK-NEXT: [[C2:%.*]] = icmp ne i8 [[V]], 0 +; CHECK-NEXT: call void @use(i1 [[C2]]) +; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 0, [[V]] +; CHECK-NEXT: call void @use(i1 [[C3]]) +; CHECK-NEXT: [[C4:%.*]] = icmp ne i8 0, [[V]] +; CHECK-NEXT: call void @use(i1 [[C4]]) +; CHECK-NEXT: ret void +; + %a = trunc i8 %v to i1 + call void @llvm.assume(i1 %a) + %c1 = icmp eq i8 %v, 0 + call void @use(i1 %c1) + %c2 = icmp ne i8 %v, 0 + call void @use(i1 %c2) + %c3 = icmp eq i8 0, %v + call void @use(i1 %c3) + %c4 = icmp ne i8 0, %v + call void @use(i1 %c4) + ret void +} diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll index bb3764160f724..7a64778b60789 100644 --- a/llvm/test/Transforms/SCCP/conditions-ranges.ll +++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll @@ -1444,3 +1444,65 @@ define i1 @ptr_icmp_data_layout() { %cmp = icmp eq ptr %a.end, @A ret i1 %cmp } + +define void @trunc_nuw_1_dominating_icmp_ne_0(i8 %x) { +; CHECK-LABEL: @trunc_nuw_1_dominating_icmp_ne_0( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1 +; CHECK-NEXT: br i1 [[TRUNC]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: ret void +; CHECK: bb2: +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: ret void +; + %trunc = trunc nuw i8 %x to i1 + br i1 %trunc, label %bb1, label %bb2 +bb1: + %c1 = icmp ne i8 %x , 0 + call void @use(i1 %c1) + %c2 = icmp ne i8 0, %x + call void @use(i1 %c2) + ret void +bb2: + %c3 = icmp ne i8 %x , 0 + call void @use(i1 %c3) + %c4 = icmp ne i8 0, %x + call void @use(i1 %c4) + ret void +} + +define void @neg_trunc_1_dominating_icmp_ne_0(i8 %x) { +; CHECK-LABEL: @neg_trunc_1_dominating_icmp_ne_0( +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1 +; CHECK-NEXT: br i1 [[TRUNC]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X]], 0 +; CHECK-NEXT: call void @use(i1 [[C1]]) +; CHECK-NEXT: [[C2:%.*]] = icmp ne i8 0, [[X]] +; CHECK-NEXT: call void @use(i1 [[C2]]) +; CHECK-NEXT: ret void +; CHECK: bb2: +; CHECK-NEXT: [[C3:%.*]] = icmp ne i8 [[X]], 0 +; CHECK-NEXT: call void @use(i1 [[C3]]) +; CHECK-NEXT: [[C4:%.*]] = icmp ne i8 0, [[X]] +; CHECK-NEXT: call void @use(i1 [[C4]]) +; CHECK-NEXT: ret void +; + %trunc = trunc i8 %x to i1 + br i1 %trunc, label %bb1, label %bb2 +bb1: + %c1 = icmp ne i8 %x , 0 + call void @use(i1 %c1) + %c2 = icmp ne i8 0, %x + call void @use(i1 %c2) + ret void +bb2: + %c3 = icmp ne i8 %x , 0 + call void @use(i1 %c3) + %c4 = icmp ne i8 0, %x + call void @use(i1 %c4) + ret void +}