xref: /llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (revision a78ce48c373572946a51228dda741681d1695d63)
1 //===-- ConstraintElimination.cpp - Eliminate conds using constraints. ----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Eliminate conditions based on constraints collected from dominating
10 // conditions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Transforms/Scalar/ConstraintElimination.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/ScopeExit.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/Statistic.h"
19 #include "llvm/Analysis/ConstraintSystem.h"
20 #include "llvm/Analysis/GlobalsModRef.h"
21 #include "llvm/Analysis/ValueTracking.h"
22 #include "llvm/IR/DataLayout.h"
23 #include "llvm/IR/Dominators.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/Instructions.h"
26 #include "llvm/IR/PatternMatch.h"
27 #include "llvm/InitializePasses.h"
28 #include "llvm/Pass.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/DebugCounter.h"
31 #include "llvm/Transforms/Scalar.h"
32 
33 #include <string>
34 
35 using namespace llvm;
36 using namespace PatternMatch;
37 
38 #define DEBUG_TYPE "constraint-elimination"
39 
40 STATISTIC(NumCondsRemoved, "Number of instructions removed");
41 DEBUG_COUNTER(EliminatedCounter, "conds-eliminated",
42               "Controls which conditions are eliminated");
43 
44 static int64_t MaxConstraintValue = std::numeric_limits<int64_t>::max();
45 
46 namespace {
47 struct ConstraintTy {
48   SmallVector<int64_t, 8> Coefficients;
49 
50   ConstraintTy(SmallVector<int64_t, 8> Coefficients)
51       : Coefficients(Coefficients) {}
52 
53   unsigned size() const { return Coefficients.size(); }
54 };
55 
56 /// Struct to manage a list of constraints.
57 struct ConstraintListTy {
58   SmallVector<ConstraintTy, 4> Constraints;
59 
60   ConstraintListTy() {}
61 
62   ConstraintListTy(const SmallVector<ConstraintTy, 4> &Constraints)
63       : Constraints(Constraints) {}
64 
65   void mergeIn(const ConstraintListTy &Other) {
66     append_range(Constraints, Other.Constraints);
67   }
68 
69   unsigned size() const { return Constraints.size(); }
70 
71   unsigned empty() const { return Constraints.empty(); }
72 
73   /// Returns true if any constraint has a non-zero coefficient for any of the
74   /// newly added indices. Zero coefficients for new indices are removed. If it
75   /// returns true, no new variable need to be added to the system.
76   bool needsNewIndices(const DenseMap<Value *, unsigned> &NewIndices) {
77     assert(size() == 1);
78     for (unsigned I = 0; I < NewIndices.size(); ++I) {
79       int64_t Last = get(0).Coefficients.pop_back_val();
80       if (Last != 0)
81         return true;
82     }
83     return false;
84   }
85 
86   ConstraintTy &get(unsigned I) { return Constraints[I]; }
87 };
88 
89 } // namespace
90 
91 // Decomposes \p V into a vector of pairs of the form { c, X } where c * X. The
92 // sum of the pairs equals \p V.  The first pair is the constant-factor and X
93 // must be nullptr. If the expression cannot be decomposed, returns an empty
94 // vector.
95 static SmallVector<std::pair<int64_t, Value *>, 4> decompose(Value *V) {
96   if (auto *CI = dyn_cast<ConstantInt>(V)) {
97     if (CI->isNegative() || CI->uge(MaxConstraintValue))
98       return {};
99     return {{CI->getSExtValue(), nullptr}};
100   }
101   auto *GEP = dyn_cast<GetElementPtrInst>(V);
102   if (GEP && GEP->getNumOperands() == 2 && GEP->isInBounds()) {
103     Value *Op0, *Op1;
104     ConstantInt *CI;
105 
106     // If the index is zero-extended, it is guaranteed to be positive.
107     if (match(GEP->getOperand(GEP->getNumOperands() - 1),
108               m_ZExt(m_Value(Op0)))) {
109       if (match(Op0, m_NUWShl(m_Value(Op1), m_ConstantInt(CI))))
110         return {{0, nullptr},
111                 {1, GEP->getPointerOperand()},
112                 {std::pow(int64_t(2), CI->getSExtValue()), Op1}};
113       if (match(Op0, m_NSWAdd(m_Value(Op1), m_ConstantInt(CI))))
114         return {{CI->getSExtValue(), nullptr},
115                 {1, GEP->getPointerOperand()},
116                 {1, Op1}};
117       return {{0, nullptr}, {1, GEP->getPointerOperand()}, {1, Op0}};
118     }
119 
120     if (match(GEP->getOperand(GEP->getNumOperands() - 1), m_ConstantInt(CI)) &&
121         !CI->isNegative())
122       return {{CI->getSExtValue(), nullptr}, {1, GEP->getPointerOperand()}};
123 
124     SmallVector<std::pair<int64_t, Value *>, 4> Result;
125     if (match(GEP->getOperand(GEP->getNumOperands() - 1),
126               m_NUWShl(m_Value(Op0), m_ConstantInt(CI))))
127       Result = {{0, nullptr},
128                 {1, GEP->getPointerOperand()},
129                 {std::pow(int64_t(2), CI->getSExtValue()), Op0}};
130     else if (match(GEP->getOperand(GEP->getNumOperands() - 1),
131                    m_NSWAdd(m_Value(Op0), m_ConstantInt(CI))))
132       Result = {{CI->getSExtValue(), nullptr},
133                 {1, GEP->getPointerOperand()},
134                 {1, Op0}};
135     else {
136       Op0 = GEP->getOperand(GEP->getNumOperands() - 1);
137       Result = {{0, nullptr}, {1, GEP->getPointerOperand()}, {1, Op0}};
138     }
139     return Result;
140   }
141 
142   Value *Op0;
143   if (match(V, m_ZExt(m_Value(Op0))))
144     V = Op0;
145 
146   Value *Op1;
147   ConstantInt *CI;
148   if (match(V, m_NUWAdd(m_Value(Op0), m_ConstantInt(CI))))
149     return {{CI->getSExtValue(), nullptr}, {1, Op0}};
150   if (match(V, m_NUWAdd(m_Value(Op0), m_Value(Op1))))
151     return {{0, nullptr}, {1, Op0}, {1, Op1}};
152 
153   if (match(V, m_NUWSub(m_Value(Op0), m_ConstantInt(CI))))
154     return {{-1 * CI->getSExtValue(), nullptr}, {1, Op0}};
155   if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1))))
156     return {{0, nullptr}, {1, Op0}, {-1, Op1}};
157 
158   return {{0, nullptr}, {1, V}};
159 }
160 
161 /// Turn a condition \p CmpI into a vector of constraints, using indices from \p
162 /// Value2Index. Additional indices for newly discovered values are added to \p
163 /// NewIndices.
164 static ConstraintListTy
165 getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
166               const DenseMap<Value *, unsigned> &Value2Index,
167               DenseMap<Value *, unsigned> &NewIndices) {
168   int64_t Offset1 = 0;
169   int64_t Offset2 = 0;
170 
171   // First try to look up \p V in Value2Index and NewIndices. Otherwise add a
172   // new entry to NewIndices.
173   auto GetOrAddIndex = [&Value2Index, &NewIndices](Value *V) -> unsigned {
174     auto V2I = Value2Index.find(V);
175     if (V2I != Value2Index.end())
176       return V2I->second;
177     auto NewI = NewIndices.find(V);
178     if (NewI != NewIndices.end())
179       return NewI->second;
180     auto Insert =
181         NewIndices.insert({V, Value2Index.size() + NewIndices.size() + 1});
182     return Insert.first->second;
183   };
184 
185   if (Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE)
186     return getConstraint(CmpInst::getSwappedPredicate(Pred), Op1, Op0,
187                          Value2Index, NewIndices);
188 
189   if (Pred == CmpInst::ICMP_EQ) {
190     auto A =
191         getConstraint(CmpInst::ICMP_UGE, Op0, Op1, Value2Index, NewIndices);
192     auto B =
193         getConstraint(CmpInst::ICMP_ULE, Op0, Op1, Value2Index, NewIndices);
194     A.mergeIn(B);
195     return A;
196   }
197 
198   if (Pred == CmpInst::ICMP_NE && match(Op1, m_Zero())) {
199     return getConstraint(CmpInst::ICMP_UGT, Op0, Op1, Value2Index, NewIndices);
200   }
201 
202   // Only ULE and ULT predicates are supported at the moment.
203   if (Pred != CmpInst::ICMP_ULE && Pred != CmpInst::ICMP_ULT)
204     return {};
205 
206   auto ADec = decompose(Op0->stripPointerCastsSameRepresentation());
207   auto BDec = decompose(Op1->stripPointerCastsSameRepresentation());
208   // Skip if decomposing either of the values failed.
209   if (ADec.empty() || BDec.empty())
210     return {};
211 
212   // Skip trivial constraints without any variables.
213   if (ADec.size() == 1 && BDec.size() == 1)
214     return {};
215 
216   Offset1 = ADec[0].first;
217   Offset2 = BDec[0].first;
218   Offset1 *= -1;
219 
220   // Create iterator ranges that skip the constant-factor.
221   auto VariablesA = llvm::drop_begin(ADec);
222   auto VariablesB = llvm::drop_begin(BDec);
223 
224   // Make sure all variables have entries in Value2Index or NewIndices.
225   for (const auto &KV :
226        concat<std::pair<int64_t, Value *>>(VariablesA, VariablesB))
227     GetOrAddIndex(KV.second);
228 
229   // Build result constraint, by first adding all coefficients from A and then
230   // subtracting all coefficients from B.
231   SmallVector<int64_t, 8> R(Value2Index.size() + NewIndices.size() + 1, 0);
232   for (const auto &KV : VariablesA)
233     R[GetOrAddIndex(KV.second)] += KV.first;
234 
235   for (const auto &KV : VariablesB)
236     R[GetOrAddIndex(KV.second)] -= KV.first;
237 
238   R[0] = Offset1 + Offset2 + (Pred == CmpInst::ICMP_ULT ? -1 : 0);
239   return {{R}};
240 }
241 
242 static ConstraintListTy
243 getConstraint(CmpInst *Cmp, const DenseMap<Value *, unsigned> &Value2Index,
244               DenseMap<Value *, unsigned> &NewIndices) {
245   return getConstraint(Cmp->getPredicate(), Cmp->getOperand(0),
246                        Cmp->getOperand(1), Value2Index, NewIndices);
247 }
248 
249 namespace {
250 /// Represents either a condition that holds on entry to a block or a basic
251 /// block, with their respective Dominator DFS in and out numbers.
252 struct ConstraintOrBlock {
253   unsigned NumIn;
254   unsigned NumOut;
255   bool IsBlock;
256   bool Not;
257   union {
258     BasicBlock *BB;
259     CmpInst *Condition;
260   };
261 
262   ConstraintOrBlock(DomTreeNode *DTN)
263       : NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()), IsBlock(true),
264         BB(DTN->getBlock()) {}
265   ConstraintOrBlock(DomTreeNode *DTN, CmpInst *Condition, bool Not)
266       : NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()), IsBlock(false),
267         Not(Not), Condition(Condition) {}
268 };
269 
270 struct StackEntry {
271   unsigned NumIn;
272   unsigned NumOut;
273   CmpInst *Condition;
274   bool IsNot;
275 
276   StackEntry(unsigned NumIn, unsigned NumOut, CmpInst *Condition, bool IsNot)
277       : NumIn(NumIn), NumOut(NumOut), Condition(Condition), IsNot(IsNot) {}
278 };
279 } // namespace
280 
281 #ifndef NDEBUG
282 static void dumpWithNames(ConstraintTy &C,
283                           DenseMap<Value *, unsigned> &Value2Index) {
284   SmallVector<std::string> Names(Value2Index.size(), "");
285   for (auto &KV : Value2Index) {
286     Names[KV.second - 1] = std::string("%") + KV.first->getName().str();
287   }
288   ConstraintSystem CS;
289   CS.addVariableRowFill(C.Coefficients);
290   CS.dump(Names);
291 }
292 #endif
293 
294 static bool eliminateConstraints(Function &F, DominatorTree &DT) {
295   bool Changed = false;
296   DT.updateDFSNumbers();
297   ConstraintSystem CS;
298 
299   SmallVector<ConstraintOrBlock, 64> WorkList;
300 
301   // First, collect conditions implied by branches and blocks with their
302   // Dominator DFS in and out numbers.
303   for (BasicBlock &BB : F) {
304     if (!DT.getNode(&BB))
305       continue;
306     WorkList.emplace_back(DT.getNode(&BB));
307 
308     // True as long as long as the current instruction is guaranteed to execute.
309     bool GuaranteedToExecute = true;
310     // Scan BB for assume calls.
311     // TODO: also use this scan to queue conditions to simplify, so we can
312     // interleave facts from assumes and conditions to simplify in a single
313     // basic block. And to skip another traversal of each basic block when
314     // simplifying.
315     for (Instruction &I : BB) {
316       Value *Cond;
317       // For now, just handle assumes with a single compare as condition.
318       if (match(&I, m_Intrinsic<Intrinsic::assume>(m_Value(Cond))) &&
319           isa<CmpInst>(Cond)) {
320         if (GuaranteedToExecute) {
321           // The assume is guaranteed to execute when BB is entered, hence Cond
322           // holds on entry to BB.
323           WorkList.emplace_back(DT.getNode(&BB), cast<CmpInst>(Cond), false);
324         } else {
325           // Otherwise the condition only holds in the successors.
326           for (BasicBlock *Succ : successors(&BB))
327             WorkList.emplace_back(DT.getNode(Succ), cast<CmpInst>(Cond), false);
328         }
329       }
330       GuaranteedToExecute &= isGuaranteedToTransferExecutionToSuccessor(&I);
331     }
332 
333     auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
334     if (!Br || !Br->isConditional())
335       continue;
336 
337     // Returns true if we can add a known condition from BB to its successor
338     // block Succ. Each predecessor of Succ can either be BB or be dominated by
339     // Succ (e.g. the case when adding a condition from a pre-header to a loop
340     // header).
341     auto CanAdd = [&BB, &DT](BasicBlock *Succ) {
342       return all_of(predecessors(Succ), [&BB, &DT, Succ](BasicBlock *Pred) {
343         return Pred == &BB || DT.dominates(Succ, Pred);
344       });
345     };
346     // If the condition is an OR of 2 compares and the false successor only has
347     // the current block as predecessor, queue both negated conditions for the
348     // false successor.
349     Value *Op0, *Op1;
350     if (match(Br->getCondition(), m_LogicalOr(m_Value(Op0), m_Value(Op1))) &&
351         match(Op0, m_Cmp()) && match(Op1, m_Cmp())) {
352       BasicBlock *FalseSuccessor = Br->getSuccessor(1);
353       if (CanAdd(FalseSuccessor)) {
354         WorkList.emplace_back(DT.getNode(FalseSuccessor), cast<CmpInst>(Op0),
355                               true);
356         WorkList.emplace_back(DT.getNode(FalseSuccessor), cast<CmpInst>(Op1),
357                               true);
358       }
359       continue;
360     }
361 
362     // If the condition is an AND of 2 compares and the true successor only has
363     // the current block as predecessor, queue both conditions for the true
364     // successor.
365     if (match(Br->getCondition(), m_LogicalAnd(m_Value(Op0), m_Value(Op1))) &&
366         match(Op0, m_Cmp()) && match(Op1, m_Cmp())) {
367       BasicBlock *TrueSuccessor = Br->getSuccessor(0);
368       if (CanAdd(TrueSuccessor)) {
369         WorkList.emplace_back(DT.getNode(TrueSuccessor), cast<CmpInst>(Op0),
370                               false);
371         WorkList.emplace_back(DT.getNode(TrueSuccessor), cast<CmpInst>(Op1),
372                               false);
373       }
374       continue;
375     }
376 
377     auto *CmpI = dyn_cast<CmpInst>(Br->getCondition());
378     if (!CmpI)
379       continue;
380     if (CanAdd(Br->getSuccessor(0)))
381       WorkList.emplace_back(DT.getNode(Br->getSuccessor(0)), CmpI, false);
382     if (CanAdd(Br->getSuccessor(1)))
383       WorkList.emplace_back(DT.getNode(Br->getSuccessor(1)), CmpI, true);
384   }
385 
386   // Next, sort worklist by dominance, so that dominating blocks and conditions
387   // come before blocks and conditions dominated by them. If a block and a
388   // condition have the same numbers, the condition comes before the block, as
389   // it holds on entry to the block.
390   sort(WorkList, [](const ConstraintOrBlock &A, const ConstraintOrBlock &B) {
391     return std::tie(A.NumIn, A.IsBlock) < std::tie(B.NumIn, B.IsBlock);
392   });
393 
394   // Finally, process ordered worklist and eliminate implied conditions.
395   SmallVector<StackEntry, 16> DFSInStack;
396   DenseMap<Value *, unsigned> Value2Index;
397   for (ConstraintOrBlock &CB : WorkList) {
398     // First, pop entries from the stack that are out-of-scope for CB. Remove
399     // the corresponding entry from the constraint system.
400     while (!DFSInStack.empty()) {
401       auto &E = DFSInStack.back();
402       LLVM_DEBUG(dbgs() << "Top of stack : " << E.NumIn << " " << E.NumOut
403                         << "\n");
404       LLVM_DEBUG(dbgs() << "CB: " << CB.NumIn << " " << CB.NumOut << "\n");
405       assert(E.NumIn <= CB.NumIn);
406       if (CB.NumOut <= E.NumOut)
407         break;
408       LLVM_DEBUG(dbgs() << "Removing " << *E.Condition << " " << E.IsNot
409                         << "\n");
410       DFSInStack.pop_back();
411       CS.popLastConstraint();
412     }
413 
414     LLVM_DEBUG({
415       dbgs() << "Processing ";
416       if (CB.IsBlock)
417         dbgs() << *CB.BB;
418       else
419         dbgs() << *CB.Condition;
420       dbgs() << "\n";
421     });
422 
423     // For a block, check if any CmpInsts become known based on the current set
424     // of constraints.
425     if (CB.IsBlock) {
426       for (Instruction &I : *CB.BB) {
427         auto *Cmp = dyn_cast<CmpInst>(&I);
428         if (!Cmp)
429           continue;
430 
431         DenseMap<Value *, unsigned> NewIndices;
432         auto R = getConstraint(Cmp, Value2Index, NewIndices);
433         if (R.size() != 1)
434           continue;
435 
436         if (R.needsNewIndices(NewIndices) || R.get(0).size() == 1)
437           continue;
438 
439         if (CS.isConditionImplied(R.get(0).Coefficients)) {
440           if (!DebugCounter::shouldExecute(EliminatedCounter))
441             continue;
442 
443           LLVM_DEBUG(dbgs() << "Condition " << *Cmp
444                             << " implied by dominating constraints\n");
445           LLVM_DEBUG({
446             for (auto &E : reverse(DFSInStack))
447               dbgs() << "   C " << *E.Condition << " " << E.IsNot << "\n";
448           });
449           Cmp->replaceUsesWithIf(
450               ConstantInt::getTrue(F.getParent()->getContext()), [](Use &U) {
451                 // Conditions in an assume trivially simplify to true. Skip uses
452                 // in assume calls to not destroy the available information.
453                 auto *II = dyn_cast<IntrinsicInst>(U.getUser());
454                 return !II || II->getIntrinsicID() != Intrinsic::assume;
455               });
456           NumCondsRemoved++;
457           Changed = true;
458         }
459         if (CS.isConditionImplied(
460                 ConstraintSystem::negate(R.get(0).Coefficients))) {
461           if (!DebugCounter::shouldExecute(EliminatedCounter))
462             continue;
463 
464           LLVM_DEBUG(dbgs() << "Condition !" << *Cmp
465                             << " implied by dominating constraints\n");
466           LLVM_DEBUG({
467             for (auto &E : reverse(DFSInStack))
468               dbgs() << "   C " << *E.Condition << " " << E.IsNot << "\n";
469           });
470           Cmp->replaceAllUsesWith(
471               ConstantInt::getFalse(F.getParent()->getContext()));
472           NumCondsRemoved++;
473           Changed = true;
474         }
475       }
476       continue;
477     }
478 
479     // Set up a function to restore the predicate at the end of the scope if it
480     // has been negated. Negate the predicate in-place, if required.
481     auto *CI = dyn_cast<CmpInst>(CB.Condition);
482     auto PredicateRestorer = make_scope_exit([CI, &CB]() {
483       if (CB.Not && CI)
484         CI->setPredicate(CI->getInversePredicate());
485     });
486     if (CB.Not) {
487       if (CI) {
488         CI->setPredicate(CI->getInversePredicate());
489       } else {
490         LLVM_DEBUG(dbgs() << "Can only negate compares so far.\n");
491         continue;
492       }
493     }
494 
495     // Otherwise, add the condition to the system and stack, if we can transform
496     // it into a constraint.
497     DenseMap<Value *, unsigned> NewIndices;
498     auto R = getConstraint(CB.Condition, Value2Index, NewIndices);
499     if (R.empty())
500       continue;
501 
502     for (auto &KV : NewIndices)
503       Value2Index.insert(KV);
504 
505     LLVM_DEBUG(dbgs() << "Adding " << *CB.Condition << " " << CB.Not << "\n");
506     bool Added = false;
507     for (auto &C : R.Constraints) {
508       auto Coeffs = C.Coefficients;
509       LLVM_DEBUG({
510         dbgs() << "  constraint: ";
511         dumpWithNames(C, Value2Index);
512       });
513       Added |= CS.addVariableRowFill(Coeffs);
514       // If R has been added to the system, queue it for removal once it goes
515       // out-of-scope.
516       if (Added)
517         DFSInStack.emplace_back(CB.NumIn, CB.NumOut, CB.Condition, CB.Not);
518     }
519   }
520 
521   assert(CS.size() == DFSInStack.size() &&
522          "updates to CS and DFSInStack are out of sync");
523   return Changed;
524 }
525 
526 PreservedAnalyses ConstraintEliminationPass::run(Function &F,
527                                                  FunctionAnalysisManager &AM) {
528   auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
529   if (!eliminateConstraints(F, DT))
530     return PreservedAnalyses::all();
531 
532   PreservedAnalyses PA;
533   PA.preserve<DominatorTreeAnalysis>();
534   PA.preserveSet<CFGAnalyses>();
535   return PA;
536 }
537 
538 namespace {
539 
540 class ConstraintElimination : public FunctionPass {
541 public:
542   static char ID;
543 
544   ConstraintElimination() : FunctionPass(ID) {
545     initializeConstraintEliminationPass(*PassRegistry::getPassRegistry());
546   }
547 
548   bool runOnFunction(Function &F) override {
549     auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
550     return eliminateConstraints(F, DT);
551   }
552 
553   void getAnalysisUsage(AnalysisUsage &AU) const override {
554     AU.setPreservesCFG();
555     AU.addRequired<DominatorTreeWrapperPass>();
556     AU.addPreserved<GlobalsAAWrapperPass>();
557     AU.addPreserved<DominatorTreeWrapperPass>();
558   }
559 };
560 
561 } // end anonymous namespace
562 
563 char ConstraintElimination::ID = 0;
564 
565 INITIALIZE_PASS_BEGIN(ConstraintElimination, "constraint-elimination",
566                       "Constraint Elimination", false, false)
567 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
568 INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass)
569 INITIALIZE_PASS_END(ConstraintElimination, "constraint-elimination",
570                     "Constraint Elimination", false, false)
571 
572 FunctionPass *llvm::createConstraintEliminationPass() {
573   return new ConstraintElimination();
574 }
575