diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index d1ac8d9fbdfd1..cb1dae92faf92 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2981,7 +2981,7 @@ static Value *simplifyICmpWithZero(CmpPredicate Pred, Value *LHS, Value *RHS, } static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS, - Value *RHS, const InstrInfoQuery &IIQ) { + Value *RHS, const SimplifyQuery &Q) { Type *ITy = getCompareTy(RHS); // The return type. Value *X; @@ -3007,7 +3007,7 @@ static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS, return ConstantInt::getTrue(ITy); ConstantRange LHS_CR = - computeConstantRange(LHS, CmpInst::isSigned(Pred), IIQ.UseInstrInfo); + computeConstantRange(LHS, CmpInst::isSigned(Pred), Q.IIQ.UseInstrInfo); if (!LHS_CR.isFullSet()) { if (RHS_CR.contains(LHS_CR)) return ConstantInt::getTrue(ITy); @@ -3018,13 +3018,16 @@ static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS, // (mul nuw/nsw X, MulC) != C --> true (if C is not a multiple of MulC) // (mul nuw/nsw X, MulC) == C --> false (if C is not a multiple of MulC) const APInt *MulC; - if (IIQ.UseInstrInfo && ICmpInst::isEquality(Pred) && + if (Q.IIQ.UseInstrInfo && ICmpInst::isEquality(Pred) && ((match(LHS, m_NUWMul(m_Value(), m_APIntAllowPoison(MulC))) && *MulC != 0 && C->urem(*MulC) != 0) || (match(LHS, m_NSWMul(m_Value(), m_APIntAllowPoison(MulC))) && *MulC != 0 && C->srem(*MulC) != 0))) return ConstantInt::get(ITy, Pred == ICmpInst::ICMP_NE); + if (Pred == ICmpInst::ICMP_UGE && C->isOne() && isKnownNonZero(LHS, Q)) + return ConstantInt::getTrue(ITy); + return nullptr; } @@ -3776,7 +3779,7 @@ static Value *simplifyICmpInst(CmpPredicate Pred, Value *LHS, Value *RHS, if (Value *V = simplifyICmpWithZero(Pred, LHS, RHS, Q)) return V; - if (Value *V = simplifyICmpWithConstant(Pred, LHS, RHS, Q.IIQ)) + if (Value *V = simplifyICmpWithConstant(Pred, LHS, RHS, Q)) return V; // If both operands have range metadata, use the metadata diff --git a/llvm/test/Transforms/InstSimplify/umax-1.ll b/llvm/test/Transforms/InstSimplify/umax-1.ll new file mode 100644 index 0000000000000..77863acb02327 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/umax-1.ll @@ -0,0 +1,120 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=instsimplify -S | FileCheck %s + +define i32 @known_non_zero_by_or(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @known_non_zero_by_or( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 +; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]] +; CHECK-NEXT: ret i32 [[VAL]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: ret i32 0 +; + %cond = icmp ne i32 %x, 0 + br i1 %cond, label %if.then, label %if.else + +if.then: + %val = or i32 %x, %y + %max = call i32 @llvm.umax.i32(i32 %val, i32 1) + ret i32 %max + +if.else: + ret i32 0 +} + +define i32 @known_non_zero_by_mul(i32 %x) { +; CHECK-LABEL: define i32 @known_non_zero_by_mul( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 +; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[NONZERO1:%.*]] = mul nuw i32 [[X]], 3 +; CHECK-NEXT: ret i32 [[NONZERO1]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: ret i32 0 +; + %cond = icmp ne i32 %x, 0 + br i1 %cond, label %if.then, label %if.else + +if.then: + %nonzero = mul nuw i32 %x, 3 + %max = call i32 @llvm.umax.i32(i32 %nonzero, i32 1) + ret i32 %max + +if.else: + ret i32 0 +} + +define i32 @known_non_zero_commute(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @known_non_zero_commute( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 +; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]] +; CHECK-NEXT: ret i32 [[VAL]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: ret i32 0 +; + %cond = icmp ne i32 %x, 0 + br i1 %cond, label %if.then, label %if.else + +if.then: + %val = or i32 %x, %y + %max = call i32 @llvm.umax.i32(i32 1, i32 %val) + ret i32 %max + +if.else: + ret i32 0 +} + +; Negative +define i32 @umax_ge_2(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @umax_ge_2( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 +; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]] +; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[VAL]], i32 2) +; CHECK-NEXT: ret i32 [[MAX]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: ret i32 0 +; + %cond = icmp ne i32 %x, 0 + br i1 %cond, label %if.then, label %if.else + +if.then: + %val = or i32 %x, %y + %max = call i32 @llvm.umax.i32(i32 %val, i32 2) + ret i32 %max + +if.else: + ret i32 0 +} + +define i32 @unknown_by_and(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @unknown_by_and( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 +; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[VAL:%.*]] = and i32 [[X]], [[Y]] +; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[VAL]], i32 1) +; CHECK-NEXT: ret i32 [[MAX]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: ret i32 0 +; + %cond = icmp ne i32 %x, 0 + br i1 %cond, label %if.then, label %if.else + +if.then: + %val = and i32 %x, %y + %max = call i32 @llvm.umax.i32(i32 %val, i32 1) + ret i32 %max + +if.else: + ret i32 0 +}