[llvm-commits] [llvm] r57748 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/Alpha/ lib/Target/CellSPU/ lib/Target/Mips/ lib/Target/Sparc/ lib/Target/X86/ test/CodeGen/X86/

Dan Gohman gohman at apple.com
Fri Oct 17 19:06:04 PDT 2008


Author: djg
Date: Fri Oct 17 21:06:02 2008
New Revision: 57748

URL: http://llvm.org/viewvc/llvm-project?rev=57748&view=rev
Log:
Teach DAGCombine to fold constant offsets into GlobalAddress nodes,
and add a TargetLowering hook for it to use to determine when this
is legal (i.e. not in PIC mode, etc.)

This allows instruction selection to emit folded constant offsets
in more cases, such as the included testcase, eliminating the need
for explicit arithmetic instructions.

This eliminates the need for the C++ code in X86ISelDAGToDAG.cpp
that attempted to achieve the same effect, but wasn't as effective.

Also, fix handling of offsets in GlobalAddressSDNodes in several
places, including changing GlobalAddressSDNode's offset from
int to int64_t.

The Mips, Alpha, Sparc, and CellSPU targets appear to be
unaware of GlobalAddress offsets currently, so set the hook to
false on those targets.

Added:
    llvm/trunk/test/CodeGen/X86/ga-offset.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h
    llvm/trunk/include/llvm/CodeGen/MachineOperand.h
    llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
    llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
    llvm/trunk/include/llvm/Target/TargetLowering.h
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
    llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp
    llvm/trunk/lib/Target/Alpha/AlphaISelLowering.h
    llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp
    llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h
    llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
    llvm/trunk/lib/Target/Mips/MipsISelLowering.h
    llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
    llvm/trunk/lib/Target/Sparc/SparcISelLowering.h
    llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.h
    llvm/trunk/lib/Target/X86/X86TargetMachine.cpp

Modified: llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h Fri Oct 17 21:06:02 2008
@@ -79,13 +79,14 @@
   }
 
   const MachineInstrBuilder &addGlobalAddress(GlobalValue *GV,
-                                              int Offset = 0) const {
+                                              int64_t Offset = 0) const {
     MI->addOperand(MachineOperand::CreateGA(GV, Offset));
     return *this;
   }
 
-  const MachineInstrBuilder &addExternalSymbol(const char *FnName) const{
-    MI->addOperand(MachineOperand::CreateES(FnName, 0));
+  const MachineInstrBuilder &addExternalSymbol(const char *FnName,
+                                               int64_t Offset = 0) const {
+    MI->addOperand(MachineOperand::CreateES(FnName, Offset));
     return *this;
   }
 };

Modified: llvm/trunk/include/llvm/CodeGen/MachineOperand.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineOperand.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineOperand.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineOperand.h Fri Oct 17 21:06:02 2008
@@ -101,7 +101,7 @@
         const char *SymbolName;   // For MO_ExternalSymbol.
         GlobalValue *GV;          // For MO_GlobalAddress.
       } Val;
-      int Offset;   // An offset from the object.
+      int64_t Offset;   // An offset from the object.
     } OffsetedInfo;
   } Contents;
   
@@ -273,7 +273,7 @@
     return Contents.OffsetedInfo.Val.GV;
   }
   
-  int getOffset() const {
+  int64_t getOffset() const {
     assert((isGlobal() || isSymbol() || isCPI()) &&
            "Wrong MachineOperand accessor");
     return Contents.OffsetedInfo.Offset;
@@ -293,7 +293,7 @@
     Contents.ImmVal = immVal;
   }
 
-  void setOffset(int Offset) {
+  void setOffset(int64_t Offset) {
     assert((isGlobal() || isSymbol() || isCPI()) &&
         "Wrong MachineOperand accessor");
     Contents.OffsetedInfo.Offset = Offset;
@@ -382,13 +382,13 @@
     Op.setIndex(Idx);
     return Op;
   }
-  static MachineOperand CreateGA(GlobalValue *GV, int Offset) {
+  static MachineOperand CreateGA(GlobalValue *GV, int64_t Offset) {
     MachineOperand Op(MachineOperand::MO_GlobalAddress);
     Op.Contents.OffsetedInfo.Val.GV = GV;
     Op.setOffset(Offset);
     return Op;
   }
-  static MachineOperand CreateES(const char *SymName, int Offset = 0) {
+  static MachineOperand CreateES(const char *SymName, int64_t Offset = 0) {
     MachineOperand Op(MachineOperand::MO_ExternalSymbol);
     Op.Contents.OffsetedInfo.Val.SymbolName = SymName;
     Op.setOffset(Offset);

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Fri Oct 17 21:06:02 2008
@@ -255,9 +255,9 @@
     return getConstantFP(Val, VT, true);
   }
   SDValue getGlobalAddress(const GlobalValue *GV, MVT VT,
-                             int offset = 0, bool isTargetGA = false);
+                           int64_t offset = 0, bool isTargetGA = false);
   SDValue getTargetGlobalAddress(const GlobalValue *GV, MVT VT,
-                                   int offset = 0) {
+                                 int64_t offset = 0) {
     return getGlobalAddress(GV, VT, offset, true);
   }
   SDValue getFrameIndex(int FI, MVT VT, bool isTarget = false);

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Fri Oct 17 21:06:02 2008
@@ -1819,15 +1819,16 @@
 
 class GlobalAddressSDNode : public SDNode {
   GlobalValue *TheGlobal;
-  int Offset;
+  int64_t Offset;
   virtual void ANCHOR();  // Out-of-line virtual method to give class a home.
 protected:
   friend class SelectionDAG;
-  GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT VT, int o = 0);
+  GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT VT,
+                      int64_t o = 0);
 public:
 
   GlobalValue *getGlobal() const { return TheGlobal; }
-  int getOffset() const { return Offset; }
+  int64_t getOffset() const { return Offset; }
 
   static bool classof(const GlobalAddressSDNode *) { return true; }
   static bool classof(const SDNode *N) {

Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLowering.h Fri Oct 17 21:06:02 2008
@@ -653,6 +653,11 @@
   virtual SDValue getPICJumpTableRelocBase(SDValue Table,
                                              SelectionDAG &DAG) const;
 
+  /// isOffsetFoldingLegal - Return true if folding a constant offset
+  /// with the given GlobalAddress is legal.  It is frequently not legal in
+  /// PIC relocation models.
+  virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
+
   //===--------------------------------------------------------------------===//
   // TargetLowering Optimization Methods
   //

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Fri Oct 17 21:06:02 2008
@@ -967,6 +967,13 @@
   // fold (add x, 0) -> x
   if (N1C && N1C->isNullValue())
     return N0;
+  // fold (add Sym, c) -> Sym+c
+  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N0))
+    if (!AfterLegalize && TLI.isOffsetFoldingLegal(GA) && N1C &&
+        GA->getOpcode() == ISD::GlobalAddress)
+      return DAG.getGlobalAddress(GA->getGlobal(), VT,
+                                  GA->getOffset() +
+                                    (uint64_t)N1C->getSExtValue());
   // fold ((c1-A)+c2) -> (c1+c2)-A
   if (N1C && N0.getOpcode() == ISD::SUB)
     if (ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0.getOperand(0)))
@@ -1133,6 +1140,21 @@
   if (N1.getOpcode() == ISD::UNDEF)
     return N1;
 
+  // If the relocation model supports it, consider symbol offsets.
+  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N0))
+    if (!AfterLegalize && TLI.isOffsetFoldingLegal(GA)) {
+      // fold (sub Sym, c) -> Sym-c
+      if (N1C && GA->getOpcode() == ISD::GlobalAddress)
+        return DAG.getGlobalAddress(GA->getGlobal(), VT,
+                                    GA->getOffset() -
+                                      (uint64_t)N1C->getSExtValue());
+      // fold (sub Sym+c1, Sym+c2) -> c1-c2
+      if (GlobalAddressSDNode *GB = dyn_cast<GlobalAddressSDNode>(N1))
+        if (GA->getGlobal() == GB->getGlobal())
+          return DAG.getConstant((uint64_t)GA->getOffset() - GB->getOffset(),
+                                 VT);
+    }
+
   return SDValue();
 }
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Fri Oct 17 21:06:02 2008
@@ -959,10 +959,15 @@
 }
 
 SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV,
-                                       MVT VT, int Offset,
+                                       MVT VT, int64_t Offset,
                                        bool isTargetGA) {
   unsigned Opc;
 
+  // Truncate (with sign-extension) the offset value to the pointer size.
+  unsigned BitWidth = VT.getSizeInBits();
+  if (BitWidth < 64)
+    Offset = (Offset << (64 - BitWidth) >> (64 - BitWidth));
+
   const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
   if (!GVar) {
     // If GV is an alias then use the aliasee for determining thread-localness.
@@ -2017,6 +2022,7 @@
 bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const {
   GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
   if (!GA) return false;
+  if (GA->getOffset() != 0) return false;
   GlobalVariable *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
   if (!GV) return false;
   MachineModuleInfo *MMI = getMachineModuleInfo();
@@ -4726,7 +4732,7 @@
 }
 
 GlobalAddressSDNode::GlobalAddressSDNode(bool isTarget, const GlobalValue *GA,
-                                         MVT VT, int o)
+                                         MVT VT, int64_t o)
   : SDNode(isa<GlobalVariable>(GA) &&
            cast<GlobalVariable>(GA)->isThreadLocal() ?
            // Thread Local

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Fri Oct 17 21:06:02 2008
@@ -656,6 +656,23 @@
   return Table;
 }
 
+bool
+TargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
+  // Assume that everything is safe in static mode.
+  if (getTargetMachine().getRelocationModel() == Reloc::Static)
+    return true;
+
+  // In dynamic-no-pic mode, assume that known defined values are safe.
+  if (getTargetMachine().getRelocationModel() == Reloc::DynamicNoPIC &&
+      GA &&
+      !GA->getGlobal()->isDeclaration() &&
+      !GA->getGlobal()->mayBeOverridden())
+    return true;
+
+  // Otherwise assume nothing is safe.
+  return false;
+}
+
 //===----------------------------------------------------------------------===//
 //  Optimization Methods
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp Fri Oct 17 21:06:02 2008
@@ -764,3 +764,9 @@
 
   return sinkMBB;
 }
+
+bool
+AlphaTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
+  // The Alpha target isn't yet aware of offsets.
+  return false;
+}

Modified: llvm/trunk/lib/Target/Alpha/AlphaISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Alpha/AlphaISelLowering.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Alpha/AlphaISelLowering.h (original)
+++ llvm/trunk/lib/Target/Alpha/AlphaISelLowering.h Fri Oct 17 21:06:02 2008
@@ -95,6 +95,8 @@
     MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
                                                    MachineBasicBlock *BB);
 
+    virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
+
   private:
     // Helpers for custom lowering.
     void LowerVAARG(SDNode *N, SDValue &Chain, SDValue &DataPtr,

Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp Fri Oct 17 21:06:02 2008
@@ -3058,3 +3058,9 @@
 bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
   return false;
 }
+
+bool
+SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
+  // The SPU target isn't yet aware of offsets.
+  return false;
+}

Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h Fri Oct 17 21:06:02 2008
@@ -139,6 +139,8 @@
     /// as the offset of the target addressing mode.
     virtual bool isLegalAddressImmediate(int64_t V, const Type *Ty) const;
     virtual bool isLegalAddressImmediate(GlobalValue *) const;
+
+    virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
   };
 }
 

Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp Fri Oct 17 21:06:02 2008
@@ -1094,3 +1094,9 @@
   }
   return std::vector<unsigned>();
 }
+
+bool
+MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
+  // The Mips target isn't yet aware of offsets.
+  return false;
+}

Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelLowering.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelLowering.h Fri Oct 17 21:06:02 2008
@@ -118,6 +118,8 @@
     std::vector<unsigned>
     getRegClassForInlineAsmConstraint(const std::string &Constraint,
               MVT VT) const;
+
+    virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
   };
 }
 

Modified: llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp Fri Oct 17 21:06:02 2008
@@ -996,3 +996,9 @@
 
   return std::vector<unsigned>();
 }
+
+bool
+SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
+  // The Sparc target isn't yet aware of offsets.
+  return false;
+}

Modified: llvm/trunk/lib/Target/Sparc/SparcISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelLowering.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcISelLowering.h (original)
+++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.h Fri Oct 17 21:06:02 2008
@@ -70,6 +70,8 @@
     std::vector<unsigned>
     getRegClassForInlineAsmConstraint(const std::string &Constraint,
                                       MVT VT) const;
+
+    virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
   };
 } // end namespace llvm
 

Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Fri Oct 17 21:06:02 2008
@@ -759,6 +759,7 @@
 /// addressing mode.
 bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
                                    bool isRoot, unsigned Depth) {
+  bool is64Bit = Subtarget->is64Bit();
   DOUT << "MatchAddress: "; DEBUG(AM.dump());
   // Limit recursion.
   if (Depth > 5)
@@ -768,7 +769,7 @@
   if (AM.isRIPRel) {
     if (!AM.ES && AM.JT != -1 && N.getOpcode() == ISD::Constant) {
       int64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
-      if (isInt32(AM.Disp + Val)) {
+      if (!is64Bit || isInt32(AM.Disp + Val)) {
         AM.Disp += Val;
         return false;
       }
@@ -783,7 +784,7 @@
   default: break;
   case ISD::Constant: {
     int64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
-    if (isInt32(AM.Disp + Val)) {
+    if (!is64Bit || isInt32(AM.Disp + Val)) {
       AM.Disp += Val;
       return false;
     }
@@ -791,10 +792,9 @@
   }
 
   case X86ISD::Wrapper: {
-DOUT << "Wrapper: 64bit " << Subtarget->is64Bit();
-DOUT << " AM "; DEBUG(AM.dump()); DOUT << "\n";
-DOUT << "AlreadySelected " << AlreadySelected << "\n";
-    bool is64Bit = Subtarget->is64Bit();
+    DOUT << "Wrapper: 64bit " << is64Bit;
+    DOUT << " AM "; DEBUG(AM.dump()); DOUT << "\n";
+    DOUT << "AlreadySelected " << AlreadySelected << "\n";
     // Under X86-64 non-small code model, GV (and friends) are 64-bits.
     // Also, base and index reg must be 0 in order to use rip as base.
     if (is64Bit && (TM.getCodeModel() != CodeModel::Small ||
@@ -808,17 +808,21 @@
     if (!AlreadySelected || (AM.Base.Reg.getNode() && AM.IndexReg.getNode())) {
       SDValue N0 = N.getOperand(0);
       if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
-        GlobalValue *GV = G->getGlobal();
-        AM.GV = GV;
-        AM.Disp += G->getOffset();
-        AM.isRIPRel = TM.symbolicAddressesAreRIPRel();
-        return false;
+        if (!is64Bit || isInt32(AM.Disp + G->getOffset())) {
+          GlobalValue *GV = G->getGlobal();
+          AM.GV = GV;
+          AM.Disp += G->getOffset();
+          AM.isRIPRel = TM.symbolicAddressesAreRIPRel();
+          return false;
+        }
       } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
-        AM.CP = CP->getConstVal();
-        AM.Align = CP->getAlignment();
-        AM.Disp += CP->getOffset();
-        AM.isRIPRel = TM.symbolicAddressesAreRIPRel();
-        return false;
+        if (!is64Bit || isInt32(AM.Disp + CP->getOffset())) {
+          AM.CP = CP->getConstVal();
+          AM.Align = CP->getAlignment();
+          AM.Disp += CP->getOffset();
+          AM.isRIPRel = TM.symbolicAddressesAreRIPRel();
+          return false;
+        }
       } else if (ExternalSymbolSDNode *S =dyn_cast<ExternalSymbolSDNode>(N0)) {
         AM.ES = S->getSymbol();
         AM.isRIPRel = TM.symbolicAddressesAreRIPRel();
@@ -862,7 +866,7 @@
           ConstantSDNode *AddVal =
             cast<ConstantSDNode>(ShVal.getNode()->getOperand(1));
           uint64_t Disp = AM.Disp + (AddVal->getZExtValue() << Val);
-          if (isInt32(Disp))
+          if (!is64Bit || isInt32(Disp))
             AM.Disp = Disp;
           else
             AM.IndexReg = ShVal;
@@ -905,7 +909,7 @@
               cast<ConstantSDNode>(MulVal.getNode()->getOperand(1));
             uint64_t Disp = AM.Disp + AddVal->getZExtValue() *
                                       CN->getZExtValue();
-            if (isInt32(Disp))
+            if (!is64Bit || isInt32(Disp))
               AM.Disp = Disp;
             else
               Reg = N.getNode()->getOperand(0);
@@ -944,7 +948,7 @@
           // Address could not have picked a GV address for the displacement.
           AM.GV == NULL &&
           // On x86-64, the resultant disp must fit in 32-bits.
-          isInt32(AM.Disp + CN->getSExtValue()) &&
+          (!is64Bit || isInt32(AM.Disp + CN->getSExtValue())) &&
           // Check to see if the LHS & C is zero.
           CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
         AM.Disp += CN->getZExtValue();
@@ -1248,49 +1252,6 @@
     case X86ISD::GlobalBaseReg: 
       return getGlobalBaseReg();
 
-    case ISD::ADD: {
-      // Turn ADD X, c to MOV32ri X+c. This cannot be done with tblgen'd
-      // code and is matched first so to prevent it from being turned into
-      // LEA32r X+c.
-      // In 64-bit small code size mode, use LEA to take advantage of
-      // RIP-relative addressing.
-      if (TM.getCodeModel() != CodeModel::Small)
-        break;
-      MVT PtrVT = TLI.getPointerTy();
-      SDValue N0 = N.getOperand(0);
-      SDValue N1 = N.getOperand(1);
-      if (N.getNode()->getValueType(0) == PtrVT &&
-          N0.getOpcode() == X86ISD::Wrapper &&
-          N1.getOpcode() == ISD::Constant) {
-        unsigned Offset = (unsigned)cast<ConstantSDNode>(N1)->getZExtValue();
-        SDValue C(0, 0);
-        // TODO: handle ExternalSymbolSDNode.
-        if (GlobalAddressSDNode *G =
-            dyn_cast<GlobalAddressSDNode>(N0.getOperand(0))) {
-          C = CurDAG->getTargetGlobalAddress(G->getGlobal(), PtrVT,
-                                             G->getOffset() + Offset);
-        } else if (ConstantPoolSDNode *CP =
-                   dyn_cast<ConstantPoolSDNode>(N0.getOperand(0))) {
-          C = CurDAG->getTargetConstantPool(CP->getConstVal(), PtrVT,
-                                            CP->getAlignment(),
-                                            CP->getOffset()+Offset);
-        }
-
-        if (C.getNode()) {
-          if (Subtarget->is64Bit()) {
-            SDValue Ops[] = { CurDAG->getRegister(0, PtrVT), getI8Imm(1),
-                                CurDAG->getRegister(0, PtrVT), C };
-            return CurDAG->SelectNodeTo(N.getNode(), X86::LEA64r,
-                                        MVT::i64, Ops, 4);
-          } else
-            return CurDAG->SelectNodeTo(N.getNode(), X86::MOV32ri, PtrVT, C);
-        }
-      }
-
-      // Other cases are handled by auto-generated code.
-      break;
-    }
-
     case X86ISD::ATOMOR64_DAG:
       return SelectAtomic64(Node, X86::ATOMOR6432);
     case X86ISD::ATOMXOR64_DAG:

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Oct 17 21:06:02 2008
@@ -1705,7 +1705,8 @@
     // non-JIT mode.
     if (!Subtarget->GVRequiresExtraLoad(G->getGlobal(),
                                         getTargetMachine(), true))
-      Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
+      Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy(),
+                                          G->getOffset());
   } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
     Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
   } else if (IsTailCall) {
@@ -4390,12 +4391,24 @@
 
 SDValue
 X86TargetLowering::LowerGlobalAddress(const GlobalValue *GV,
+                                      int64_t Offset,
                                       SelectionDAG &DAG) const {
-  SDValue Result = DAG.getTargetGlobalAddress(GV, getPointerTy());
+  bool IsPic = getTargetMachine().getRelocationModel() == Reloc::PIC_;
+  bool ExtraLoadRequired =
+    Subtarget->GVRequiresExtraLoad(GV, getTargetMachine(), false);
+
+  // Create the TargetGlobalAddress node, folding in the constant
+  // offset if it is legal.
+  SDValue Result;
+  if (!IsPic && !ExtraLoadRequired) {
+    Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), Offset);
+    Offset = 0;
+  } else
+    Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), 0);
   Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result);
+
   // With PIC, the address is actually $g + Offset.
-  if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
-      !Subtarget->isPICStyleRIPRel()) {
+  if (IsPic && !Subtarget->isPICStyleRIPRel()) {
     Result = DAG.getNode(ISD::ADD, getPointerTy(),
                          DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
                          Result);
@@ -4406,17 +4419,24 @@
   // the GlobalAddress must be in the base or index register of the address, not
   // the GV offset field. Platform check is inside GVRequiresExtraLoad() call
   // The same applies for external symbols during PIC codegen
-  if (Subtarget->GVRequiresExtraLoad(GV, getTargetMachine(), false))
+  if (ExtraLoadRequired)
     Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), Result,
                          PseudoSourceValue::getGOT(), 0);
 
+  // If there was a non-zero offset that we didn't fold, create an explicit
+  // addition for it.
+  if (Offset != 0)
+    Result = DAG.getNode(ISD::ADD, getPointerTy(), Result,
+                         DAG.getConstant(Offset, getPointerTy()));
+
   return Result;
 }
 
 SDValue
 X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) {
   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
-  return LowerGlobalAddress(GV, DAG);
+  int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
+  return LowerGlobalAddress(GV, Offset, DAG);
 }
 
 // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit
@@ -7006,6 +7026,7 @@
   if (N->getOpcode() == X86ISD::Wrapper) {
     if (isa<GlobalAddressSDNode>(N->getOperand(0))) {
       GA = cast<GlobalAddressSDNode>(N->getOperand(0))->getGlobal();
+      Offset = cast<GlobalAddressSDNode>(N->getOperand(0))->getOffset();
       return true;
     }
   }
@@ -7448,7 +7469,7 @@
     
     if (GA) {
       if (hasMemory) 
-        Op = LowerGlobalAddress(GA->getGlobal(), DAG);
+        Op = LowerGlobalAddress(GA->getGlobal(), Offset, DAG);
       else
         Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0),
                                         Offset);

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Fri Oct 17 21:06:02 2008
@@ -551,7 +551,8 @@
     SDValue LowerINSERT_VECTOR_ELT_SSE4(SDValue Op, SelectionDAG &DAG);
     SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG);
     SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
-    SDValue LowerGlobalAddress(const GlobalValue *GV, SelectionDAG &DAG) const;
+    SDValue LowerGlobalAddress(const GlobalValue *GV, int64_t Offset,
+                               SelectionDAG &DAG) const;
     SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
     SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
     SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG);

Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=57748&r1=57747&r2=57748&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Fri Oct 17 21:06:02 2008
@@ -143,6 +143,15 @@
     else
       setRelocationModel(Reloc::Static);
   }
+
+  // ELF doesn't have a distinct dynamic-no-PIC model. Dynamic-no-PIC
+  // is defined as a model for code which may be used in static or
+  // dynamic executables but not necessarily a shared library. On ELF
+  // implement this by using the Static model.
+  if (Subtarget.isTargetELF() &&
+      getRelocationModel() == Reloc::DynamicNoPIC)
+    setRelocationModel(Reloc::Static);
+
   if (Subtarget.is64Bit()) {
     // No DynamicNoPIC support under X86-64.
     if (getRelocationModel() == Reloc::DynamicNoPIC)

Added: llvm/trunk/test/CodeGen/X86/ga-offset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/ga-offset.ll?rev=57748&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/ga-offset.ll (added)
+++ llvm/trunk/test/CodeGen/X86/ga-offset.ll Fri Oct 17 21:06:02 2008
@@ -0,0 +1,18 @@
+; RUN: llvm-as < %s | llc -march=x86 > %t
+; RUN: not grep lea %t
+; RUN: not grep add %t
+; RUN: grep mov %t | count 1
+; RUN: llvm-as < %s | llc -march=x86-64 -relocation-model=static > %t
+; RUN: not grep lea %t
+; RUN: not grep add %t
+; RUN: grep mov %t | count 1
+
+; This store should fold to a single mov instruction.
+
+ at ptr = global i32* null
+ at dst = global [131072 x i32] zeroinitializer
+
+define void @foo() nounwind {
+  store i32* getelementptr ([131072 x i32]* @dst, i32 0, i32 16), i32** @ptr
+  ret void
+}





More information about the llvm-commits mailing list