Split SelectionDAGISel::IsLegalAndProfitableToFold to
authorEvan Cheng <evan.cheng@apple.com>
Mon, 15 Feb 2010 19:41:07 +0000 (19:41 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Mon, 15 Feb 2010 19:41:07 +0000 (19:41 +0000)
IsLegalToFold and IsProfitableToFold. The generic version of the later simply checks whether the folding candidate has a single use.

This allows the target isel routines more flexibility in deciding whether folding makes sense. The specific case we are interested in is folding constant pool loads with multiple uses.

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

include/llvm/CodeGen/SelectionDAGISel.h
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
lib/Target/PIC16/PIC16ISelLowering.cpp
lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
lib/Target/X86/X86ISelDAGToDAG.cpp
utils/TableGen/DAGISelEmitter.cpp

index b33b21da42ad903a0dd5fa5d2226a8f74d758983..ae78c5577b6e7f06df1fda63ef7e41f34e729fc6 100644 (file)
@@ -85,11 +85,13 @@ public:
     return true;
   }
 
-  /// IsLegalAndProfitableToFold - Returns true if the specific operand node N of
-  /// U can be folded during instruction selection that starts at Root and
-  /// folding N is profitable.
-  virtual
-  bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U, SDNode *Root) const;
+  /// IsProfitableToFold - Returns true if it's profitable to fold the specific
+  /// operand node N of U during instruction selection that starts at Root.
+  virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const;
+
+  /// IsLegalToFold - Returns true if the specific operand node N of
+  /// U can be folded during instruction selection that starts at Root.
+  virtual bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const;
 
   /// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer
   /// to use for this target when scheduling the DAG.
index da2e6e42a376336853cce151e09dd9dc840d944e..eead526f099e170af6240ea948b875645b68cffa 100644 (file)
@@ -1341,8 +1341,7 @@ static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse,
 /// isNonImmUse - Start searching from Root up the DAG to check is Def can
 /// be reached. Return true if that's the case. However, ignore direct uses
 /// by ImmedUse (which would be U in the example illustrated in
-/// IsLegalAndProfitableToFold) and by Root (which can happen in the store
-/// case).
+/// IsLegalToFold) and by Root (which can happen in the store case).
 /// FIXME: to be really generic, we should allow direct use by any node
 /// that is being folded. But realisticly since we only fold loads which
 /// have one non-chain use, we only need to watch out for load/op/store
@@ -1353,11 +1352,17 @@ static inline bool isNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse) {
   return findNonImmUse(Root, Def, ImmedUse, Root, Visited);
 }
 
-/// IsLegalAndProfitableToFold - Returns true if the specific operand node N of
-/// U can be folded during instruction selection that starts at Root and
-/// folding N is profitable.
-bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
-                                                  SDNode *Root) const {
+/// IsProfitableToFold - Returns true if it's profitable to fold the specific
+/// operand node N of U during instruction selection that starts at Root.
+bool SelectionDAGISel::IsProfitableToFold(SDValue N, SDNode *U,
+                                          SDNode *Root) const {
+  if (OptLevel == CodeGenOpt::None) return false;
+  return N.hasOneUse();
+}
+
+/// IsLegalToFold - Returns true if the specific operand node N of
+/// U can be folded during instruction selection that starts at Root.
+bool SelectionDAGISel::IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const {
   if (OptLevel == CodeGenOpt::None) return false;
 
   // If Root use can somehow reach N through a path that that doesn't contain
@@ -1411,7 +1416,7 @@ bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
     VT = Root->getValueType(Root->getNumValues()-1);
   }
 
-  return !isNonImmUse(Root, N, U);
+  return !isNonImmUse(Root, N.getNode(), U);
 }
 
 SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) {
index a458269b7c7ab5f50e39c9a3c2f38681b0190ee4..df4ae706b3338200f5db7fde5938434b0ef8f737 100644 (file)
@@ -58,6 +58,8 @@ public:
     return "ARM Instruction Selection";
   }
 
+  virtual void InstructionSelect();
+
   /// getI32Imm - Return a target constant of type i32 with the specified
   /// value.
   inline SDValue getI32Imm(unsigned Imm) {
@@ -65,7 +67,7 @@ public:
   }
 
   SDNode *Select(SDNode *N);
-  virtual void InstructionSelect();
+
   bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A,
                                SDValue &B, SDValue &C);
   bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base,
index 4eec757297d85604a8195334ff21052423f02eb2..a8c5e0af8857c9801cbbb1b96e5706975968d249 100644 (file)
@@ -133,8 +133,7 @@ namespace {
     bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
     bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
 
-    bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
-                                    SDNode *Root) const;
+    bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const;
 
     virtual bool
     SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
@@ -336,8 +335,8 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
   return false;
 }
 
-bool MSP430DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
-                                                    SDNode *Root) const {
+bool MSP430DAGToDAGISel::IsLegalToFold(SDValue N, SDNode *U,
+                                       SDNode *Root) const {
   if (OptLevel == CodeGenOpt::None) return false;
 
   /// RMW preprocessing creates the following code:
@@ -364,11 +363,11 @@ bool MSP430DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
   /// during preprocessing) to determine whether it's legal to introduce such
   /// "cycle" for a moment.
   DenseMap<SDNode*, SDNode*>::const_iterator I = RMWStores.find(Root);
-  if (I != RMWStores.end() && I->second == N)
+  if (I != RMWStores.end() && I->second == N.getNode())
     return true;
 
   // Proceed to 'generic' cycle finder code
-  return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root);
+  return SelectionDAGISel::IsLegalToFold(N, U, Root);
 }
 
 
@@ -656,7 +655,7 @@ SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op,
                                                unsigned Opc8, unsigned Opc16) {
   if (N1.getOpcode() == ISD::LOAD &&
       N1.hasOneUse() &&
-      IsLegalAndProfitableToFold(N1.getNode(), Op, Op)) {
+      IsLegalToFold(N1, Op, Op)) {
     LoadSDNode *LD = cast<LoadSDNode>(N1);
     if (!isValidIndexedLoad(LD))
       return NULL;
index 92b5c7b253b0a2d5c0a8909df7cefec6691f9717..d2fc8db91f7ed984cd86fde4ad8e3134bd89e636 100644 (file)
@@ -1513,8 +1513,7 @@ bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp,
       // Direct load operands are folded in binary operations. But before folding
       // verify if this folding is legal. Fold only if it is legal otherwise
       // convert this direct load to a separate memory operation.
-      if(ISel->IsLegalAndProfitableToFold(Op.getOperand(0).getNode(), 
-                                         Op.getNode(), Op.getNode()))
+      if(ISel->IsLegalToFold(Op.getOperand(0), Op.getNode(), Op.getNode()))
         return false;
       else 
         MemOp = 0;
index f6f632d5768401546807d72e31f1cc497593c85c..7f0d9fb4d7d9e897ad6c8f7cbde1d47988226a1d 100644 (file)
@@ -594,8 +594,7 @@ bool SystemZDAGToDAGISel::SelectLAAddr(SDNode *Op, SDValue Addr,
 bool SystemZDAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N,
                                  SDValue &Base, SDValue &Disp, SDValue &Index) {
   if (ISD::isNON_EXTLoad(N.getNode()) &&
-      N.hasOneUse() &&
-      IsLegalAndProfitableToFold(N.getNode(), P, P))
+      IsLegalToFold(N, P, P))
     return SelectAddrRRI20(P, N.getOperand(1), Base, Disp, Index);
   return false;
 }
index 7bd935d2bb64d50d7d8dd764eeb48099a7bbb4e0..7b349f6a16fb166d59a9e39648a45e9d327f4779 100644 (file)
@@ -183,8 +183,9 @@ namespace {
 
     virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
 
-    virtual
-      bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U, SDNode *Root) const;
+    virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const;
+
+    virtual bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const;
 
 // Include the pieces autogenerated from the target description.
 #include "X86GenDAGISel.inc"
@@ -303,11 +304,18 @@ namespace {
 }
 
 
-bool X86DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
-                                                 SDNode *Root) const {
+bool
+X86DAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const {
   if (OptLevel == CodeGenOpt::None) return false;
 
-  if (U == Root)
+  if (!N.hasOneUse())
+    return false;
+
+  if (N.getOpcode() != ISD::LOAD)
+    return true;
+
+  // If N is a load, do additional profitability checks.
+  if (U == Root) {
     switch (U->getOpcode()) {
     default: break;
     case X86ISD::ADD:
@@ -354,9 +362,17 @@ bool X86DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
       }
     }
     }
+  }
+
+  return true;
+}
+
+
+bool X86DAGToDAGISel::IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const {
+  if (OptLevel == CodeGenOpt::None) return false;
 
   // Proceed to 'generic' cycle finder code
-  return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root);
+  return SelectionDAGISel::IsLegalToFold(N, U, Root);
 }
 
 /// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
@@ -1311,8 +1327,8 @@ bool X86DAGToDAGISel::SelectScalarSSELoad(SDNode *Op, SDValue Pred,
     InChain = N.getOperand(0).getValue(1);
     if (ISD::isNON_EXTLoad(InChain.getNode()) &&
         InChain.getValue(0).hasOneUse() &&
-        N.hasOneUse() &&
-        IsLegalAndProfitableToFold(N.getNode(), Pred.getNode(), Op)) {
+        IsProfitableToFold(N, Pred.getNode(), Op) &&
+        IsLegalToFold(N, Pred.getNode(), Op)) {
       LoadSDNode *LD = cast<LoadSDNode>(InChain);
       if (!SelectAddr(Op, LD->getBasePtr(), Base, Scale, Index, Disp, Segment))
         return false;
@@ -1436,8 +1452,8 @@ bool X86DAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N,
                                   SDValue &Index, SDValue &Disp,
                                   SDValue &Segment) {
   if (ISD::isNON_EXTLoad(N.getNode()) &&
-      N.hasOneUse() &&
-      IsLegalAndProfitableToFold(N.getNode(), P, P))
+      IsProfitableToFold(N, P, P) &&
+      IsLegalToFold(N, P, P))
     return SelectAddr(P, N.getOperand(1), Base, Scale, Index, Disp, Segment);
   return false;
 }
index 0eb06bb5412cb8fb16d5011202354d2bbc2bcb89..d2e260e2e7e56ed445ba053de65f1faac6b0966f 100644 (file)
@@ -566,8 +566,11 @@ void PatternCodeEmitter::EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
     if (NodeHasChain)
       OpNo = 1;
     if (!isRoot) {
-      // Multiple uses of actual result?
-      emitCheck(getValueName(RootName) + ".hasOneUse()");
+      // Check if it's profitable to fold the node. e.g. Check for multiple uses
+      // of actual result?
+      std::string ParentName(RootName.begin(), RootName.end()-1);
+      emitCheck("IsProfitableToFold(" + getValueName(RootName) +
+                ", " + getNodeName(ParentName) + ", N)");
       EmittedUseCheck = true;
       if (NodeHasChain) {
         // If the immediate use can somehow reach this node through another
@@ -597,8 +600,7 @@ void PatternCodeEmitter::EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
         }
         
         if (NeedCheck) {
-          std::string ParentName(RootName.begin(), RootName.end()-1);
-          emitCheck("IsLegalAndProfitableToFold(" + getNodeName(RootName) +
+          emitCheck("IsLegalToFold(" + getValueName(RootName) +
                     ", " + getNodeName(ParentName) + ", N)");
         }
       }