Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -3673,6 +3673,9 @@ - ``I``: An immediate 13-bit signed integer. - ``r``: A 32-bit integer register. +- ``f``: Any floating-point register on SparcV8, or a floating point + register in the "low" half of the registers on SparcV9. +- ``e``: Any floating point register. (Same as ``f`` on SparcV8.) SystemZ: Index: llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp +++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp @@ -3384,7 +3384,10 @@ if (Constraint.size() == 1) { switch (Constraint[0]) { default: break; - case 'r': return C_RegisterClass; + case 'r': + case 'f': + case 'e': + return C_RegisterClass; case 'I': // SIMM13 return C_Other; } @@ -3463,6 +3466,24 @@ return std::make_pair(0U, &SP::IntPairRegClass); else return std::make_pair(0U, &SP::IntRegsRegClass); + case 'f': + if (VT == MVT::f32) + return std::make_pair(0U, &SP::FPRegsRegClass); + else if (VT == MVT::f64) + return std::make_pair(0U, &SP::LowDFPRegsRegClass); + else if (VT == MVT::f128) + return std::make_pair(0U, &SP::LowQFPRegsRegClass); + llvm_unreachable("Unknown ValueType for f-register-type!"); + break; + case 'e': + if (VT == MVT::f32) + return std::make_pair(0U, &SP::FPRegsRegClass); + else if (VT == MVT::f64) + return std::make_pair(0U, &SP::DFPRegsRegClass); + else if (VT == MVT::f128) + return std::make_pair(0U, &SP::QFPRegsRegClass); + llvm_unreachable("Unknown ValueType for e-register-type!"); + break; } } else if (!Constraint.empty() && Constraint.size() <= 5 && Constraint[0] == '{' && *(Constraint.end()-1) == '}') { Index: llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td +++ llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td @@ -346,11 +346,13 @@ // Floating point register classes. def FPRegs : RegisterClass<"SP", [f32], 32, (sequence "F%u", 0, 31)>; - def DFPRegs : RegisterClass<"SP", [f64], 64, (sequence "D%u", 0, 31)>; - def QFPRegs : RegisterClass<"SP", [f128], 128, (sequence "Q%u", 0, 15)>; +// The Low?FPRegs classes are used only for inline-asm constraints. +def LowDFPRegs : RegisterClass<"SP", [f64], 64, (sequence "D%u", 0, 15)>; +def LowQFPRegs : RegisterClass<"SP", [f128], 128, (sequence "Q%u", 0, 7)>; + // Floating point control register classes. def FCCRegs : RegisterClass<"SP", [i1], 1, (sequence "FCC%u", 0, 3)>; Index: llvm/trunk/test/CodeGen/SPARC/inlineasm-v9.ll =================================================================== --- llvm/trunk/test/CodeGen/SPARC/inlineasm-v9.ll +++ llvm/trunk/test/CodeGen/SPARC/inlineasm-v9.ll @@ -0,0 +1,30 @@ +; RUN: llc -march=sparcv9 <%s | FileCheck %s + +;; Ensures that inline-asm accepts and uses 'f' and 'e' register constraints. +; CHECK-LABEL: faddd: +; CHECK: faddd %f0, %f2, %f0 +define double @faddd(double, double) local_unnamed_addr #2 { +entry: + %2 = tail call double asm sideeffect "faddd $1, $2, $0;", "=f,f,e"(double %0, double %1) #7 + ret double %2 +} + +; CHECK-LABEL: faddq: +; CHECK: faddq %f0, %f4, %f0 +define fp128 @faddq(fp128, fp128) local_unnamed_addr #2 { +entry: + %2 = tail call fp128 asm sideeffect "faddq $1, $2, $0;", "=f,f,e"(fp128 %0, fp128 %1) #7 + ret fp128 %2 +} + +;; Ensure that 'e' can indeed go in the high area, and 'f' cannot. +; CHECK-LABEL: faddd_high: +; CHECK: fmovd %f2, %f32 +; CHECK: fmovd %f0, %f2 +; CHECK: faddd %f2, %f32, %f2 +define double @faddd_high(double, double) local_unnamed_addr #2 { +entry: + %2 = tail call double asm sideeffect "faddd $1, $2, $0;", "=f,f,e,~{d0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7}"(double %0, double %1) #7 + ret double %2 +} + Index: llvm/trunk/test/CodeGen/SPARC/inlineasm.ll =================================================================== --- llvm/trunk/test/CodeGen/SPARC/inlineasm.ll +++ llvm/trunk/test/CodeGen/SPARC/inlineasm.ll @@ -94,3 +94,21 @@ %0 = call i64 asm sideeffect "xor $1, %g0, $0", "=r,0,~{i1}"(i64 5); ret i64 %0 } + + +;; Ensures that inline-asm accepts and uses 'f' and 'e' register constraints. +; CHECK-LABEL: fadds: +; CHECK: fadds %f0, %f1, %f0 +define float @fadds(float, float) local_unnamed_addr #2 { +entry: + %2 = tail call float asm sideeffect "fadds $1, $2, $0;", "=f,f,e"(float %0, float %1) #7 + ret float %2 +} + +; CHECK-LABEL: faddd: +; CHECK: faddd %f0, %f2, %f0 +define double @faddd(double, double) local_unnamed_addr #2 { +entry: + %2 = tail call double asm sideeffect "faddd $1, $2, $0;", "=f,f,e"(double %0, double %1) #7 + ret double %2 +}