Move a bunch of inline asm code out of line.
authorChris Lattner <sabre@nondot.org>
Sun, 27 Apr 2008 00:09:47 +0000 (00:09 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 27 Apr 2008 00:09:47 +0000 (00:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50313 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetLowering.h
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/CodeGen/SelectionDAG/TargetLowering.cpp
lib/Transforms/Scalar/CodeGenPrepare.cpp

index 0ff58eb91dddc82d986e84a434b29851b91f33c1..559f0387ace1f3781b2c7d69be0727a2dccb7d41 100644 (file)
@@ -1076,74 +1076,13 @@ public:
         ConstraintType(TargetLowering::C_Unknown),
         CallOperandVal(0), ConstraintVT(MVT::Other) {
     }
-  
-    /// getConstraintGenerality - Return an integer indicating how general CT is.
-    unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
-      switch (CT) {
-      default: assert(0 && "Unknown constraint type!");
-      case TargetLowering::C_Other:
-      case TargetLowering::C_Unknown:
-        return 0;
-      case TargetLowering::C_Register:
-        return 1;
-      case TargetLowering::C_RegisterClass:
-        return 2;
-      case TargetLowering::C_Memory:
-        return 3;
-      }
-    }
-
-    /// ComputeConstraintToUse - Determines the constraint code and constraint
-    /// type to use.
-    void ComputeConstraintToUse(const TargetLowering &TLI) {
-      assert(!Codes.empty() && "Must have at least one constraint");
-  
-      std::string *Current = &Codes[0];
-      TargetLowering::ConstraintType CurType = TLI.getConstraintType(*Current);
-      // Single-letter constraints ('r') are very common.
-      if (Codes.size() == 1) {
-        ConstraintCode = *Current;
-        ConstraintType = CurType;
-      } else {
-        unsigned CurGenerality = getConstraintGenerality(CurType);
-
-        // If we have multiple constraints, try to pick the most general one
-        // ahead of time.  This isn't a wonderful solution, but handles common
-        // cases.
-        for (unsigned j = 1, e = Codes.size(); j != e; ++j) {
-          TargetLowering::ConstraintType ThisType = 
-            TLI.getConstraintType(Codes[j]);
-          unsigned ThisGenerality = getConstraintGenerality(ThisType);
-          if (ThisGenerality > CurGenerality) {
-            // This constraint letter is more general than the previous one,
-            // use it.
-            CurType = ThisType;
-            Current = &Codes[j];
-            CurGenerality = ThisGenerality;
-          }
-        }
-
-        ConstraintCode = *Current;
-        ConstraintType = CurType;
-      }
-
-      // 'X' matches anything.
-      if (ConstraintCode == "X" && CallOperandVal) {
-        // Labels and constants are handled elsewhere ('X' is the only thing
-        // that matches labels).
-        if (isa<BasicBlock>(CallOperandVal) || isa<ConstantInt>(CallOperandVal))
-          return;
-        
-        // Otherwise, try to resolve it to something we know about by looking at
-        // the actual operand type.
-        if (const char *Repl = TLI.LowerXConstraint(ConstraintVT)) {
-          ConstraintCode = Repl;
-          ConstraintType = TLI.getConstraintType(ConstraintCode);
-        }
-      }
-    }
   };
 
+  /// ComputeConstraintToUse - Determines the constraint code and constraint
+  /// type to use for the specific AsmOperandInfo, setting
+  /// OpInfo.ConstraintCode and OpInfo.ConstraintType.
+  virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo) const;
+  
   /// getConstraintType - Given a constraint, return the type of constraint it
   /// is for this target.
   virtual ConstraintType getConstraintType(const std::string &Constraint) const;
index 22e8ad8ef025206db52fd8a67c589142d1ea2f35..888d4605bd5733f92edb3467024b1e3d510aa86c 100644 (file)
@@ -3824,7 +3824,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
     OpInfo.ConstraintVT = OpVT;
     
     // Compute the constraint code and ConstraintType to use.
-    OpInfo.ComputeConstraintToUse(TLI);
+    TLI.ComputeConstraintToUse(OpInfo);
 
     // Keep track of whether we see an earlyclobber.
     SawEarlyClobber |= OpInfo.isEarlyClobber;
index 6c15ff91c94098b90a3977cd727c8d1064340821..cd43349411ee317327c94ad252a0f901c9738816 100644 (file)
@@ -1498,6 +1498,7 @@ PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
 //  Inline Assembler Implementation Methods
 //===----------------------------------------------------------------------===//
 
+
 TargetLowering::ConstraintType
 TargetLowering::getConstraintType(const std::string &Constraint) const {
   // FIXME: lots more standard ones to handle.
@@ -1646,6 +1647,102 @@ getRegForInlineAsmConstraint(const std::string &Constraint,
   return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
 }
 
+//===----------------------------------------------------------------------===//
+// Constraint Selection.
+
+/// getConstraintGenerality - Return an integer indicating how general CT
+/// is.
+static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
+  switch (CT) {
+  default: assert(0 && "Unknown constraint type!");
+  case TargetLowering::C_Other:
+  case TargetLowering::C_Unknown:
+    return 0;
+  case TargetLowering::C_Register:
+    return 1;
+  case TargetLowering::C_RegisterClass:
+    return 2;
+  case TargetLowering::C_Memory:
+    return 3;
+  }
+}
+
+/// ChooseConstraint - If there are multiple different constraints that we
+/// could pick for this operand (e.g. "imr") try to pick the 'best' one.
+/// This is somewhat tricky: constraints fall into three four classes:
+///    Other         -> immediates and magic values
+///    Register      -> one specific register
+///    RegisterClass -> a group of regs
+///    Memory        -> memory
+/// Ideally, we would pick the most specific constraint possible: if we have
+/// something that fits into a register, we would pick it.  The problem here
+/// is that if we have something that could either be in a register or in
+/// memory that use of the register could cause selection of *other*
+/// operands to fail: they might only succeed if we pick memory.  Because of
+/// this the heuristic we use is:
+///
+///  1) If there is an 'other' constraint, and if the operand is valid for
+///     that constraint, use it.  This makes us take advantage of 'i'
+///     constraints when available.
+///  2) Otherwise, pick the most general constraint present.  This prefers
+///     'm' over 'r', for example.
+///
+static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
+                             const TargetLowering &TLI) {
+  assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options");
+  unsigned BestIdx = 0;
+  TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown;
+  int BestGenerality = -1;
+  
+  // Loop over the options, keeping track of the most general one.
+  for (unsigned i = 0, e = OpInfo.Codes.size(); i != e; ++i) {
+    TargetLowering::ConstraintType CType =
+      TLI.getConstraintType(OpInfo.Codes[i]);
+    
+    // This constraint letter is more general than the previous one, use it.
+    int Generality = getConstraintGenerality(CType);
+    if (Generality > BestGenerality) {
+      BestType = CType;
+      BestIdx = i;
+      BestGenerality = Generality;
+    }
+  }
+  
+  OpInfo.ConstraintCode = OpInfo.Codes[BestIdx];
+  OpInfo.ConstraintType = BestType;
+}
+
+/// ComputeConstraintToUse - Determines the constraint code and constraint
+/// type to use for the specific AsmOperandInfo, setting
+/// OpInfo.ConstraintCode and OpInfo.ConstraintType.
+void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo) const {
+  assert(!OpInfo.Codes.empty() && "Must have at least one constraint");
+  
+  // Single-letter constraints ('r') are very common.
+  if (OpInfo.Codes.size() == 1) {
+    OpInfo.ConstraintCode = OpInfo.Codes[0];
+    OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode);
+  } else {
+    ChooseConstraint(OpInfo, *this);
+  }
+  
+  // 'X' matches anything.
+  if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) {
+    // Labels and constants are handled elsewhere ('X' is the only thing
+    // that matches labels).
+    if (isa<BasicBlock>(OpInfo.CallOperandVal) ||
+        isa<ConstantInt>(OpInfo.CallOperandVal))
+      return;
+    
+    // Otherwise, try to resolve it to something we know about by looking at
+    // the actual operand type.
+    if (const char *Repl = LowerXConstraint(OpInfo.ConstraintVT)) {
+      OpInfo.ConstraintCode = Repl;
+      OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode);
+    }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 //  Loop Strength Reduction hooks
 //===----------------------------------------------------------------------===//
index 4be37a33cf44322e891e5c92b3979b4e2ada298d..cdabadeb36255aacff8c5607f44289129bb79494 100644 (file)
@@ -962,7 +962,7 @@ bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS,
     }
 
     // Compute the constraint code and ConstraintType to use.
-    OpInfo.ComputeConstraintToUse(*TLI);
+    TLI->ComputeConstraintToUse(OpInfo);
 
     if (OpInfo.ConstraintType == TargetLowering::C_Memory &&
         OpInfo.isIndirect) {