[llvm-commits] [llvm] r90013 - in /llvm/trunk: lib/Analysis/MemoryDependenceAnalysis.cpp test/Transforms/GVN/pre-load.ll

Chris Lattner sabre at nondot.org
Fri Nov 27 11:11:32 PST 2009


Author: lattner
Date: Fri Nov 27 13:11:31 2009
New Revision: 90013

URL: http://llvm.org/viewvc/llvm-project?rev=90013&view=rev
Log:
add support for recursive phi translation and phi 
translation of add with immediate.  This allows us
to optimize this function:

void test(int N, double* G) {
  long j;
  G[1] = 1;
    for (j = 1; j < N - 1; j++)
        G[j+1] = G[j] + G[j+1];
}

to only do one load every iteration of the loop.


Modified:
    llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
    llvm/trunk/test/Transforms/GVN/pre-load.ll

Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=90013&r1=90012&r2=90013&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Fri Nov 27 13:11:31 2009
@@ -694,17 +694,31 @@
   // We can handle bitcast of a PHI, but the PHI needs to be in the same block
   // as the bitcast.
   if (BitCastInst *BC = dyn_cast<BitCastInst>(Inst))
+    // FIXME: Allow any phi translatable operand.
     if (PHINode *PN = dyn_cast<PHINode>(BC->getOperand(0)))
       if (PN->getParent() == BC->getParent())
         return true;
   
-  // We can translate a GEP that uses a PHI in the current block for at least
-  // one of its operands.
+  // We can translate a GEP if all of its operands defined in this block are phi
+  // translatable. 
   if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
-    for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i)
-      if (PHINode *PN = dyn_cast<PHINode>(GEP->getOperand(i)))
-        if (PN->getParent() == GEP->getParent())
-          return true;
+    for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) {
+      Instruction *GEPOpI = dyn_cast<Instruction>(GEP->getOperand(i));
+      if (GEPOpI == 0 || GEPOpI->getParent() != Inst->getParent())
+        continue;
+      
+      if (!isPHITranslatable(GEPOpI))
+        return false;
+    }
+    return true;
+  }
+  
+  if (Inst->getOpcode() == Instruction::Add &&
+      isa<ConstantInt>(Inst->getOperand(1))) {
+    Instruction *GEPOpI = dyn_cast<Instruction>(Inst->getOperand(0));
+    if (GEPOpI == 0 || GEPOpI->getParent() != Inst->getParent())
+      return true;
+    return isPHITranslatable(GEPOpI);
   }
 
   //   cerr << "MEMDEP: Could not PHI translate: " << *Pointer;
@@ -731,6 +745,7 @@
   
   // Handle bitcast of PHI.
   if (BitCastInst *BC = dyn_cast<BitCastInst>(Inst)) {
+    // FIXME: Recurse!
     PHINode *BCPN = cast<PHINode>(BC->getOperand(0));
     Value *PHIIn = BCPN->getIncomingValueForBlock(Pred);
     
@@ -749,7 +764,7 @@
     return 0;
   }
 
-  // Handle getelementptr with at least one PHI operand.
+  // Handle getelementptr with at least one PHI translatable operand.
   if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
     SmallVector<Value*, 8> GEPOps;
     BasicBlock *CurBB = GEP->getParent();
@@ -764,8 +779,8 @@
       }
       
       // If the operand is a phi node, do phi translation.
-      if (PHINode *PN = dyn_cast<PHINode>(GEPOp)) {
-        GEPOps.push_back(PN->getIncomingValueForBlock(Pred));
+      if (Value *InOp = PHITranslatePointer(GEPOp, CurBB, Pred, TD)) {
+        GEPOps.push_back(InOp);
         continue;
       }
       
@@ -778,7 +793,6 @@
     if (Value *V = SimplifyGEPInst(&GEPOps[0], GEPOps.size(), TD))
       return V;
 
-
     // Scan to see if we have this GEP available.
     Value *APHIOp = GEPOps[0];
     for (Value::use_iterator UI = APHIOp->use_begin(), E = APHIOp->use_end();
@@ -800,6 +814,49 @@
     return 0;
   }
   
+  // Handle add with a constant RHS.
+  if (Inst->getOpcode() == Instruction::Add &&
+      isa<ConstantInt>(Inst->getOperand(1))) {
+    // PHI translate the LHS.
+    Value *LHS;
+    Constant *RHS = cast<ConstantInt>(Inst->getOperand(1));
+    Instruction *OpI = dyn_cast<Instruction>(Inst->getOperand(0));
+    bool isNSW = cast<BinaryOperator>(Inst)->hasNoSignedWrap();
+    bool isNUW = cast<BinaryOperator>(Inst)->hasNoUnsignedWrap();
+    
+    if (OpI == 0 || OpI->getParent() != Inst->getParent())
+      LHS = Inst->getOperand(0);
+    else {
+      LHS = PHITranslatePointer(Inst->getOperand(0), CurBB, Pred, TD);
+      if (LHS == 0)
+        return 0;
+    }
+    
+    // If the PHI translated LHS is an add of a constant, fold the immediates.
+    if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(LHS))
+      if (BOp->getOpcode() == Instruction::Add)
+        if (ConstantInt *CI = dyn_cast<ConstantInt>(BOp->getOperand(1))) {
+          LHS = BOp->getOperand(0);
+          RHS = ConstantExpr::getAdd(RHS, CI);
+          isNSW = isNUW = false;
+        }
+    
+    // See if the add simplifies away.
+    if (Value *Res = SimplifyAddInst(LHS, RHS, isNSW, isNUW, TD))
+      return Res;
+    
+    // Otherwise, see if we have this add available somewhere.
+    for (Value::use_iterator UI = LHS->use_begin(), E = LHS->use_end();
+         UI != E; ++UI) {
+      if (BinaryOperator *BO = dyn_cast<BinaryOperator>(*UI))
+        if (BO->getOperand(0) == LHS && BO->getOperand(1) == RHS &&
+            BO->getParent()->getParent() == CurBB->getParent())
+          return BO;
+    }
+    
+    return 0;
+  }
+  
   return 0;
 }
 

Modified: llvm/trunk/test/Transforms/GVN/pre-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pre-load.ll?rev=90013&r1=90012&r2=90013&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/GVN/pre-load.ll (original)
+++ llvm/trunk/test/Transforms/GVN/pre-load.ll Fri Nov 27 13:11:31 2009
@@ -195,6 +195,49 @@
   ret void
 }
 
+;void test7(int N, double* G) {
+;  long j;
+;  G[1] = 1;
+;  for (j = 1; j < N - 1; j++)
+;      G[j+1] = G[j] + G[j+1];
+;}
+
+; This requires phi translation of the adds.
+define void @test7(i32 %N, double* nocapture %G) nounwind ssp {
+entry:
+  %0 = getelementptr inbounds double* %G, i64 1   
+  store double 1.000000e+00, double* %0, align 8
+  %1 = add i32 %N, -1                             
+  %2 = icmp sgt i32 %1, 1                         
+  br i1 %2, label %bb.nph, label %return
+
+bb.nph:                                           
+  %tmp = sext i32 %1 to i64                       
+  %tmp7 = add i64 %tmp, -1                        
+  br label %bb
+
+bb:                                               
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ] 
+  %tmp8 = add i64 %indvar, 2                      
+  %scevgep = getelementptr double* %G, i64 %tmp8  
+  %tmp9 = add i64 %indvar, 1                      
+  %scevgep10 = getelementptr double* %G, i64 %tmp9 
+  %3 = load double* %scevgep10, align 8           
+  %4 = load double* %scevgep, align 8             
+  %5 = fadd double %3, %4                         
+  store double %5, double* %scevgep, align 8
+  %exitcond = icmp eq i64 %tmp9, %tmp7            
+  br i1 %exitcond, label %return, label %bb
+
+; Should only be one load in the loop.
+; CHECK: bb:
+; CHECK: load double*
+; CHECK-NOT: load double*
+; CHECK: br i1 %exitcond
+
+return:                                           
+  ret void
+}
 
 
 ;;; --- todo





More information about the llvm-commits mailing list