Skip to content

Commit

Permalink
[PowerPC] Handle FP physical register in inline asm constraint.
Browse files Browse the repository at this point in the history
Do not defer to the base class when the register constraint is a
physical fpr. The base class will select SPILLTOVSRRC as the register
class and register allocation will fail on subtargets without VSX
registers.

Differential Revision: https://reviews.llvm.org/D91629
  • Loading branch information
mandlebug authored and DrChat committed May 4, 2021
1 parent b61c24f commit 65c111f
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 10 deletions.
41 changes: 31 additions & 10 deletions llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Expand Up @@ -15092,17 +15092,38 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
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 SPILLTOVSRRC 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<unsigned, const TargetRegisterClass *> R =
TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);

Expand Down
23 changes: 23 additions & 0 deletions 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
}

26 changes: 26 additions & 0 deletions 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

0 comments on commit 65c111f

Please sign in to comment.