diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3281,6 +3281,29 @@ return nullptr; } +static Value *simplifyICmpWithDominatingAssume(CmpInst::Predicate Predicate, + Value *LHS, Value *RHS, + const SimplifyQuery &Q) { + if (!Q.AC || !Q.CxtI) + return nullptr; + + for (Value *AssumeBaseOp : {LHS, RHS}) { + for (auto &AssumeVH : Q.AC->assumptionsFor(AssumeBaseOp)) { + if (!AssumeVH) + continue; + + CallInst *Assume = cast(AssumeVH); + if (Optional Imp = + isImpliedCondition(Assume->getArgOperand(0), Predicate, LHS, RHS, + Q.DL)) + if (isValidAssumeForContext(Assume, Q.CxtI, Q.DT)) + return ConstantInt::get(GetCompareTy(LHS), *Imp); + } + } + + return nullptr; +} + /// Given operands for an ICmpInst, see if we can fold the result. /// If not, this returns null. static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, @@ -3515,6 +3538,9 @@ if (Value *V = simplifyICmpWithMinMax(Pred, LHS, RHS, Q, MaxRecurse)) return V; + if (Value *V = simplifyICmpWithDominatingAssume(Pred, LHS, RHS, Q)) + return V; + // Simplify comparisons of related pointers using a powerful, recursive // GEP-walk when we have target data available.. if (LHS->getType()->isPointerTy()) diff --git a/llvm/test/Transforms/InstSimplify/assume_icmp.ll b/llvm/test/Transforms/InstSimplify/assume_icmp.ll --- a/llvm/test/Transforms/InstSimplify/assume_icmp.ll +++ b/llvm/test/Transforms/InstSimplify/assume_icmp.ll @@ -8,22 +8,14 @@ ; CHECK-LABEL: @basic_ugt( ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) -; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[X]], [[Y]] -; CHECK-NEXT: call void @use(i1 [[CMP2]]) -; CHECK-NEXT: [[CMP3:%.*]] = icmp uge i32 [[X]], [[Y]] -; CHECK-NEXT: call void @use(i1 [[CMP3]]) -; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[X]], [[Y]] -; CHECK-NEXT: call void @use(i1 [[CMP4]]) -; CHECK-NEXT: [[CMP5:%.*]] = icmp ule i32 [[X]], [[Y]] -; CHECK-NEXT: call void @use(i1 [[CMP5]]) -; CHECK-NEXT: [[CMP6:%.*]] = icmp ugt i32 [[Y]], [[X]] -; CHECK-NEXT: call void @use(i1 [[CMP6]]) -; CHECK-NEXT: [[CMP7:%.*]] = icmp uge i32 [[Y]], [[X]] -; CHECK-NEXT: call void @use(i1 [[CMP7]]) -; CHECK-NEXT: [[CMP8:%.*]] = icmp ult i32 [[Y]], [[X]] -; CHECK-NEXT: call void @use(i1 [[CMP8]]) -; CHECK-NEXT: [[CMP9:%.*]] = icmp ule i32 [[Y]], [[X]] -; CHECK-NEXT: call void @use(i1 [[CMP9]]) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; %cmp1 = icmp ugt i32 %x, %y @@ -56,20 +48,16 @@ ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[X]], [[Y]] ; CHECK-NEXT: call void @use(i1 [[CMP2]]) -; CHECK-NEXT: [[CMP3:%.*]] = icmp uge i32 [[X]], [[Y]] -; CHECK-NEXT: call void @use(i1 [[CMP3]]) -; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[X]], [[Y]] -; CHECK-NEXT: call void @use(i1 [[CMP4]]) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ule i32 [[X]], [[Y]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) -; CHECK-NEXT: [[CMP6:%.*]] = icmp ugt i32 [[Y]], [[X]] -; CHECK-NEXT: call void @use(i1 [[CMP6]]) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[CMP7:%.*]] = icmp uge i32 [[Y]], [[X]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp ult i32 [[Y]], [[X]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) -; CHECK-NEXT: [[CMP9:%.*]] = icmp ule i32 [[Y]], [[X]] -; CHECK-NEXT: call void @use(i1 [[CMP9]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; %cmp1 = icmp uge i32 %x, %y @@ -96,6 +84,9 @@ ret void } +; This does not simplify in InstSimplify, because AssumptionCache tracker +; does not track values through "and". The "and" assume will be broken +; down into two separate assume calls by InstCombine. define void @and(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @and( ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]