diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index a62e84f9aaf..a3bddf949a5 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include using namespace llvm; @@ -2880,6 +2881,79 @@ MipsTargetLowering::getSingleConstraintMatchWeight( return weight; } +/// This is a helper function to parse a physical register string and split it +/// into non-numeric and numeric parts (Prefix and Reg). The first boolean flag +/// that is returned indicates whether parsing was successful. The second flag +/// is true if the numeric part exists. +static std::pair +parsePhysicalReg(const StringRef &C, std::string &Prefix, + unsigned long long &Reg) { + if (C.front() != '{' || C.back() != '}') + return std::make_pair(false, false); + + // Search for the first numeric character. + StringRef::const_iterator I, B = C.begin() + 1, E = C.end() - 1; + I = std::find_if(B, E, std::ptr_fun(isdigit)); + + Prefix.assign(B, I - B); + + // The second flag is set to false if no numeric characters were found. + if (I == E) + return std::make_pair(true, false); + + // Parse the numeric characters. + return std::make_pair(!getAsUnsignedInteger(StringRef(I, E - I), 10, Reg), + true); +} + +std::pair MipsTargetLowering:: +parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const { + const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); + const TargetRegisterClass *RC; + std::string Prefix; + unsigned long long Reg; + + std::pair R = parsePhysicalReg(C, Prefix, Reg); + + if (!R.first) + return std::make_pair((unsigned)0, (const TargetRegisterClass*)0); + + if ((Prefix == "hi" || Prefix == "lo")) { // Parse hi/lo. + // No numeric characters follow "hi" or "lo". + if (R.second) + return std::make_pair((unsigned)0, (const TargetRegisterClass*)0); + + RC = TRI->getRegClass(Prefix == "hi" ? + Mips::HIRegsRegClassID : Mips::LORegsRegClassID); + return std::make_pair(*(RC->begin()), RC); + } + + if (!R.second) + return std::make_pair((unsigned)0, (const TargetRegisterClass*)0); + + if (Prefix == "$f") { // Parse $f0-$f31. + // If the size of FP registers is 64-bit or Reg is an even number, select + // the 64-bit register class. Otherwise, select the 32-bit register class. + if (VT == MVT::Other) + VT = (Subtarget->isFP64bit() || !(Reg % 2)) ? MVT::f64 : MVT::f32; + + RC= getRegClassFor(VT); + + if (RC == &Mips::AFGR64RegClass) { + assert(Reg % 2 == 0); + Reg >>= 1; + } + } else if (Prefix == "$fcc") { // Parse $fcc0-$fcc7. + RC = TRI->getRegClass(Mips::FCCRegClassID); + } else { // Parse $0-$31. + assert(Prefix == "$"); + RC = getRegClassFor((VT == MVT::Other) ? MVT::i32 : VT); + } + + assert(Reg < RC->getNumRegs()); + return std::make_pair(*(RC->begin() + Reg), RC); +} + /// Given a register class constraint, like 'r', if this corresponds directly /// to an LLVM register class, return a register of 0 and the register class /// pointer. @@ -2926,6 +3000,13 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const return std::make_pair(0u, static_cast(0)); } } + + std::pair R; + R = parseRegForInlineAsmConstraint(Constraint, VT); + + if (R.second) + return R; + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 123a2a69e5e..686a38292b5 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -433,6 +433,11 @@ namespace llvm { ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; + /// This function parses registers that appear in inline-asm constraints. + /// It returns pair (0, 0) on failure. + std::pair + parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const; + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const; diff --git a/test/CodeGen/Mips/2008-08-01-AsmInline.ll b/test/CodeGen/Mips/2008-08-01-AsmInline.ll index dbde742ad3f..e274bc0e14f 100644 --- a/test/CodeGen/Mips/2008-08-01-AsmInline.ll +++ b/test/CodeGen/Mips/2008-08-01-AsmInline.ll @@ -51,3 +51,21 @@ entry: ret void } +; Check that RA doesn't allocate registers in the clobber list. +; CHECK-LABEL: foo4: +; CHECK: #APP +; CHECK-NOT: ulh $2 +; CHECK: #NO_APP +; CHECK: #APP +; CHECK-NOT: $f0 +; CHECK: #NO_APP + +define void @foo4() { +entry: + %0 = tail call i32 asm sideeffect "ulh $0,16($$sp)\0A\09", "=r,~{$2}"() + store i32 %0, i32* @gi2, align 4 + %1 = load float* @gf0, align 4 + %2 = tail call double asm sideeffect "cvt.d.s $0, $1\0A\09", "=f,f,~{$f0}"(float %1) + store double %2, double* @gd0, align 8 + ret void +}