[ConstraintElimination] Add initial signed support.
authorFlorian Hahn <flo@fhahn.com>
Fri, 4 Feb 2022 14:02:48 +0000 (14:02 +0000)
committerFlorian Hahn <flo@fhahn.com>
Fri, 4 Feb 2022 14:02:48 +0000 (14:02 +0000)
This patch adds initial support for signed conditions. To do so,
ConstraintElimination maintains two separate systems, one with facts
from signed and one for unsigned conditions.

To start with this means information from signed and unsigned conditions
is kept completely separate. When it is safe to do so, information from
signed conditions may be also transferred to the unsigned system and
vice versa. That's left for follow-ups.

In the initial version, de-composition of signed values just handles
constants and otherwise just uses the value, without trying to
decompose the operation. Again this can be extended in follow-up
changes.

The main benefit of this limited signed support is proving >=s 0
pre-conditions added in D118799. But even this initial version also
fixes PR53273.

Depends on D118799.

Reviewed By: reames

Differential Revision: https://reviews.llvm.org/D118806

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
llvm/test/Transforms/ConstraintElimination/gep-arithmetic.ll
llvm/test/Transforms/ConstraintElimination/i128.ll
llvm/test/Transforms/ConstraintElimination/loops-header-tested-base.ll
llvm/test/Transforms/ConstraintElimination/mixed-signed-unsigned-predicates.ll
llvm/test/Transforms/ConstraintElimination/sge.ll
llvm/test/Transforms/ConstraintElimination/zext.ll

index d27a987..404dd4c 100644 (file)
@@ -42,9 +42,41 @@ DEBUG_COUNTER(EliminatedCounter, "conds-eliminated",
               "Controls which conditions are eliminated");
 
 static int64_t MaxConstraintValue = std::numeric_limits<int64_t>::max();
+static int64_t MinSignedConstraintValue = std::numeric_limits<int64_t>::min();
 
 namespace {
 
+/// Wrapper encapsulating separate constraint systems and corresponding value
+/// mappings for both unsigned and signed information. Facts are added to and
+/// conditions are checked against the corresponding system depending on the
+/// signed-ness of their predicates. While the information is kept separate
+/// based on signed-ness, certain conditions can be transferred between the two
+/// systems.
+class ConstraintInfo {
+  DenseMap<Value *, unsigned> UnsignedValue2Index;
+  DenseMap<Value *, unsigned> SignedValue2Index;
+
+  ConstraintSystem UnsignedCS;
+  ConstraintSystem SignedCS;
+
+public:
+  DenseMap<Value *, unsigned> &getValue2Index(bool Signed) {
+    return Signed ? SignedValue2Index : UnsignedValue2Index;
+  }
+  const DenseMap<Value *, unsigned> &getValue2Index(bool Signed) const {
+    return Signed ? SignedValue2Index : UnsignedValue2Index;
+  }
+
+  ConstraintSystem &getCS(bool Signed) {
+    return Signed ? SignedCS : UnsignedCS;
+  }
+  const ConstraintSystem &getCS(bool Signed) const {
+    return Signed ? SignedCS : UnsignedCS;
+  }
+
+  void popLastConstraint(bool Signed) { getCS(Signed).popLastConstraint(); }
+};
+
 /// Struct to express a pre-condition of the form %Op0 Pred %Op1.
 struct PreconditionTy {
   CmpInst::Predicate Pred;
@@ -58,8 +90,10 @@ struct PreconditionTy {
 struct ConstraintTy {
   SmallVector<int64_t, 8> Coefficients;
 
-  ConstraintTy(SmallVector<int64_t, 8> Coefficients)
-      : Coefficients(Coefficients) {}
+  bool IsSigned;
+
+  ConstraintTy(SmallVector<int64_t, 8> Coefficients, bool IsSigned)
+      : Coefficients(Coefficients), IsSigned(IsSigned) {}
 
   unsigned size() const { return Coefficients.size(); }
 };
@@ -104,13 +138,14 @@ struct ConstraintListTy {
 
   /// 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<Value *, unsigned> &Value2Index) const;
+  bool isValid(const ConstraintInfo &Info) const;
+
   /// Returns true if there is exactly one constraint in the list and isValid is
   /// also true.
-  bool isValidSingle(const ConstraintSystem &CS,
-                     DenseMap<Value *, unsigned> &Value2Index) const {
-    return size() == 1 && isValid(CS, Value2Index);
+  bool isValidSingle(const ConstraintInfo &Info) const {
+    if (size() != 1)
+      return false;
+    return isValid(Info);
   }
 };
 
@@ -121,7 +156,21 @@ struct ConstraintListTy {
 // must be nullptr. If the expression cannot be decomposed, returns an empty
 // vector.
 static SmallVector<std::pair<int64_t, Value *>, 4>
-decompose(Value *V, SmallVector<PreconditionTy, 4> &Preconditions) {
+decompose(Value *V, SmallVector<PreconditionTy, 4> &Preconditions,
+          bool IsSigned) {
+
+  // Decompose \p V used with a signed predicate.
+  if (IsSigned) {
+    if (auto *CI = dyn_cast<ConstantInt>(V)) {
+      const APInt &Val = CI->getValue();
+      if (Val.sle(MinSignedConstraintValue) || Val.sge(MaxConstraintValue))
+        return {};
+      return {{CI->getSExtValue(), nullptr}};
+    }
+
+    return {{0, nullptr}, {1, V}};
+  }
+
   if (auto *CI = dyn_cast<ConstantInt>(V)) {
     if (CI->isNegative() || CI->uge(MaxConstraintValue))
       return {};
@@ -216,7 +265,8 @@ getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
     return Insert.first->second;
   };
 
-  if (Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE)
+  if (Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE ||
+      Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE)
     return getConstraint(CmpInst::getSwappedPredicate(Pred), Op1, Op0,
                          Value2Index, NewIndices);
 
@@ -238,13 +288,15 @@ getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
   }
 
   // Only ULE and ULT predicates are supported at the moment.
-  if (Pred != CmpInst::ICMP_ULE && Pred != CmpInst::ICMP_ULT)
+  if (Pred != CmpInst::ICMP_ULE && Pred != CmpInst::ICMP_ULT &&
+      Pred != CmpInst::ICMP_SLE && Pred != CmpInst::ICMP_SLT)
     return {};
 
-  auto ADec =
-      decompose(Op0->stripPointerCastsSameRepresentation(), Preconditions);
-  auto BDec =
-      decompose(Op1->stripPointerCastsSameRepresentation(), Preconditions);
+  bool IsSigned = CmpInst::isSigned(Pred);
+  auto ADec = decompose(Op0->stripPointerCastsSameRepresentation(),
+                        Preconditions, IsSigned);
+  auto BDec = decompose(Op1->stripPointerCastsSameRepresentation(),
+                        Preconditions, IsSigned);
   // Skip if decomposing either of the values failed.
   if (ADec.empty() || BDec.empty())
     return {};
@@ -275,25 +327,28 @@ getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
   for (const auto &KV : VariablesB)
     R[GetOrAddIndex(KV.second)] -= KV.first;
 
-  R[0] = Offset1 + Offset2 + (Pred == CmpInst::ICMP_ULT ? -1 : 0);
-  return {{R}, Preconditions};
+  R[0] = Offset1 + Offset2 +
+         (Pred == (IsSigned ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT) ? -1 : 0);
+  return {{{R, IsSigned}}, Preconditions};
 }
 
-static ConstraintListTy getConstraint(CmpInst *Cmp,
-                                      DenseMap<Value *, unsigned> &Value2Index,
+static ConstraintListTy getConstraint(CmpInst *Cmp, ConstraintInfo &Info,
                                       DenseMap<Value *, unsigned> &NewIndices) {
-  return getConstraint(Cmp->getPredicate(), Cmp->getOperand(0),
-                       Cmp->getOperand(1), Value2Index, NewIndices);
+  return getConstraint(
+      Cmp->getPredicate(), Cmp->getOperand(0), Cmp->getOperand(1),
+      Info.getValue2Index(CmpInst::isSigned(Cmp->getPredicate())), NewIndices);
 }
 
-bool ConstraintListTy::isValid(const ConstraintSystem &CS,
-                               DenseMap<Value *, unsigned> &Value2Index) const {
-  return all_of(Preconditions, [&CS, &Value2Index](const PreconditionTy &C) {
+bool ConstraintListTy::isValid(const ConstraintInfo &Info) const {
+  return all_of(Preconditions, [&Info](const PreconditionTy &C) {
     DenseMap<Value *, unsigned> NewIndices;
-    auto R = getConstraint(C.Pred, C.Op0, C.Op1, Value2Index, NewIndices);
+    auto R = getConstraint(C.Pred, C.Op0, C.Op1,
+                           Info.getValue2Index(CmpInst::isSigned(C.Pred)),
+                           NewIndices);
     // TODO: properly check NewIndices.
     return NewIndices.empty() && R.Preconditions.empty() && R.size() == 1 &&
-           CS.isConditionImplied(R.get(0).Coefficients);
+           Info.getCS(CmpInst::isSigned(C.Pred))
+               .isConditionImplied(R.get(0).Coefficients);
   });
 }
 
@@ -321,11 +376,14 @@ struct ConstraintOrBlock {
 struct StackEntry {
   unsigned NumIn;
   unsigned NumOut;
-  CmpInst *Condition;
+  Instruction *Condition;
   bool IsNot;
+  bool IsSigned = false;
 
-  StackEntry(unsigned NumIn, unsigned NumOut, CmpInst *Condition, bool IsNot)
-      : NumIn(NumIn), NumOut(NumOut), Condition(Condition), IsNot(IsNot) {}
+  StackEntry(unsigned NumIn, unsigned NumOut, Instruction *Condition,
+             bool IsNot, bool IsSigned)
+      : NumIn(NumIn), NumOut(NumOut), Condition(Condition), IsNot(IsNot),
+        IsSigned(IsSigned) {}
 };
 } // namespace
 
@@ -345,7 +403,8 @@ static void dumpWithNames(ConstraintTy &C,
 static bool eliminateConstraints(Function &F, DominatorTree &DT) {
   bool Changed = false;
   DT.updateDFSNumbers();
-  ConstraintSystem CS;
+
+  ConstraintInfo Info;
 
   SmallVector<ConstraintOrBlock, 64> WorkList;
 
@@ -447,7 +506,6 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
 
   // Finally, process ordered worklist and eliminate implied conditions.
   SmallVector<StackEntry, 16> DFSInStack;
-  DenseMap<Value *, unsigned> Value2Index;
   for (ConstraintOrBlock &CB : WorkList) {
     // First, pop entries from the stack that are out-of-scope for CB. Remove
     // the corresponding entry from the constraint system.
@@ -462,7 +520,7 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
       LLVM_DEBUG(dbgs() << "Removing " << *E.Condition << " " << E.IsNot
                         << "\n");
       DFSInStack.pop_back();
-      CS.popLastConstraint();
+      Info.popLastConstraint(E.IsSigned);
     }
 
     LLVM_DEBUG({
@@ -483,12 +541,12 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
           continue;
 
         DenseMap<Value *, unsigned> NewIndices;
-        auto R = getConstraint(Cmp, Value2Index, NewIndices);
-
-        if (!R.isValidSingle(CS, Value2Index) || R.needsNewIndices(NewIndices))
+        auto R = getConstraint(Cmp, Info, NewIndices);
+        if (!R.isValidSingle(Info) || R.needsNewIndices(NewIndices))
           continue;
 
-        if (CS.isConditionImplied(R.get(0).Coefficients)) {
+        auto &CSToUse = Info.getCS(R.get(0).IsSigned);
+        if (CSToUse.isConditionImplied(R.get(0).Coefficients)) {
           if (!DebugCounter::shouldExecute(EliminatedCounter))
             continue;
 
@@ -508,7 +566,7 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
           NumCondsRemoved++;
           Changed = true;
         }
-        if (CS.isConditionImplied(
+        if (CSToUse.isConditionImplied(
                 ConstraintSystem::negate(R.get(0).Coefficients))) {
           if (!DebugCounter::shouldExecute(EliminatedCounter))
             continue;
@@ -547,31 +605,45 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
     // Otherwise, add the condition to the system and stack, if we can transform
     // it into a constraint.
     DenseMap<Value *, unsigned> NewIndices;
-    auto R = getConstraint(CB.Condition, Value2Index, NewIndices);
-    if (!R.isValid(CS, Value2Index))
+    auto R = getConstraint(CB.Condition, Info, NewIndices);
+    if (!R.isValid(Info))
       continue;
 
     for (auto &KV : NewIndices)
-      Value2Index.insert(KV);
+      Info.getValue2Index(CmpInst::isSigned(CB.Condition->getPredicate()))
+          .insert(KV);
 
     LLVM_DEBUG(dbgs() << "Adding " << *CB.Condition << " " << CB.Not << "\n");
     bool Added = false;
-    for (auto &C : R.Constraints) {
-      auto Coeffs = C.Coefficients;
+    for (auto &E : R.Constraints) {
+      auto &CSToUse = Info.getCS(E.IsSigned);
+      if (E.Coefficients.empty())
+        continue;
+
       LLVM_DEBUG({
         dbgs() << "  constraint: ";
-        dumpWithNames(C, Value2Index);
+        dumpWithNames(E, Info.getValue2Index(E.IsSigned));
       });
-      Added |= CS.addVariableRowFill(Coeffs);
+
+      Added |= CSToUse.addVariableRowFill(E.Coefficients);
+
       // If R has been added to the system, queue it for removal once it goes
       // out-of-scope.
       if (Added)
-        DFSInStack.emplace_back(CB.NumIn, CB.NumOut, CB.Condition, CB.Not);
+        DFSInStack.emplace_back(CB.NumIn, CB.NumOut, CB.Condition, CB.Not,
+                                E.IsSigned);
     }
   }
 
-  assert(CS.size() == DFSInStack.size() &&
+#ifndef NDEBUG
+  unsigned SignedEntries =
+      count_if(DFSInStack, [](const StackEntry &E) { return E.IsSigned; });
+  assert(Info.getCS(false).size() == DFSInStack.size() - SignedEntries &&
          "updates to CS and DFSInStack are out of sync");
+  assert(Info.getCS(true).size() == SignedEntries &&
+         "updates to CS and DFSInStack are out of sync");
+#endif
+
   return Changed;
 }
 
index f66c1e9..c490f72 100644 (file)
@@ -259,7 +259,7 @@ define i4 @ptr_N_signed_positive_explicit_check_constant_step(i8* %src, i8* %low
 ; 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, [[CMP_STEP_END]]
+; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret i4 3
@@ -374,7 +374,7 @@ define i4 @ptr_N_and_step_signed_positive_explicit_check_constant_step(i8* %src,
 ; 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, [[CMP_STEP_END]]
+; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret i4 3
index bb5bc51..8a4b9d8 100644 (file)
@@ -35,3 +35,37 @@ bb1:
 bb2:
   ret void
 }
+
+
+define void @test_signed_too_large(i128 %x) {
+; CHECK-LABEL: @test_signed_too_large(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sle i128 [[X:%.*]], 12345678901234123123123
+; CHECK-NEXT:    br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i128 [[X]], -12345678901234123123123
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    [[C_3:%.*]] = icmp sge i128 [[X]], -12345678901234123123123
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    [[C_4:%.*]] = icmp sge i128 [[X]], -12345678901234123123123
+; CHECK-NEXT:    call void @use(i1 [[C_4]])
+; CHECK-NEXT:    ret void
+; CHECK:       bb2:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %c.1 = icmp sle i128 %x, 12345678901234123123123
+  br i1 %c.1, label %bb1, label %bb2
+
+bb1:
+  %c.2 = icmp slt i128 %x, -12345678901234123123123
+  call void @use(i1 %c.2)
+  %c.3 = icmp sge i128 %x, -12345678901234123123123
+  call void @use(i1 %c.3)
+  %c.4 = icmp sge i128 %x, -12345678901234123123123
+  call void @use(i1 %c.4)
+  ret void
+
+bb2:
+  ret void
+}
index dc09d99..24f6b1e 100644 (file)
@@ -13,9 +13,9 @@ define void @loop_phi_pos_start_value(i32 %y, i1 %c, i32 %n) {
 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    [[F_1:%.*]] = icmp sle i32 [[X]], [[N]]
-; CHECK-NEXT:    call void @use(i1 [[F_1]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp sgt i32 [[X]], [[N]]
-; CHECK-NEXT:    call void @use(i1 [[T_1]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp sge i32 [[X]], 10
 ; CHECK-NEXT:    call void @use(i1 [[T_2]])
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sle i32 [[X]], 9
@@ -77,9 +77,9 @@ define void @loop_phi_neg_start_value(i32 %y, i1 %c, i32 %n) {
 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    [[F_1:%.*]] = icmp sle i32 [[X]], [[N]]
-; CHECK-NEXT:    call void @use(i1 [[F_1]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp sgt i32 [[X]], [[N]]
-; CHECK-NEXT:    call void @use(i1 [[T_1]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp sge i32 [[X]], -10
 ; CHECK-NEXT:    call void @use(i1 [[T_2]])
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sle i32 [[X]], 9
@@ -145,9 +145,9 @@ define void @loop_count_down(i32 %y, i1 %c, i32 %n) {
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp sgt i32 [[X]], [[N]]
 ; CHECK-NEXT:    call void @use(i1 [[T_1]])
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp sge i32 [[X]], 0
-; CHECK-NEXT:    call void @use(i1 [[T_2]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[T_3:%.*]] = icmp sge i32 [[X]], -1
-; CHECK-NEXT:    call void @use(i1 [[T_3]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sle i32 [[X]], 9
 ; CHECK-NEXT:    call void @use(i1 [[C_2]])
 ; CHECK-NEXT:    [[C_3:%.*]] = icmp sgt i32 [[X]], 9
index fc845ef..5965d3d 100644 (file)
@@ -261,7 +261,7 @@ define i1 @test_and_ule_sge(i32 %x, i32 %y, i32 %z, i32 %a) {
 ; CHECK-NEXT:    [[SC_2:%.*]] = icmp sle i32 [[X]], [[Y]]
 ; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], [[SC_2]]
 ; CHECK-NEXT:    [[SC_3:%.*]] = icmp sle i32 [[Y]], [[Z]]
-; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], [[SC_3]]
+; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], true
 ; CHECK-NEXT:    [[SC_4:%.*]] = icmp sle i32 [[X]], [[A]]
 ; CHECK-NEXT:    [[RES_8:%.*]] = xor i1 [[RES_7]], [[SC_4]]
 ; CHECK-NEXT:    ret i1 [[RES_8]]
index 9254191..347ed41 100644 (file)
@@ -10,7 +10,7 @@ define void @test_1_variable_constraint(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp sge i32 [[X]], [[Y]]
-; CHECK-NEXT:    call void @use(i1 [[T_1]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i32 [[X]], 10
 ; CHECK-NEXT:    call void @use(i1 [[C_2]])
 ; CHECK-NEXT:    [[C_3:%.*]] = icmp sge i32 [[Y]], [[X]]
@@ -20,9 +20,9 @@ define void @test_1_variable_constraint(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    ret void
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp sge i32 [[Y]], [[X]]
-; CHECK-NEXT:    call void @use(i1 [[T_2]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[F_1:%.*]] = icmp sge i32 [[X]], [[Y]]
-; CHECK-NEXT:    call void @use(i1 [[F_1]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[C_5:%.*]] = icmp sge i32 [[X]], 10
 ; CHECK-NEXT:    call void @use(i1 [[C_5]])
 ; CHECK-NEXT:    [[C_6:%.*]] = icmp sge i32 10, [[X]]
@@ -63,9 +63,9 @@ define void @test_1_constant_constraint(i32 %x) {
 ; CHECK-NEXT:    br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp sge i32 [[X]], 10
-; CHECK-NEXT:    call void @use(i1 [[T_1]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp sge i32 [[X]], 9
-; CHECK-NEXT:    call void @use(i1 [[T_2]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i32 [[X]], 11
 ; CHECK-NEXT:    call void @use(i1 [[C_2]])
 ; CHECK-NEXT:    [[C_4:%.*]] = icmp sge i32 10, [[X]]
@@ -73,11 +73,11 @@ define void @test_1_constant_constraint(i32 %x) {
 ; CHECK-NEXT:    ret void
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[T_3:%.*]] = icmp sge i32 11, [[X]]
-; CHECK-NEXT:    call void @use(i1 [[T_3]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[F_1:%.*]] = icmp sge i32 [[X]], 10
-; CHECK-NEXT:    call void @use(i1 [[F_1]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[F_1_1:%.*]] = icmp sge i32 [[X]], 10
-; CHECK-NEXT:    call void @use(i1 [[F_1_1]])
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    [[C_5:%.*]] = icmp sge i32 [[X]], 9
 ; CHECK-NEXT:    call void @use(i1 [[C_5]])
 ; CHECK-NEXT:    [[C_6:%.*]] = icmp sge i32 1, [[X]]
@@ -125,7 +125,7 @@ define i32 @test1(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[C_2]], label [[BB2:%.*]], label [[EXIT]]
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[C_3:%.*]] = icmp sge i32 [[X]], [[Z]]
-; CHECK-NEXT:    br i1 [[C_3]], label [[BB3:%.*]], label [[EXIT]]
+; CHECK-NEXT:    br i1 true, label [[BB3:%.*]], label [[EXIT]]
 ; CHECK:       bb3:
 ; CHECK-NEXT:    ret i32 10
 ; CHECK:       exit:
@@ -224,7 +224,7 @@ define i32 @test4(i32 %x, i32 %y, i32 %z) {
 ; CHECK-NEXT:    br i1 [[C_2]], label [[BB2:%.*]], label [[EXIT]]
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp sge i32 [[X]], [[Z]]
-; CHECK-NEXT:    call void @use(i1 [[T_1]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[U_1:%.*]] = icmp eq i32 [[X]], [[Z]]
 ; CHECK-NEXT:    call void @use(i1 [[U_1]])
 ; CHECK-NEXT:    ret i32 10
index 1b7b79b..3162149 100644 (file)
@@ -169,7 +169,7 @@ define i1 @sge_zext(i8 %x, i16 %y) {
 ; CHECK:       bb1:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp sge i16 [[X_EXT]], [[Y]]
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i16 [[X_EXT]], 10
-; CHECK-NEXT:    [[R_1:%.*]] = xor i1 [[T_1]], [[C_2]]
+; CHECK-NEXT:    [[R_1:%.*]] = xor i1 true, [[C_2]]
 ; CHECK-NEXT:    [[C_3:%.*]] = icmp sge i16 [[Y]], [[X_EXT]]
 ; CHECK-NEXT:    [[R_2:%.*]] = xor i1 [[R_1]], [[C_3]]
 ; CHECK-NEXT:    [[C_4:%.*]] = icmp sge i16 10, [[X_EXT]]
@@ -178,7 +178,7 @@ define i1 @sge_zext(i8 %x, i16 %y) {
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp sge i16 [[Y]], [[X_EXT]]
 ; CHECK-NEXT:    [[F_1:%.*]] = icmp sge i16 [[X_EXT]], [[Y]]
-; CHECK-NEXT:    [[R_4:%.*]] = xor i1 [[T_2]], [[F_1]]
+; CHECK-NEXT:    [[R_4:%.*]] = xor i1 true, false
 ; CHECK-NEXT:    [[C_5:%.*]] = icmp sge i16 [[X_EXT]], 10
 ; CHECK-NEXT:    [[R_5:%.*]] = xor i1 [[R_4]], [[C_5]]
 ; CHECK-NEXT:    [[C_6:%.*]] = icmp sge i16 10, [[X_EXT]]