Introduce a new LoopInfo utility function makeLoopInvariant, which
authorDan Gohman <gohman@apple.com>
Tue, 14 Jul 2009 01:06:29 +0000 (01:06 +0000)
committerDan Gohman <gohman@apple.com>
Tue, 14 Jul 2009 01:06:29 +0000 (01:06 +0000)
works similar to isLoopInvariant, except that it will do trivial
hoisting to try to make the value loop invariant if it isn't already.
This makes it easier for transformation passes to clear trivial
instructions out of the way (the regular LICM pass doesn't run
until relatively late). This is code factored out of LoopSimplify
and other places.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75578 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/LoopInfo.h
lib/Analysis/LoopInfo.cpp

index 2bed04b3b290cfaca931a39ea9bd3940b4805b97..90afc01da066a44c416879b421263829f34a0488 100644 (file)
@@ -476,6 +476,33 @@ public:
   ///
   bool isLoopInvariant(Value *V) const;
 
+  /// isLoopInvariant - Return true if the specified instruction is
+  /// loop-invariant.
+  ///
+  bool isLoopInvariant(Instruction *I) const;
+
+  /// makeLoopInvariant - If the given value is an instruciton inside of the
+  /// loop and it can be hoisted, do so to make it trivially loop-invariant.
+  /// Return true if the value after any hoisting is loop invariant. This
+  /// function can be used as a slightly more aggressive replacement for
+  /// isLoopInvariant.
+  ///
+  /// If InsertPt is specified, it is the point to hoist instructions to.
+  /// If null, the terminator of the loop preheader is used.
+  ///
+  bool makeLoopInvariant(Value *V, Instruction *InsertPt = 0) const;
+
+  /// makeLoopInvariant - If the given instruction is inside of the
+  /// loop and it can be hoisted, do so to make it trivially loop-invariant.
+  /// Return true if the instruction after any hoisting is loop invariant. This
+  /// function can be used as a slightly more aggressive replacement for
+  /// isLoopInvariant.
+  ///
+  /// If InsertPt is specified, it is the point to hoist instructions to.
+  /// If null, the terminator of the loop preheader is used.
+  ///
+  bool makeLoopInvariant(Instruction *I, Instruction *InsertPt = 0) const;
+
   /// getCanonicalInductionVariable - Check to see if the loop has a canonical
   /// induction variable: an integer recurrence that starts at 0 and increments
   /// by one each time through the loop.  If so, return the phi node that
index db5ce2118cb5c7979d9c8038bd9c79f603c8bf31..fb8027c14fdca8918636f77f87196c1aa24e431c 100644 (file)
@@ -38,10 +38,71 @@ X("loops", "Natural Loop Information", true, true);
 ///
 bool Loop::isLoopInvariant(Value *V) const {
   if (Instruction *I = dyn_cast<Instruction>(V))
-    return !contains(I->getParent());
+    return isLoopInvariant(I);
   return true;  // All non-instructions are loop invariant
 }
 
+/// isLoopInvariant - Return true if the specified instruction is
+/// loop-invariant.
+///
+bool Loop::isLoopInvariant(Instruction *I) const {
+  return !contains(I->getParent());
+}
+
+/// makeLoopInvariant - If the given value is an instruciton inside of the
+/// loop and it can be hoisted, do so to make it trivially loop-invariant.
+/// Return true if the value after any hoisting is loop invariant. This
+/// function can be used as a slightly more aggressive replacement for
+/// isLoopInvariant.
+///
+/// If InsertPt is specified, it is the point to hoist instructions to.
+/// If null, the terminator of the loop preheader is used.
+///
+bool Loop::makeLoopInvariant(Value *V, Instruction *InsertPt) const {
+  if (Instruction *I = dyn_cast<Instruction>(V))
+    return makeLoopInvariant(I);
+  return true;  // All non-instructions are loop-invariant.
+}
+
+/// makeLoopInvariant - If the given instruction is inside of the
+/// loop and it can be hoisted, do so to make it trivially loop-invariant.
+/// Return true if the instruction after any hoisting is loop invariant. This
+/// function can be used as a slightly more aggressive replacement for
+/// isLoopInvariant.
+///
+/// If InsertPt is specified, it is the point to hoist instructions to.
+/// If null, the terminator of the loop preheader is used.
+///
+bool Loop::makeLoopInvariant(Instruction *I, Instruction *InsertPt) const {
+  // Test if the value is already loop-invariant.
+  if (isLoopInvariant(I))
+    return true;
+  // Don't hoist instructions with side-effects.
+  if (I->isTrapping())
+    return false;
+  // Don't hoist PHI nodes.
+  if (isa<PHINode>(I))
+    return false;
+  // Don't hoist allocation instructions.
+  if (isa<AllocationInst>(I))
+    return false;
+  // Determine the insertion point, unless one was given.
+  if (!InsertPt) {
+    BasicBlock *Preheader = getLoopPreheader();
+    // Without a preheader, hoisting is not feasible.
+    if (!Preheader)
+      return false;
+    InsertPt = Preheader->getTerminator();
+  }
+  // Don't hoist instructions with loop-variant operands.
+  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
+    if (!makeLoopInvariant(I->getOperand(i), InsertPt))
+      return false;
+  // Hoist.
+  I->moveBefore(InsertPt);
+  return true;
+}
+
 /// getCanonicalInductionVariable - Check to see if the loop has a canonical
 /// induction variable: an integer recurrence that starts at 0 and increments
 /// by one each time through the loop.  If so, return the phi node that