[llvm-commits] [llvm] r119727 - in /llvm/trunk: include/llvm/Analysis/LoopInfo.h lib/Analysis/ScalarEvolution.cpp lib/Transforms/Scalar/LoopUnswitch.cpp lib/Transforms/Utils/LoopSimplify.cpp test/Transforms/LoopUnswitch/2010-11-18-LCSSA.ll

Duncan Sands baldrick at free.fr
Thu Nov 18 11:59:41 PST 2010


Author: baldrick
Date: Thu Nov 18 13:59:41 2010
New Revision: 119727

URL: http://llvm.org/viewvc/llvm-project?rev=119727&view=rev
Log:
Factor code for testing whether replacing one value with another
preserves LCSSA form out of ScalarEvolution and into the LoopInfo
class.  Use it to check that SimplifyInstruction simplifications
are not breaking LCSSA form.  Fixes PR8622.

Added:
    llvm/trunk/test/Transforms/LoopUnswitch/2010-11-18-LCSSA.ll
Modified:
    llvm/trunk/include/llvm/Analysis/LoopInfo.h
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
    llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp

Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopInfo.h?rev=119727&r1=119726&r2=119727&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/LoopInfo.h (original)
+++ llvm/trunk/include/llvm/Analysis/LoopInfo.h Thu Nov 18 13:59:41 2010
@@ -1020,6 +1020,25 @@
   void removeBlock(BasicBlock *BB) {
     LI.removeBlock(BB);
   }
+
+  /// replacementPreservesLCSSAForm - Returns true if replacing From with To
+  /// everywhere is guaranteed to preserve LCSSA form.
+  bool replacementPreservesLCSSAForm(Instruction *From, Value *To) {
+    // Preserving LCSSA form is only problematic if the replacing value is an
+    // instruction.
+    Instruction *I = dyn_cast<Instruction>(To);
+    if (!I) return true;
+    // If the instruction is not defined in a loop then it can safely replace
+    // anything.
+    Loop *ToLoop = getLoopFor(I->getParent());
+    if (!ToLoop) return true;
+    // If the replacing instruction is defined in the same loop as the original
+    // instruction, or in a loop that contains it as an inner loop, then using
+    // it as a replacement will not break LCSSA form.
+    Loop *FromLoop = getLoopFor(From->getParent());
+    if (ToLoop->contains(FromLoop)) return true;
+    return false;
+  }
 };
 
 

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=119727&r1=119726&r2=119727&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Nov 18 13:59:41 2010
@@ -2768,25 +2768,10 @@
   // PHI's incoming blocks are in a different loop, in which case doing so
   // risks breaking LCSSA form. Instcombine would normally zap these, but
   // it doesn't have DominatorTree information, so it may miss cases.
-  if (Value *V = SimplifyInstruction(PN, TD, DT)) {
-    Instruction *I = dyn_cast<Instruction>(V);
-    // Only instructions are problematic for preserving LCSSA form.
-    if (!I)
+  if (Value *V = SimplifyInstruction(PN, TD, DT))
+    if (LI->replacementPreservesLCSSAForm(PN, V))
       return getSCEV(V);
 
-    // If the instruction is not defined in a loop, then it can be used freely.
-    Loop *ILoop = LI->getLoopFor(I->getParent());
-    if (!ILoop)
-      return getSCEV(I);
-
-    // If the instruction is defined in the same loop as the phi node, or in a
-    // loop that contains the phi node loop as an inner loop, then using it as
-    // a replacement for the phi node will not break LCSSA form.
-    Loop *PNLoop = LI->getLoopFor(PN->getParent());
-    if (ILoop->contains(PNLoop))
-      return getSCEV(I);
-  }
-
   // If it's not a loop phi, we can't handle it yet.
   return getUnknown(PN);
 }

Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=119727&r1=119726&r2=119727&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Thu Nov 18 13:59:41 2010
@@ -990,15 +990,16 @@
       ++NumSimplify;
       continue;
     }
-    
+
     // See if instruction simplification can hack this up.  This is common for
     // things like "select false, X, Y" after unswitching made the condition be
     // 'false'.
-    if (Value *V = SimplifyInstruction(I, 0, DT)) {
-      ReplaceUsesOfWith(I, V, Worklist, L, LPM);
-      continue;
-    }
-    
+    if (Value *V = SimplifyInstruction(I, 0, DT))
+      if (LI->replacementPreservesLCSSAForm(I, V)) {
+        ReplaceUsesOfWith(I, V, Worklist, L, LPM);
+        continue;
+      }
+
     // Special case hacks that appear commonly in unswitched code.
     if (BranchInst *BI = dyn_cast<BranchInst>(I)) {
       if (BI->isUnconditional()) {

Modified: llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp?rev=119727&r1=119726&r2=119727&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp Thu Nov 18 13:59:41 2010
@@ -269,11 +269,12 @@
   PHINode *PN;
   for (BasicBlock::iterator I = L->getHeader()->begin();
        (PN = dyn_cast<PHINode>(I++)); )
-    if (Value *V = SimplifyInstruction(PN, 0, DT)) {
-      if (AA) AA->deleteValue(PN);
-      PN->replaceAllUsesWith(V);
-      PN->eraseFromParent();
-    }
+    if (Value *V = SimplifyInstruction(PN, 0, DT))
+      if (LI->replacementPreservesLCSSAForm(PN, V)) {
+          if (AA) AA->deleteValue(PN);
+          PN->replaceAllUsesWith(V);
+          PN->eraseFromParent();
+      }
 
   // If this loop has multiple exits and the exits all go to the same
   // block, attempt to merge the exits. This helps several passes, such
@@ -445,17 +446,18 @@
 /// FindPHIToPartitionLoops - The first part of loop-nestification is to find a
 /// PHI node that tells us how to partition the loops.
 static PHINode *FindPHIToPartitionLoops(Loop *L, DominatorTree *DT,
-                                        AliasAnalysis *AA) {
+                                        AliasAnalysis *AA, LoopInfo *LI) {
   for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ) {
     PHINode *PN = cast<PHINode>(I);
     ++I;
-    if (Value *V = SimplifyInstruction(PN, 0, DT)) {
-      // This is a degenerate PHI already, don't modify it!
-      PN->replaceAllUsesWith(V);
-      if (AA) AA->deleteValue(PN);
-      PN->eraseFromParent();
-      continue;
-    }
+    if (Value *V = SimplifyInstruction(PN, 0, DT))
+      if (LI->replacementPreservesLCSSAForm(PN, V)) {
+        // This is a degenerate PHI already, don't modify it!
+        PN->replaceAllUsesWith(V);
+        if (AA) AA->deleteValue(PN);
+        PN->eraseFromParent();
+        continue;
+      }
 
     // Scan this PHI node looking for a use of the PHI node by itself.
     for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
@@ -523,7 +525,7 @@
 /// created.
 ///
 Loop *LoopSimplify::SeparateNestedLoop(Loop *L, LPPassManager &LPM) {
-  PHINode *PN = FindPHIToPartitionLoops(L, DT, AA);
+  PHINode *PN = FindPHIToPartitionLoops(L, DT, AA, LI);
   if (PN == 0) return 0;  // No known way to partition.
 
   // Pull out all predecessors that have varying values in the loop.  This

Added: llvm/trunk/test/Transforms/LoopUnswitch/2010-11-18-LCSSA.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/2010-11-18-LCSSA.ll?rev=119727&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LoopUnswitch/2010-11-18-LCSSA.ll (added)
+++ llvm/trunk/test/Transforms/LoopUnswitch/2010-11-18-LCSSA.ll Thu Nov 18 13:59:41 2010
@@ -0,0 +1,28 @@
+; RUN: opt < %s -loop-unswitch
+; PR8622
+ at g_38 = external global i32, align 4
+
+define void @func_67(i32 %p_68.coerce) nounwind {
+entry:
+  br i1 true, label %for.end12, label %bb.nph
+
+bb.nph:                                           ; preds = %entry
+  %g_38.promoted = load i32* @g_38
+  br label %for.body
+
+for.body:                                         ; preds = %for.cond, %bb.nph
+  %tobool.i = icmp eq i32 %p_68.coerce, 1
+  %xor4.i = xor i32 %p_68.coerce, 1
+  %call1 = select i1 %tobool.i, i32 0, i32 %xor4.i
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body
+  br i1 true, label %for.cond.for.end12_crit_edge, label %for.body
+
+for.cond.for.end12_crit_edge:                     ; preds = %for.cond
+  store i32 %call1, i32* @g_38
+  br label %for.end12
+
+for.end12:                                        ; preds = %for.cond.for.end12_crit_edge, %entry
+  ret void
+}





More information about the llvm-commits mailing list