Added target lowering hooks which LSR consults to make more intelligent
authorEvan Cheng <evan.cheng@apple.com>
Mon, 13 Mar 2006 23:14:23 +0000 (23:14 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Mon, 13 Mar 2006 23:14:23 +0000 (23:14 +0000)
transformation decisions.

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

include/llvm/Transforms/Scalar.h
lib/Transforms/Scalar/LoopStrengthReduce.cpp

index eb2f89682ab489cd83cbea1dae5d3bbcd9dec07f..701460db639b6a8d9a8ac86807245465145efd00 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef LLVM_TRANSFORMS_SCALAR_H
 #define LLVM_TRANSFORMS_SCALAR_H
 
+#include <cstdlib>
+
 namespace llvm {
 
 class ModulePass;
@@ -22,6 +24,7 @@ class FunctionPass;
 class GetElementPtrInst;
 class PassInfo;
 class TerminatorInst;
+class TargetLowering;
 
 //===----------------------------------------------------------------------===//
 //
@@ -132,9 +135,12 @@ FunctionPass *createLICMPass();
 // a loop's canonical induction variable as one of their indices.  The
 // MaxTargetAMSize is the largest element size that the target architecture
 // can handle in its addressing modes.  Power of two multipliers less than or
-// equal to this value are not reduced.
+// equal to this value are not reduced. It also takes an optional second
+// parameter used to consult the target machine whether certain transformations
+// are profitable.
 //
-FunctionPass *createLoopStrengthReducePass(unsigned MaxTargetAMSize = 1);
+FunctionPass *createLoopStrengthReducePass(unsigned MaxTargetAMSize = 1,
+                                           const TargetLowering *TLI = NULL);
 
 //===----------------------------------------------------------------------===//
 //
index 45a79d7f037fd8e2015a831120934185f6ec760c..2723176edb18f314d3ae94fe06dc5b7ae529b857 100644 (file)
@@ -31,6 +31,7 @@
 #include "llvm/Target/TargetData.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetLowering.h"
 #include <algorithm>
 #include <iostream>
 #include <set>
@@ -105,9 +106,14 @@ namespace {
     /// DeadInsts - Keep track of instructions we may have made dead, so that
     /// we can remove them after we are done working.
     std::set<Instruction*> DeadInsts;
+
+    /// TLI - Keep a pointer of a TargetLowering to consult for determining
+    /// transformation profitability.
+    const TargetLowering *TLI;
+
   public:
-    LoopStrengthReduce(unsigned MTAMS = 1)
-      : MaxTargetAMSize(MTAMS) {
+    LoopStrengthReduce(unsigned MTAMS = 1, const TargetLowering *tli = NULL)
+      : MaxTargetAMSize(MTAMS), TLI(tli) {
     }
 
     virtual bool runOnFunction(Function &) {
@@ -162,8 +168,9 @@ private:
                                     "Loop Strength Reduction");
 }
 
-FunctionPass *llvm::createLoopStrengthReducePass(unsigned MaxTargetAMSize) {
-  return new LoopStrengthReduce(MaxTargetAMSize);
+FunctionPass *llvm::createLoopStrengthReducePass(unsigned MaxTargetAMSize,
+                                                 const TargetLowering *TLI) {
+  return new LoopStrengthReduce(MaxTargetAMSize, TLI);
 }
 
 /// getCastedVersionOf - Return the specified value casted to uintptr_t.
@@ -574,25 +581,25 @@ void BasedUser::RewriteInstructionToUseNewBase(const SCEVHandle &NewBase,
 
 /// isTargetConstant - Return true if the following can be referenced by the
 /// immediate field of a target instruction.
-static bool isTargetConstant(const SCEVHandle &V) {
-
-  // FIXME: Look at the target to decide if &GV is a legal constant immediate.
+static bool isTargetConstant(const SCEVHandle &V, const TargetLowering *TLI) {
   if (SCEVConstant *SC = dyn_cast<SCEVConstant>(V)) {
-    // PPC allows a sign-extended 16-bit immediate field.
     int64_t V = SC->getValue()->getSExtValue();
-    if (V > -(1 << 16) && V < (1 << 16)-1)
-        return true;
-    return false;
+    if (TLI)
+      return TLI->isLegalAddressImmediate(V);
+    else
+      // Defaults to PPC. PPC allows a sign-extended 16-bit immediate field.
+      return (V > -(1 << 16) && V < (1 << 16)-1);
   }
 
-  return false;     // ENABLE this for x86
-
   if (SCEVUnknown *SU = dyn_cast<SCEVUnknown>(V))
     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(SU->getValue()))
-      if (CE->getOpcode() == Instruction::Cast)
-        if (isa<GlobalValue>(CE->getOperand(0)))
-          // FIXME: should check to see that the dest is uintptr_t!
+      if (CE->getOpcode() == Instruction::Cast) {
+        Constant *Op0 = CE->getOperand(0);
+        if (isa<GlobalValue>(Op0) &&
+            TLI &&
+            TLI->isLegalAddressImmediate(cast<GlobalValue>(Op0)))
           return true;
+      }
   return false;
 }
 
@@ -638,7 +645,8 @@ static void MoveLoopVariantsToImediateField(SCEVHandle &Val, SCEVHandle &Imm,
 /// MoveImmediateValues - Look at Val, and pull out any additions of constants
 /// that can fit into the immediate field of instructions in the target.
 /// Accumulate these immediate values into the Imm value.
-static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
+static void MoveImmediateValues(const TargetLowering *TLI,
+                                SCEVHandle &Val, SCEVHandle &Imm,
                                 bool isAddress, Loop *L) {
   if (SCEVAddExpr *SAE = dyn_cast<SCEVAddExpr>(Val)) {
     std::vector<SCEVHandle> NewOps;
@@ -646,7 +654,7 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
     
     for (unsigned i = 0; i != SAE->getNumOperands(); ++i) {
       SCEVHandle NewOp = SAE->getOperand(i);
-      MoveImmediateValues(NewOp, Imm, isAddress, L);
+      MoveImmediateValues(TLI, NewOp, Imm, isAddress, L);
       
       if (!NewOp->isLoopInvariant(L)) {
         // If this is a loop-variant expression, it must stay in the immediate
@@ -665,7 +673,7 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
   } else if (SCEVAddRecExpr *SARE = dyn_cast<SCEVAddRecExpr>(Val)) {
     // Try to pull immediates out of the start value of nested addrec's.
     SCEVHandle Start = SARE->getStart();
-    MoveImmediateValues(Start, Imm, isAddress, L);
+    MoveImmediateValues(TLI, Start, Imm, isAddress, L);
     
     if (Start != SARE->getStart()) {
       std::vector<SCEVHandle> Ops(SARE->op_begin(), SARE->op_end());
@@ -675,12 +683,12 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
     return;
   } else if (SCEVMulExpr *SME = dyn_cast<SCEVMulExpr>(Val)) {
     // Transform "8 * (4 + v)" -> "32 + 8*V" if "32" fits in the immed field.
-    if (isAddress && isTargetConstant(SME->getOperand(0)) &&
+    if (isAddress && isTargetConstant(SME->getOperand(0), TLI) &&
         SME->getNumOperands() == 2 && SME->isLoopInvariant(L)) {
 
       SCEVHandle SubImm = SCEVUnknown::getIntegerSCEV(0, Val->getType());
       SCEVHandle NewOp = SME->getOperand(1);
-      MoveImmediateValues(NewOp, SubImm, isAddress, L);
+      MoveImmediateValues(TLI, NewOp, SubImm, isAddress, L);
       
       // If we extracted something out of the subexpressions, see if we can 
       // simplify this!
@@ -688,7 +696,7 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
         // Scale SubImm up by "8".  If the result is a target constant, we are
         // good.
         SubImm = SCEVMulExpr::get(SubImm, SME->getOperand(0));
-        if (isTargetConstant(SubImm)) {
+        if (isTargetConstant(SubImm, TLI)) {
           // Accumulate the immediate.
           Imm = SCEVAddExpr::get(Imm, SubImm);
           
@@ -702,7 +710,7 @@ static void MoveImmediateValues(SCEVHandle &Val, SCEVHandle &Imm,
 
   // Loop-variant expressions must stay in the immediate field of the
   // expression.
-  if ((isAddress && isTargetConstant(Val)) ||
+  if ((isAddress && isTargetConstant(Val, TLI)) ||
       !Val->isLoopInvariant(L)) {
     Imm = SCEVAddExpr::get(Imm, Val);
     Val = SCEVUnknown::getIntegerSCEV(0, Val->getType());
@@ -879,7 +887,7 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
         if (SI->getOperand(1) == UsersToProcess[i].OperandValToReplace)
           isAddress = true;
       
-      MoveImmediateValues(UsersToProcess[i].Base, UsersToProcess[i].Imm,
+      MoveImmediateValues(TLI, UsersToProcess[i].Base, UsersToProcess[i].Imm,
                           isAddress, L);
     }
   }
@@ -941,7 +949,7 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
     // this by forcing a noop cast to be inserted into the preheader in this
     // case.
     if (Constant *C = dyn_cast<Constant>(BaseV))
-      if (!C->isNullValue() && !isTargetConstant(Base)) {
+      if (!C->isNullValue() && !isTargetConstant(Base, TLI)) {
         // We want this constant emitted into the preheader!
         BaseV = new CastInst(BaseV, BaseV->getType(), "preheaderinsert",
                              PreInsertPt);