diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -15591,17 +15591,38 @@ return std::make_pair(0U, &PPC::VSFRCRegClass); } - // If we name a VSX register, we can't defer to the base class because it - // will not recognize the correct register (their names will be VSL{0-31} - // and V{0-31} so they won't match). So we match them here. - if (Constraint.size() > 3 && Constraint[1] == 'v' && Constraint[2] == 's') { - int VSNum = atoi(Constraint.data() + 3); - assert(VSNum >= 0 && VSNum <= 63 && - "Attempted to access a vsr out of range"); - if (VSNum < 32) - return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass); - return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass); + // Handle special cases of physical registers that are not properly handled + // by the base class. + if (Constraint[0] == '{' && Constraint[Constraint.size() - 1] == '}') { + // If we name a VSX register, we can't defer to the base class because it + // will not recognize the correct register (their names will be VSL{0-31} + // and V{0-31} so they won't match). So we match them here. + if (Constraint.size() > 3 && Constraint[1] == 'v' && Constraint[2] == 's') { + int VSNum = atoi(Constraint.data() + 3); + assert(VSNum >= 0 && VSNum <= 63 && + "Attempted to access a vsr out of range"); + if (VSNum < 32) + return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass); + return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass); + } + + // For float registers, we can't defer to the base class as it will match + // the SPILLTOVSX class. + if (Constraint.size() > 3 && Constraint[1] == 'f') { + int RegNum = atoi(Constraint.data() + 2); + if (RegNum > 31 || RegNum < 0) + report_fatal_error("Invalid floating point register number"); + if (VT == MVT::f32 || VT == MVT::i32) + return Subtarget.hasSPE() + ? std::make_pair(PPC::R0 + RegNum, &PPC::GPRCRegClass) + : std::make_pair(PPC::F0 + RegNum, &PPC::F4RCRegClass); + if (VT == MVT::f64 || VT == MVT::i64) + return Subtarget.hasSPE() + ? std::make_pair(PPC::S0 + RegNum, &PPC::SPERCRegClass) + : std::make_pair(PPC::F0 + RegNum, &PPC::F8RCRegClass); + } } + std::pair R = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); diff --git a/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr-spe.ll b/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr-spe.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr-spe.ll @@ -0,0 +1,23 @@ +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu \ +; RUN: -mattr=+spe | FileCheck %s + +define i32 @test_f32(float %x) { +; CHECK-LABEL: test_f32: +; CHECK: #APP +; CHECK-NEXT: efsctsi 31, 3 +; CHECK-NEXT: #NO_APP +entry: + %0 = call i32 asm sideeffect "efsctsi $0, $1", "={f31},f"(float %x) + ret i32 %0 +} + +define i32 @test_f64(double %x) { +; CHECK-LABEL: test_f64: +; CHECK: #APP +; CHECK-NEXT: efdctsi 0, 3 +; CHECK-NEXT: #NO_APP +entry: + %0 = call i32 asm sideeffect "efdctsi $0, $1", "={f0},d"(double %x) + ret i32 %0 +} + diff --git a/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr.ll b/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/inline-asm-physical-fpr.ll @@ -0,0 +1,26 @@ +; RUN: llc -mcpu=pwr7 -mattr=-altivec -verify-machineinstrs \ +; RUN: -mtriple=powerpc-unknown-aix < %s | FileCheck %s + +; RUN: llc -mcpu=pwr7 -mattr=-altivec -verify-machineinstrs \ +; RUN: -mtriple=powerpc64-unknown-aix < %s | FileCheck %s + + +define dso_local double @test_double(double %a, double %b) { +entry: + %0 = tail call double asm "fadd. $0,$1,$2\0A", "={f31},d,d,0"(double %a, double %b, double 0.000000e+00) + ret double %0 +} + +; CHECK-LABEL: test_double +; CHECK: #APP +; CHECK-NEXT: fadd. 31,1,2 + +define dso_local signext i32 @test_int(double %a, double %b) { +entry: + %0 = tail call i32 asm "fadd. $0,$1,$2\0A", "={f0},d,d,0"(double %a, double %b, i32 0) + ret i32 %0 +} + +; CHECK-LABEL: test_int +; CHECK: #APP +; CHECK-NEXT: fadd. 0,1,2