[llvm-commits] [llvm] r60012 - /llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp

Chris Lattner sabre at nondot.org
Mon Nov 24 23:09:13 PST 2008


Author: lattner
Date: Tue Nov 25 01:09:13 2008
New Revision: 60012

URL: http://llvm.org/viewvc/llvm-project?rev=60012&view=rev
Log:
significantly refactor all the addressing mode matching logic
into a new AddressingModeMatcher class.  This makes it easier
to reason about and reduces passing around of stuff, but has
no functionality change.

Modified:
    llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp?rev=60012&r1=60011&r2=60012&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp Tue Nov 25 01:09:13 2008
@@ -53,9 +53,8 @@
     bool CanMergeBlocks(const BasicBlock *BB, const BasicBlock *DestBB) const;
     void EliminateMostlyEmptyBlock(BasicBlock *BB);
     bool OptimizeBlock(BasicBlock &BB);
-    bool OptimizeLoadStoreInst(Instruction *I, Value *Addr,
-                               const Type *AccessTy,
-                               DenseMap<Value*,Value*> &SunkAddrs);
+    bool OptimizeMemoryInst(Instruction *I, Value *Addr, const Type *AccessTy,
+                            DenseMap<Value*,Value*> &SunkAddrs);
     bool OptimizeInlineAsmInst(Instruction *I, CallSite CS,
                                DenseMap<Value*,Value*> &SunkAddrs);
     bool OptimizeExtUses(Instruction *I);
@@ -486,6 +485,10 @@
   }
 }
 
+//===----------------------------------------------------------------------===//
+// Addressing Mode Analysis and Optimization
+//===----------------------------------------------------------------------===//
+
 namespace {
   /// ExtAddrMode - This is an extended version of TargetLowering::AddrMode
   /// which holds actual Value*'s for register values.
@@ -506,7 +509,6 @@
   return OS;
 }
 
-
 void ExtAddrMode::print(OStream &OS) const {
   bool NeedPlus = false;
   OS << "[";
@@ -527,13 +529,44 @@
   OS << ']';
 }
 
-/// TryMatchingScaledValue - Try adding ScaleReg*Scale to the specified
-/// addressing mode.  Return true if this addr mode is legal for the target,
+namespace {
+/// AddressingModeMatcher - This class exposes a single public method, which is
+/// used to construct a "maximal munch" of the addressing mode for the target
+/// specified by TLI for an access to "V" with an access type of AccessTy.  This
+/// returns the addressing mode that is actually matched by value, but also
+/// returns the list of instructions involved in that addressing computation in
+/// AddrModeInsts.
+class AddressingModeMatcher {
+  SmallVectorImpl<Instruction*> &AddrModeInsts;
+  const TargetLowering &TLI;
+  const Type *AccessTy;
+  ExtAddrMode &AddrMode;
+  AddressingModeMatcher(SmallVectorImpl<Instruction*> &AMI,
+                        const TargetLowering &T, const Type *AT,ExtAddrMode &AM)
+    : AddrModeInsts(AMI), TLI(T), AccessTy(AT), AddrMode(AM) {}
+public:
+  
+  static ExtAddrMode Match(Value *V, const Type *AccessTy, 
+                           SmallVectorImpl<Instruction*> &AddrModeInsts,
+                           const TargetLowering &TLI) {
+    ExtAddrMode Result;
+
+    bool Success = 
+      AddressingModeMatcher(AddrModeInsts,TLI,AccessTy,Result).MatchAddr(V, 0);
+    Success = Success; assert(Success && "Couldn't select *anything*?");
+    return Result;
+  }
+private:
+  bool MatchScaledValue(Value *ScaleReg, int64_t Scale);
+  bool MatchAddr(Value *V, unsigned Depth);
+  bool MatchOperationAddr(User *Operation, unsigned Opcode, unsigned Depth);
+};
+} // end anonymous namespace
+
+/// MatchScaledValue - Try adding ScaleReg*Scale to the current addressing mode.
+/// Return true and update AddrMode if this addr mode is legal for the target,
 /// false if not.
-static bool TryMatchingScaledValue(Value *ScaleReg, int64_t Scale,
-                                   const Type *AccessTy, ExtAddrMode &AddrMode,
-                                   SmallVectorImpl<Instruction*> &AddrModeInsts,
-                                   const TargetLowering &TLI, unsigned Depth) {
+bool AddressingModeMatcher::MatchScaledValue(Value *ScaleReg, int64_t Scale) {
   // If we already have a scale of this value, we can add to it, otherwise, we
   // need an available scale field.
   if (AddrMode.Scale != 0 && AddrMode.ScaledReg != ScaleReg)
@@ -566,6 +599,7 @@
     if (TLI.isLegalAddressingMode(TestAddrMode, AccessTy)) {
       AddrModeInsts.push_back(cast<Instruction>(ScaleReg));
       AddrMode = TestAddrMode;
+      return true;
     }
   }
 
@@ -573,46 +607,31 @@
   return true;
 }
 
-static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy,
-                                           ExtAddrMode &AddrMode,
-                                           SmallVectorImpl<Instruction*> &AMI,
-                                           const TargetLowering &TLI,
-                                           unsigned Depth);
-
-/// FindMaximalLegalAddressingModeForOperation - Given an instruction or
-/// constant expr, see if we can fold the operation into the addressing mode.
-/// If so, update the addressing mode and return true, otherwise return false.
-static bool 
-FindMaximalLegalAddressingModeForOperation(User *AddrInst, unsigned Opcode,
-                                           const Type *AccessTy,
-                                           ExtAddrMode &AddrMode,
-                                   SmallVectorImpl<Instruction*> &AddrModeInsts,
-                                           const TargetLowering &TLI,
-                                           unsigned Depth) {
+
+/// MatchOperationAddr - Given an instruction or constant expr, see if we can
+/// fold the operation into the addressing mode.  If so, update the addressing
+/// mode and return true, otherwise return false without modifying AddrMode.
+bool AddressingModeMatcher::MatchOperationAddr(User *AddrInst, unsigned Opcode,
+                                               unsigned Depth) {
+  // Avoid exponential behavior on extremely deep expression trees.
+  if (Depth >= 5) return false;
+  
   switch (Opcode) {
   case Instruction::PtrToInt:
     // PtrToInt is always a noop, as we know that the int type is pointer sized.
-    if (FindMaximalLegalAddressingMode(AddrInst->getOperand(0), AccessTy,
-                                       AddrMode, AddrModeInsts, TLI, Depth))
-      return true;
-    break;
+    return MatchAddr(AddrInst->getOperand(0), Depth);
   case Instruction::IntToPtr:
     // This inttoptr is a no-op if the integer type is pointer sized.
     if (TLI.getValueType(AddrInst->getOperand(0)->getType()) ==
-        TLI.getPointerTy()) {
-      if (FindMaximalLegalAddressingMode(AddrInst->getOperand(0), AccessTy,
-                                         AddrMode, AddrModeInsts, TLI, Depth))
-        return true;
-    }
-    break;
+        TLI.getPointerTy())
+      return MatchAddr(AddrInst->getOperand(0), Depth);
+    return false;
   case Instruction::Add: {
     // Check to see if we can merge in the RHS then the LHS.  If so, we win.
     ExtAddrMode BackupAddrMode = AddrMode;
     unsigned OldSize = AddrModeInsts.size();
-    if (FindMaximalLegalAddressingMode(AddrInst->getOperand(1), AccessTy,
-                                       AddrMode, AddrModeInsts, TLI, Depth+1) &&
-        FindMaximalLegalAddressingMode(AddrInst->getOperand(0), AccessTy,
-                                       AddrMode, AddrModeInsts, TLI, Depth+1))
+    if (MatchAddr(AddrInst->getOperand(1), Depth+1) &&
+        MatchAddr(AddrInst->getOperand(0), Depth+1))
       return true;
     
     // Restore the old addr mode info.
@@ -620,10 +639,8 @@
     AddrModeInsts.resize(OldSize);
     
     // Otherwise this was over-aggressive.  Try merging in the LHS then the RHS.
-    if (FindMaximalLegalAddressingMode(AddrInst->getOperand(0), AccessTy,
-                                       AddrMode, AddrModeInsts, TLI, Depth+1) &&
-        FindMaximalLegalAddressingMode(AddrInst->getOperand(1), AccessTy,
-                                       AddrMode, AddrModeInsts, TLI, Depth+1))
+    if (MatchAddr(AddrInst->getOperand(0), Depth+1) &&
+        MatchAddr(AddrInst->getOperand(1), Depth+1))
       return true;
     
     // Otherwise we definitely can't merge the ADD in.
@@ -641,15 +658,12 @@
   case Instruction::Shl: {
     // Can only handle X*C and X << C.
     ConstantInt *RHS = dyn_cast<ConstantInt>(AddrInst->getOperand(1));
-    if (!RHS) break;
+    if (!RHS) return false;
     int64_t Scale = RHS->getSExtValue();
     if (Opcode == Instruction::Shl)
       Scale = 1 << Scale;
     
-    if (TryMatchingScaledValue(AddrInst->getOperand(0), Scale, AccessTy,
-                               AddrMode, AddrModeInsts, TLI, Depth))
-      return true;
-    break;
+    return MatchScaledValue(AddrInst->getOperand(0), Scale);
   }
   case Instruction::GetElementPtr: {
     // Scan the GEP.  We check it if it contains constant offsets and at most
@@ -664,7 +678,7 @@
       if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
         const StructLayout *SL = TD->getStructLayout(STy);
         unsigned Idx =
-        cast<ConstantInt>(AddrInst->getOperand(i))->getZExtValue();
+          cast<ConstantInt>(AddrInst->getOperand(i))->getZExtValue();
         ConstantOffset += SL->getElementOffset(Idx);
       } else {
         uint64_t TypeSize = TD->getABITypeSize(GTI.getIndexedType());
@@ -672,10 +686,8 @@
           ConstantOffset += CI->getSExtValue()*TypeSize;
         } else if (TypeSize) {  // Scales of zero don't do anything.
           // We only allow one variable index at the moment.
-          if (VariableOperand != -1) {
-            VariableOperand = -2;
-            break;
-          }
+          if (VariableOperand != -1)
+            return false;
           
           // Remember the variable index.
           VariableOperand = i;
@@ -684,81 +696,70 @@
       }
     }
     
-    // If the GEP had multiple variable indices, punt.
-    if (VariableOperand == -2)
-      break;
-    
     // A common case is for the GEP to only do a constant offset.  In this case,
     // just add it to the disp field and check validity.
     if (VariableOperand == -1) {
       AddrMode.BaseOffs += ConstantOffset;
       if (ConstantOffset == 0 || TLI.isLegalAddressingMode(AddrMode, AccessTy)){
         // Check to see if we can fold the base pointer in too.
-        if (FindMaximalLegalAddressingMode(AddrInst->getOperand(0), AccessTy,
-                                           AddrMode, AddrModeInsts, TLI,
-                                           Depth+1))
-          return true;
-      }
-      AddrMode.BaseOffs -= ConstantOffset;
-    } else {
-      // Check that this has no base reg yet.  If so, we won't have a place to
-      // put the base of the GEP (assuming it is not a null ptr).
-      bool SetBaseReg = false;
-      if (AddrMode.HasBaseReg) {
-        if (!isa<ConstantPointerNull>(AddrInst->getOperand(0)))
-          break;
-      } else {
-        AddrMode.HasBaseReg = true;
-        AddrMode.BaseReg = AddrInst->getOperand(0);
-        SetBaseReg = true;
-      }
-      
-      // See if the scale amount is valid for this target.
-      AddrMode.BaseOffs += ConstantOffset;
-      if (TryMatchingScaledValue(AddrInst->getOperand(VariableOperand),
-                                 VariableScale, AccessTy, AddrMode,
-                                 AddrModeInsts, TLI, Depth)) {
-        if (!SetBaseReg) return true;
-        
-        // If this match succeeded, we know that we can form an address with the
-        // GepBase as the basereg.  See if we can match *more*.
-        AddrMode.HasBaseReg = false;
-        AddrMode.BaseReg = 0;
-        if (FindMaximalLegalAddressingMode(AddrInst->getOperand(0), AccessTy,
-                                           AddrMode, AddrModeInsts, TLI,
-                                           Depth+1))
+        if (MatchAddr(AddrInst->getOperand(0), Depth+1))
           return true;
-        // Strange, shouldn't happen.  Restore the base reg and succeed the easy
-        // way.
-        AddrMode.HasBaseReg = true;
-        AddrMode.BaseReg = AddrInst->getOperand(0);
-        return true;
       }
-      
       AddrMode.BaseOffs -= ConstantOffset;
-      if (SetBaseReg) {
-        AddrMode.HasBaseReg = false;
-        AddrMode.BaseReg = 0;
-      }
+      return false;
     }
-    break;
+
+    // Save the valid addressing mode in case we can't match.
+    ExtAddrMode BackupAddrMode = AddrMode;
+    
+    // Check that this has no base reg yet.  If so, we won't have a place to
+    // put the base of the GEP (assuming it is not a null ptr).
+    bool SetBaseReg = true;
+    if (isa<ConstantPointerNull>(AddrInst->getOperand(0)))
+      SetBaseReg = false;   // null pointer base doesn't need representation.
+    else if (AddrMode.HasBaseReg)
+      return false;  // Base register already specified, can't match GEP.
+    else {
+      // Otherwise, we'll use the GEP base as the BaseReg.
+      AddrMode.HasBaseReg = true;
+      AddrMode.BaseReg = AddrInst->getOperand(0);
+    }
+    
+    // See if the scale and offset amount is valid for this target.
+    AddrMode.BaseOffs += ConstantOffset;
+    
+    // FIXME: If VariableScale = 1, just call MatchAddr recursively?
+    if (!MatchScaledValue(AddrInst->getOperand(VariableOperand),VariableScale)){
+      AddrMode = BackupAddrMode;
+      return false;
+    }
+    
+    // If we have a null as the base of the GEP, folding in the constant offset
+    // plus variable scale is all we can do.
+    if (!SetBaseReg) return true;
+      
+    // If this match succeeded, we know that we can form an address with the
+    // GepBase as the basereg.  Match the base pointer of the GEP more
+    // aggressively by zeroing out BaseReg and rematching.  If the base is
+    // (for example) another GEP, this allows merging in that other GEP into
+    // the addressing mode we're forming.
+    AddrMode.HasBaseReg = false;
+    AddrMode.BaseReg = 0;
+    bool Success = MatchAddr(AddrInst->getOperand(0), Depth+1);
+    assert(Success && "MatchAddr should be able to fill in BaseReg!");
+    Success=Success;
+    return true;
   }
   }
   return false;
 }
 
-/// FindMaximalLegalAddressingMode - If we can, try to merge the computation of
-/// Addr into the specified addressing mode.  If Addr can't be added to AddrMode
-/// this returns false.  This assumes that Addr is either a pointer type or
-/// intptr_t for the target.
+/// MatchAddr - If we can, try to add the value of 'Addr' into the current
+/// addressing mode.  If Addr can't be added to AddrMode this returns false and
+/// leaves AddrMode unmodified.  This assumes that Addr is either a pointer type
+/// or intptr_t for the target.
 ///
-/// This method is used to optimize both load/store and inline asms with memory
-/// operands.
-static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy,
-                                           ExtAddrMode &AddrMode,
-                                   SmallVectorImpl<Instruction*> &AddrModeInsts,
-                                           const TargetLowering &TLI,
-                                           unsigned Depth) {
+bool AddressingModeMatcher::MatchAddr(Value *Addr, unsigned Depth) {
   if (ConstantInt *CI = dyn_cast<ConstantInt>(Addr)) {
     // Fold in immediates if legal for the target.
     AddrMode.BaseOffs += CI->getSExtValue();
@@ -766,7 +767,7 @@
       return true;
     AddrMode.BaseOffs -= CI->getSExtValue();
   } else if (GlobalValue *GV = dyn_cast<GlobalValue>(Addr)) {
-    // If this is a global variable, fold it into the addressing mode if possible.
+    // If this is a global variable, try to fold it into the addressing mode.
     if (AddrMode.BaseGV == 0) {
       AddrMode.BaseGV = GV;
       if (TLI.isLegalAddressingMode(AddrMode, AccessTy))
@@ -774,24 +775,18 @@
       AddrMode.BaseGV = 0;
     }
   } else if (Instruction *I = dyn_cast<Instruction>(Addr)) {
-    if (Depth < 5 &&   // Limit recursion to avoid exponential behavior.
-        FindMaximalLegalAddressingModeForOperation(I, I->getOpcode(),
-                                                   AccessTy, AddrMode,
-                                                   AddrModeInsts, TLI, Depth)) {
+    if (MatchOperationAddr(I, I->getOpcode(), Depth)) {
       AddrModeInsts.push_back(I);
       return true;
     }
   } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr)) {
-    if (Depth < 5 &&   // Limit recursion to avoid exponential behavior.
-        FindMaximalLegalAddressingModeForOperation(CE, CE->getOpcode(),
-                                                   AccessTy, AddrMode,
-                                                   AddrModeInsts, TLI, Depth))
+    if (MatchOperationAddr(CE, CE->getOpcode(), Depth))
       return true;
   } else if (isa<ConstantPointerNull>(Addr)) {
+    // Null pointer gets folded without affecting the addressing mode.
     return true;
   }
 
-
   // Worse case, the target should support [reg] addressing modes. :)
   if (!AddrMode.HasBaseReg) {
     AddrMode.HasBaseReg = true;
@@ -817,6 +812,10 @@
 }
 
 
+//===----------------------------------------------------------------------===//
+// Memory Optimization
+//===----------------------------------------------------------------------===//
+
 /// IsNonLocalValue - Return true if the specified values are defined in a
 /// different basic block than BB.
 static bool IsNonLocalValue(Value *V, BasicBlock *BB) {
@@ -825,21 +824,22 @@
   return false;
 }
 
-/// OptimizeLoadStoreInst - Load and Store Instructions have often have
+/// OptimizeMemoryInst - Load and Store Instructions have often have
 /// addressing modes that can do significant amounts of computation.  As such,
 /// instruction selection will try to get the load or store to do as much
 /// computation as possible for the program.  The problem is that isel can only
 /// see within a single block.  As such, we sink as much legal addressing mode
 /// stuff into the block as possible.
-bool CodeGenPrepare::OptimizeLoadStoreInst(Instruction *LdStInst, Value *Addr,
-                                           const Type *AccessTy,
-                                           DenseMap<Value*,Value*> &SunkAddrs) {
+///
+/// This method is used to optimize both load/store and inline asms with memory
+/// operands.
+bool CodeGenPrepare::OptimizeMemoryInst(Instruction *LdStInst, Value *Addr,
+                                        const Type *AccessTy,
+                                        DenseMap<Value*,Value*> &SunkAddrs) {
   // Figure out what addressing mode will be built up for this operation.
   SmallVector<Instruction*, 16> AddrModeInsts;
-  ExtAddrMode AddrMode;
-  bool Success = FindMaximalLegalAddressingMode(Addr, AccessTy, AddrMode,
-                                                AddrModeInsts, *TLI, 0);
-  Success = Success; assert(Success && "Couldn't select *anything*?");
+  ExtAddrMode AddrMode = 
+    AddressingModeMatcher::Match(Addr, AccessTy, AddrModeInsts, *TLI);
 
   // Check to see if any of the instructions supersumed by this addr mode are
   // non-local to I's BB.
@@ -940,7 +940,7 @@
 }
 
 /// OptimizeInlineAsmInst - If there are any memory operands, use
-/// OptimizeLoadStoreInt to sink their address computing into the block when
+/// OptimizeMemoryInst to sink their address computing into the block when
 /// possible / profitable.
 bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS,
                                            DenseMap<Value*,Value*> &SunkAddrs) {
@@ -981,8 +981,7 @@
     if (OpInfo.ConstraintType == TargetLowering::C_Memory &&
         OpInfo.isIndirect) {
       Value *OpVal = OpInfo.CallOperandVal;
-      MadeChange |= OptimizeLoadStoreInst(I, OpVal, OpVal->getType(),
-                                          SunkAddrs);
+      MadeChange |= OptimizeMemoryInst(I, OpVal, OpVal->getType(), SunkAddrs);
     }
   }
 
@@ -1111,13 +1110,13 @@
       MadeChange |= OptimizeCmpExpression(CI);
     } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
       if (TLI)
-        MadeChange |= OptimizeLoadStoreInst(I, I->getOperand(0), LI->getType(),
-                                            SunkAddrs);
+        MadeChange |= OptimizeMemoryInst(I, I->getOperand(0), LI->getType(),
+                                         SunkAddrs);
     } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
       if (TLI)
-        MadeChange |= OptimizeLoadStoreInst(I, SI->getOperand(1),
-                                            SI->getOperand(0)->getType(),
-                                            SunkAddrs);
+        MadeChange |= OptimizeMemoryInst(I, SI->getOperand(1),
+                                         SI->getOperand(0)->getType(),
+                                         SunkAddrs);
     } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
       if (GEPI->hasAllZeroIndices()) {
         /// The GEP operand must be a pointer, so must its result -> BitCast





More information about the llvm-commits mailing list