diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -44,6 +44,17 @@ static int64_t MaxConstraintValue = std::numeric_limits::max(); namespace { + +/// Struct to express a pre-condition of the form %Op0 Pred %Op1. +struct PreconditionTy { + CmpInst::Predicate Pred; + Value *Op0; + Value *Op1; + + PreconditionTy(CmpInst::Predicate Pred, Value *Op0, Value *Op1) + : Pred(Pred), Op0(Op0), Op1(Op1) {} +}; + struct ConstraintTy { SmallVector Coefficients; @@ -53,17 +64,23 @@ unsigned size() const { return Coefficients.size(); } }; -/// Struct to manage a list of constraints. +/// Struct to manage a list of constraints with pre-conditions that must be +/// satisfied before using the constraints. struct ConstraintListTy { SmallVector Constraints; + SmallVector Preconditions; ConstraintListTy() {} - ConstraintListTy(const SmallVector &Constraints) - : Constraints(Constraints) {} + ConstraintListTy(ArrayRef Constraints, + ArrayRef Preconditions) + : Constraints(Constraints.begin(), Constraints.end()), + Preconditions(Preconditions.begin(), Preconditions.end()) {} void mergeIn(const ConstraintListTy &Other) { append_range(Constraints, Other.Constraints); + // TODO: Do smarter merges here, e.g. exclude duplicates. + append_range(Preconditions, Other.Preconditions); } unsigned size() const { return Constraints.size(); } @@ -84,6 +101,17 @@ } ConstraintTy &get(unsigned I) { return Constraints[I]; } + + /// Returns true if all preconditions for this list of constraints are + /// satisfied given \p CS and the corresponding \p Value2Index mapping. + bool isValid(const ConstraintSystem &CS, + DenseMap &Value2Index) const; + /// Returns true if there is exactly one constraint in the list and isValid is + /// also true. + bool isValidSingle(const ConstraintSystem &CS, + DenseMap &Value2Index) const { + return size() == 1 && isValid(CS, Value2Index); + } }; } // namespace @@ -92,7 +120,8 @@ // sum of the pairs equals \p V. The first pair is the constant-factor and X // must be nullptr. If the expression cannot be decomposed, returns an empty // vector. -static SmallVector, 4> decompose(Value *V) { +static SmallVector, 4> +decompose(Value *V, SmallVector &Preconditions) { if (auto *CI = dyn_cast(V)) { if (CI->isNegative() || CI->uge(MaxConstraintValue)) return {}; @@ -136,6 +165,10 @@ Op0 = GEP->getOperand(GEP->getNumOperands() - 1); Result = {{0, nullptr}, {1, GEP->getPointerOperand()}, {1, Op0}}; } + // If Op0 is signed non-negative, the GEP is increasing monotonically and + // can be de-composed. + Preconditions.emplace_back(CmpInst::ICMP_SGE, Op0, + ConstantInt::get(Op0->getType(), 0)); return Result; } @@ -168,6 +201,7 @@ int64_t Offset1 = 0; int64_t Offset2 = 0; + SmallVector Preconditions; // First try to look up \p V in Value2Index and NewIndices. Otherwise add a // new entry to NewIndices. auto GetOrAddIndex = [&Value2Index, &NewIndices](Value *V) -> unsigned { @@ -207,8 +241,10 @@ if (Pred != CmpInst::ICMP_ULE && Pred != CmpInst::ICMP_ULT) return {}; - auto ADec = decompose(Op0->stripPointerCastsSameRepresentation()); - auto BDec = decompose(Op1->stripPointerCastsSameRepresentation()); + auto ADec = + decompose(Op0->stripPointerCastsSameRepresentation(), Preconditions); + auto BDec = + decompose(Op1->stripPointerCastsSameRepresentation(), Preconditions); // Skip if decomposing either of the values failed. if (ADec.empty() || BDec.empty()) return {}; @@ -240,16 +276,27 @@ R[GetOrAddIndex(KV.second)] -= KV.first; R[0] = Offset1 + Offset2 + (Pred == CmpInst::ICMP_ULT ? -1 : 0); - return {{R}}; + return {{R}, Preconditions}; } -static ConstraintListTy -getConstraint(CmpInst *Cmp, const DenseMap &Value2Index, - DenseMap &NewIndices) { +static ConstraintListTy getConstraint(CmpInst *Cmp, + DenseMap &Value2Index, + DenseMap &NewIndices) { return getConstraint(Cmp->getPredicate(), Cmp->getOperand(0), Cmp->getOperand(1), Value2Index, NewIndices); } +bool ConstraintListTy::isValid(const ConstraintSystem &CS, + DenseMap &Value2Index) const { + return all_of(Preconditions, [&CS, &Value2Index](const PreconditionTy &C) { + DenseMap NewIndices; + auto R = getConstraint(C.Pred, C.Op0, C.Op1, Value2Index, NewIndices); + // TODO: properly check NewIndices. + return NewIndices.empty() && R.Preconditions.empty() && R.size() == 1 && + CS.isConditionImplied(R.get(0).Coefficients); + }); +} + namespace { /// Represents either a condition that holds on entry to a block or a basic /// block, with their respective Dominator DFS in and out numbers. @@ -437,10 +484,8 @@ DenseMap NewIndices; auto R = getConstraint(Cmp, Value2Index, NewIndices); - if (R.size() != 1) - continue; - if (R.needsNewIndices(NewIndices)) + if (!R.isValidSingle(CS, Value2Index) || R.needsNewIndices(NewIndices)) continue; if (CS.isConditionImplied(R.get(0).Coefficients)) { @@ -503,7 +548,7 @@ // it into a constraint. DenseMap NewIndices; auto R = getConstraint(CB.Condition, Value2Index, NewIndices); - if (R.empty()) + if (!R.isValid(CS, Value2Index)) continue; for (auto &KV : NewIndices) diff --git a/llvm/test/Transforms/ConstraintElimination/gep-arithmetic.ll b/llvm/test/Transforms/ConstraintElimination/gep-arithmetic.ll --- a/llvm/test/Transforms/ConstraintElimination/gep-arithmetic.ll +++ b/llvm/test/Transforms/ConstraintElimination/gep-arithmetic.ll @@ -85,7 +85,7 @@ ; CHECK-NEXT: [[CMP_DST_SUB_4_LOWER:%.*]] = icmp uge i8* [[DST_SUB_4]], [[LOWER]] ; CHECK-NEXT: [[CMP_DST_SUB_4_UPPER:%.*]] = icmp ult i8* [[DST_SUB_4]], [[UPPER]] ; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[CMP_DST_SUB_4_LOWER]] -; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true +; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], [[CMP_DST_SUB_4_UPPER]] ; CHECK-NEXT: [[DST_SUB_5:%.*]] = getelementptr inbounds i8, i8* [[DST]], i64 -5 ; CHECK-NEXT: [[CMP_DST_SUB_5_LOWER:%.*]] = icmp uge i8* [[DST_SUB_5]], [[LOWER]] ; CHECK-NEXT: [[CMP_DST_SUB_5_UPPER:%.*]] = icmp ult i8* [[DST_SUB_5]], [[UPPER]] @@ -259,7 +259,7 @@ ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1 ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]] ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]] -; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false +; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, [[CMP_STEP_END]] ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret i4 3 @@ -374,7 +374,7 @@ ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1 ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]] ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]] -; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false +; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, [[CMP_STEP_END]] ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret i4 3 @@ -435,7 +435,7 @@ ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1 ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]] ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]] -; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false +; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, [[CMP_STEP_END]] ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret i4 3 @@ -545,7 +545,7 @@ ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[STEP]] ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]] ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]] -; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false +; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret i4 3 @@ -652,7 +652,7 @@ ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[STEP]] ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]] ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]] -; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false +; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret i4 3 @@ -912,7 +912,7 @@ ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]] ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]] ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]] -; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false +; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret i4 3 diff --git a/llvm/test/Transforms/ConstraintElimination/geps-unsigned-predicates.ll b/llvm/test/Transforms/ConstraintElimination/geps-unsigned-predicates.ll --- a/llvm/test/Transforms/ConstraintElimination/geps-unsigned-predicates.ll +++ b/llvm/test/Transforms/ConstraintElimination/geps-unsigned-predicates.ll @@ -480,7 +480,7 @@ ; CHECK: if.then: ; CHECK-NEXT: [[START_OFF_2:%.*]] = getelementptr inbounds i8, i8* [[START]], i8 [[OFF]] ; CHECK-NEXT: [[T_0:%.*]] = icmp uge i8* [[START_OFF_2]], [[HIGH]] -; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 [[T_0]]) ; CHECK-NEXT: ret void ; CHECK: if.end: ; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 1 @@ -488,7 +488,7 @@ ; CHECK-NEXT: call void @use(i1 [[C_0]]) ; CHECK-NEXT: [[START_OFF:%.*]] = getelementptr inbounds i8, i8* [[START]], i8 [[OFF]] ; CHECK-NEXT: [[F_0:%.*]] = icmp uge i8* [[START_OFF]], [[HIGH]] -; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 [[F_0]]) ; CHECK-NEXT: ret void ; entry: @@ -531,7 +531,7 @@ ; CHECK-NEXT: [[IDX_SHL_1:%.*]] = shl nuw i8 [[IDX]], 1 ; CHECK-NEXT: [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i8 [[IDX_SHL_1]] ; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult i32* [[ADD_PTR_SHL_1]], [[MAX]] -; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 [[C_MAX_0]]) ; CHECK-NEXT: [[IDX_SHL_2:%.*]] = shl nuw i8 [[IDX]], 2 ; CHECK-NEXT: [[ADD_PTR_SHL_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i8 [[IDX_SHL_2]] ; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult i32* [[ADD_PTR_SHL_2]], [[MAX]] diff --git a/llvm/test/Transforms/ConstraintElimination/large-system-growth.ll b/llvm/test/Transforms/ConstraintElimination/large-system-growth.ll --- a/llvm/test/Transforms/ConstraintElimination/large-system-growth.ll +++ b/llvm/test/Transforms/ConstraintElimination/large-system-growth.ll @@ -13,16 +13,16 @@ ; CHECK: bb28: ; CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds i8, i8* [[Y]], i64 [[X]] ; CHECK-NEXT: [[TMP30:%.*]] = icmp ult i8* [[TMP29]], [[Z]] -; CHECK-NEXT: br i1 true, label [[EARLY_EXIT]], label [[BB32:%.*]] +; CHECK-NEXT: br i1 [[TMP30]], label [[EARLY_EXIT]], label [[BB32:%.*]] ; CHECK: bb32: ; CHECK-NEXT: [[TMP33:%.*]] = icmp ult i8* [[TMP29]], [[Z]] -; CHECK-NEXT: br i1 true, label [[BB35:%.*]], label [[EARLY_EXIT]] +; CHECK-NEXT: br i1 [[TMP33]], label [[BB35:%.*]], label [[EARLY_EXIT]] ; CHECK: bb35: ; CHECK-NEXT: [[TMP36:%.*]] = icmp ult i8* [[Y]], [[Z]] -; CHECK-NEXT: br i1 true, label [[EARLY_EXIT]], label [[BB38:%.*]] +; CHECK-NEXT: br i1 [[TMP36]], label [[EARLY_EXIT]], label [[BB38:%.*]] ; CHECK: bb38: ; CHECK-NEXT: [[TMP41:%.*]] = icmp ult i8* [[Y]], [[Z]] -; CHECK-NEXT: br i1 true, label [[EARLY_EXIT]], label [[BB43:%.*]] +; CHECK-NEXT: br i1 false, label [[EARLY_EXIT]], label [[BB43:%.*]] ; CHECK: bb43: ; CHECK-NEXT: [[TMP47:%.*]] = getelementptr inbounds i8, i8* [[W:%.*]], i64 [[X]] ; CHECK-NEXT: [[TMP48:%.*]] = icmp ult i8* [[TMP47]], [[Y]] @@ -30,10 +30,10 @@ ; CHECK: bb50: ; CHECK-NEXT: [[TMP52:%.*]] = getelementptr inbounds i8, i8* [[W]], i64 [[X]] ; CHECK-NEXT: [[TMP53:%.*]] = icmp ult i8* [[TMP52]], [[Y]] -; CHECK-NEXT: br i1 true, label [[EARLY_EXIT]], label [[BB55:%.*]] +; CHECK-NEXT: br i1 [[TMP53]], label [[EARLY_EXIT]], label [[BB55:%.*]] ; CHECK: bb55: ; CHECK-NEXT: [[TMP57:%.*]] = icmp ult i8* [[W]], [[Y]] -; CHECK-NEXT: br i1 true, label [[BB59:%.*]], label [[EARLY_EXIT]] +; CHECK-NEXT: br i1 [[TMP57]], label [[BB59:%.*]], label [[EARLY_EXIT]] ; CHECK: bb59: ; CHECK-NEXT: [[TMP60:%.*]] = icmp ult i8* [[W]], [[Y]] ; CHECK-NEXT: call void @use(i1 true) diff --git a/llvm/test/Transforms/ConstraintElimination/loops-bottom-tested-pointer-cmps.ll b/llvm/test/Transforms/ConstraintElimination/loops-bottom-tested-pointer-cmps.ll --- a/llvm/test/Transforms/ConstraintElimination/loops-bottom-tested-pointer-cmps.ll +++ b/llvm/test/Transforms/ConstraintElimination/loops-bottom-tested-pointer-cmps.ll @@ -94,7 +94,7 @@ ; CHECK-NEXT: [[PTR_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[IV_1]] ; CHECK-NEXT: [[CMP_PTR_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV_1]] ; CHECK-NEXT: [[CMP_PTR_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV_1]] -; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_PTR_IV_1_UPPER]] +; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_PTR_IV_1_LOWER]], [[CMP_PTR_IV_1_UPPER]] ; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]] ; CHECK: loop.latch: ; CHECK-NEXT: store i8 0, i8* [[PTR_IV]], align 4 @@ -173,7 +173,7 @@ ; CHECK-NEXT: [[PTR_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[IV_1]] ; CHECK-NEXT: [[CMP_PTR_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV_1]] ; CHECK-NEXT: [[CMP_PTR_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV_1]] -; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_PTR_IV_1_UPPER]] +; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_PTR_IV_1_LOWER]], [[CMP_PTR_IV_1_UPPER]] ; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]] ; CHECK: loop.latch: ; CHECK-NEXT: store i8 0, i8* [[PTR_IV]], align 4 diff --git a/llvm/test/Transforms/ConstraintElimination/loops-header-tested-pointer-cmps.ll b/llvm/test/Transforms/ConstraintElimination/loops-header-tested-pointer-cmps.ll --- a/llvm/test/Transforms/ConstraintElimination/loops-header-tested-pointer-cmps.ll +++ b/llvm/test/Transforms/ConstraintElimination/loops-header-tested-pointer-cmps.ll @@ -21,7 +21,7 @@ ; CHECK-NEXT: [[SRC_IV:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[IV]] ; CHECK-NEXT: [[CMP_IV_START:%.*]] = icmp ult i8* [[SRC_IV]], [[LOWER]] ; CHECK-NEXT: [[CMP_IV_END:%.*]] = icmp uge i8* [[SRC_IV]], [[UPPER]] -; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_IV_START]], false +; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_IV_START]], [[CMP_IV_END]] ; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]] ; CHECK: loop.body.1: ; CHECK-NEXT: [[PTR_SRC_IV:%.*]] = bitcast i8* [[SRC_IV]] to i32* @@ -30,7 +30,7 @@ ; CHECK-NEXT: [[SRC_IV_1:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_1]] ; CHECK-NEXT: [[CMP_IV_1_START:%.*]] = icmp ult i8* [[SRC_IV_1]], [[LOWER]] ; CHECK-NEXT: [[CMP_IV_1_END:%.*]] = icmp uge i8* [[SRC_IV_1]], [[UPPER]] -; CHECK-NEXT: [[OR_2:%.*]] = or i1 false, false +; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[CMP_IV_1_START]], [[CMP_IV_1_END]] ; CHECK-NEXT: br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]] ; CHECK: loop.body.2: ; CHECK-NEXT: [[PTR_SRC_IV_1:%.*]] = bitcast i8* [[SRC_IV_1]] to i32* @@ -39,7 +39,7 @@ ; CHECK-NEXT: [[SRC_IV_2:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_2]] ; CHECK-NEXT: [[CMP_IV_2_START:%.*]] = icmp ult i8* [[SRC_IV_2]], [[LOWER]] ; CHECK-NEXT: [[CMP_IV_2_END:%.*]] = icmp uge i8* [[SRC_IV_2]], [[UPPER]] -; CHECK-NEXT: [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]] +; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[CMP_IV_2_START]], [[CMP_IV_2_END]] ; CHECK-NEXT: br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]] ; CHECK: loop.latch: ; CHECK-NEXT: [[PTR_SRC_IV_2:%.*]] = bitcast i8* [[SRC_IV_2]] to i32* @@ -130,14 +130,14 @@ ; CHECK-NEXT: [[SRC_IV_1:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_1]] ; CHECK-NEXT: [[CMP_IV_1_START:%.*]] = icmp ult i8* [[SRC_IV_1]], [[LOWER]] ; CHECK-NEXT: [[CMP_IV_1_END:%.*]] = icmp uge i8* [[SRC_IV_1]], [[UPPER]] -; CHECK-NEXT: [[OR_2:%.*]] = or i1 false, [[CMP_IV_1_END]] +; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[CMP_IV_1_START]], [[CMP_IV_1_END]] ; CHECK-NEXT: br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]] ; CHECK: loop.body.2: ; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2 ; CHECK-NEXT: [[SRC_IV_2:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_2]] ; CHECK-NEXT: [[CMP_IV_2_START:%.*]] = icmp ult i8* [[SRC_IV_2]], [[LOWER]] ; CHECK-NEXT: [[CMP_IV_2_END:%.*]] = icmp uge i8* [[SRC_IV_2]], [[UPPER]] -; CHECK-NEXT: [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]] +; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[CMP_IV_2_START]], [[CMP_IV_2_END]] ; CHECK-NEXT: br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]] ; CHECK: loop.latch: ; CHECK-NEXT: [[PTR:%.*]] = bitcast i8* [[SRC_IV]] to i32* @@ -226,14 +226,14 @@ ; CHECK-NEXT: [[SRC_IV_1:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_1]] ; CHECK-NEXT: [[CMP_IV_1_START:%.*]] = icmp ult i8* [[SRC_IV_1]], [[LOWER]] ; CHECK-NEXT: [[CMP_IV_1_END:%.*]] = icmp uge i8* [[SRC_IV_1]], [[UPPER]] -; CHECK-NEXT: [[OR_2:%.*]] = or i1 false, [[CMP_IV_1_END]] +; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[CMP_IV_1_START]], [[CMP_IV_1_END]] ; CHECK-NEXT: br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]] ; CHECK: loop.body.2: ; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2 ; CHECK-NEXT: [[SRC_IV_2:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_2]] ; CHECK-NEXT: [[CMP_IV_2_START:%.*]] = icmp ult i8* [[SRC_IV_2]], [[LOWER]] ; CHECK-NEXT: [[CMP_IV_2_END:%.*]] = icmp uge i8* [[SRC_IV_2]], [[UPPER]] -; CHECK-NEXT: [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]] +; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[CMP_IV_2_START]], [[CMP_IV_2_END]] ; CHECK-NEXT: br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]] ; CHECK: loop.latch: ; CHECK-NEXT: [[PTR:%.*]] = bitcast i8* [[SRC_IV]] to i32* @@ -329,7 +329,7 @@ ; CHECK-NEXT: [[SRC_IV_2:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_2]] ; CHECK-NEXT: [[CMP_IV_2_START:%.*]] = icmp ult i8* [[SRC_IV_2]], [[LOWER]] ; CHECK-NEXT: [[CMP_IV_2_END:%.*]] = icmp uge i8* [[SRC_IV_2]], [[UPPER]] -; CHECK-NEXT: [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]] +; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[CMP_IV_2_START]], [[CMP_IV_2_END]] ; CHECK-NEXT: br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]] ; CHECK: loop.latch: ; CHECK-NEXT: [[PTR:%.*]] = bitcast i8* [[SRC_IV]] to i32* @@ -418,7 +418,7 @@ ; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[ADD]] ; CHECK-NEXT: [[CMP_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV_1]] ; CHECK-NEXT: [[CMP_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV_1]] -; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_1_UPPER]] +; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_IV_1_LOWER]], [[CMP_IV_1_UPPER]] ; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] ; CHECK: for.latch: ; CHECK-NEXT: store i8 0, i8* [[GEP_IV]], align 4 @@ -502,7 +502,7 @@ ; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[ADD]] ; CHECK-NEXT: [[CMP_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV_1]] ; CHECK-NEXT: [[CMP_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV_1]] -; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_1_UPPER]] +; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_IV_1_LOWER]], [[CMP_IV_1_UPPER]] ; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] ; CHECK: for.latch: ; CHECK-NEXT: store i8 0, i8* [[GEP_IV]], align 4 @@ -588,7 +588,7 @@ ; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[ADD]] ; CHECK-NEXT: [[CMP_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV_1]] ; CHECK-NEXT: [[CMP_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV_1]] -; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_1_UPPER]] +; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_IV_1_LOWER]], [[CMP_IV_1_UPPER]] ; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] ; CHECK: for.latch: ; CHECK-NEXT: store i8 0, i8* [[GEP_IV]], align 4