Fix PR850 and CodeGen/X86/2006-07-31-SingleRegClass.ll.
authorChris Lattner <sabre@nondot.org>
Mon, 31 Jul 2006 23:26:50 +0000 (23:26 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 31 Jul 2006 23:26:50 +0000 (23:26 +0000)
The CFE refers to all single-register constraints (like "A") by their 16-bit
name, even though the 8 or 32-bit version of the register may be needed.
The X86 backend should realize what is going on and redecode the name back
to its proper form.

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

lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h

index 2061c660c5cec410dd6e56749f10e1c04d90fd1f..cb81f72834b73082e3db207114d30a90b1adcd92 100644 (file)
@@ -4212,3 +4212,63 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint,
   
   return std::vector<unsigned>();
 }
+
+std::pair<unsigned, const TargetRegisterClass*> 
+X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
+                                                MVT::ValueType VT) const {
+  // Use the default implementation in TargetLowering to convert the register
+  // constraint into a member of a register class.
+  std::pair<unsigned, const TargetRegisterClass*> Res;
+  Res = TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
+  
+  // Not found?  Bail out.
+  if (Res.second == 0) return Res;
+  
+  // Otherwise, check to see if this is a register class of the wrong value
+  // type.  For example, we want to map "{ax},i32" -> {eax}, we don't want it to
+  // turn into {ax},{dx}.
+  if (Res.second->hasType(VT))
+    return Res;   // Correct type already, nothing to do.
+  
+  // All of the single-register GCC register classes map their values onto
+  // 16-bit register pieces "ax","dx","cx","bx","si","di","bp","sp".  If we
+  // really want an 8-bit or 32-bit register, map to the appropriate register
+  // class and return the appropriate register.
+  if (Res.second != X86::GR16RegisterClass)
+    return Res;
+  
+  if (VT == MVT::i8) {
+    unsigned DestReg = 0;
+    switch (Res.first) {
+    default: break;
+    case X86::AX: DestReg = X86::AL; break;
+    case X86::DX: DestReg = X86::DL; break;
+    case X86::CX: DestReg = X86::CL; break;
+    case X86::BX: DestReg = X86::BL; break;
+    }
+    if (DestReg) {
+      Res.first = DestReg;
+      Res.second = Res.second = X86::GR8RegisterClass;
+    }
+  } else if (VT == MVT::i32) {
+    unsigned DestReg = 0;
+    switch (Res.first) {
+    default: break;
+    case X86::AX: DestReg = X86::EAX; break;
+    case X86::DX: DestReg = X86::EDX; break;
+    case X86::CX: DestReg = X86::ECX; break;
+    case X86::BX: DestReg = X86::EBX; break;
+    case X86::SI: DestReg = X86::ESI; break;
+    case X86::DI: DestReg = X86::EDI; break;
+    case X86::BP: DestReg = X86::EBP; break;
+    case X86::SP: DestReg = X86::ESP; break;
+    }
+    if (DestReg) {
+      Res.first = DestReg;
+      Res.second = Res.second = X86::GR32RegisterClass;
+    }
+  }
+  
+  return Res;
+}
+
index 2002910dfc41ed93013af1c36a1fe1442b92e3d4..0901b2a770b03347ea2b9d52ebca70e5335b0b19 100644 (file)
@@ -316,6 +316,14 @@ namespace llvm {
       getRegClassForInlineAsmConstraint(const std::string &Constraint,
                                         MVT::ValueType VT) const;
 
+    /// getRegForInlineAsmConstraint - Given a physical register constraint (e.g.
+    /// {edx}), return the register number and the register class for the
+    /// register.  This should only be used for C_Register constraints.  On error,
+    /// this returns a register number of 0.
+    std::pair<unsigned, const TargetRegisterClass*> 
+      getRegForInlineAsmConstraint(const std::string &Constraint,
+                                   MVT::ValueType VT) const;
+    
     /// isLegalAddressImmediate - Return true if the integer value or
     /// GlobalValue can be used as the offset of the target addressing mode.
     virtual bool isLegalAddressImmediate(int64_t V) const;