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<CallInst>(AssumeVH);
+ if (Optional<bool> 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,
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())
; 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
; 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
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:%.*]]