[PowerPC] Do not use FISel for calls and TOC-based accesses with PC-Rel

PC-Relative addressing introduces a fair bit of complexity for correctly
eliminating TOC accesses. FastISel does not include any of that handling so we
miscompile code with -mcpu=pwr10 -O0 if it includes an external call that
FastISel does not handle followed by any of the following:

    Floating point constant materialization
    Materialization of a GlobalValue
    Call that FastISel does handle

This patch switches to SDISel for any of the above.

Differential revision: https://reviews.llvm.org/D86343
This commit is contained in:
Nemanja Ivanovic 2020-08-24 16:51:19 -05:00
parent f7c87b7e37
commit 075a92dea1
2 changed files with 24 additions and 10 deletions

View File

@ -1567,6 +1567,10 @@ bool PPCFastISel::fastLowerCall(CallLoweringInfo &CLI) {
if (IsVarArg) if (IsVarArg)
return false; return false;
// If this is a PC-Rel function, let SDISel handle the call.
if (Subtarget->isUsingPCRelativeCalls())
return false;
// Handle simple calls for now, with legal return types and // Handle simple calls for now, with legal return types and
// those that can be extended. // those that can be extended.
Type *RetTy = CLI.RetTy; Type *RetTy = CLI.RetTy;
@ -1991,6 +1995,10 @@ bool PPCFastISel::fastSelectInstruction(const Instruction *I) {
// Materialize a floating-point constant into a register, and return // Materialize a floating-point constant into a register, and return
// the register number (or zero if we failed to handle it). // the register number (or zero if we failed to handle it).
unsigned PPCFastISel::PPCMaterializeFP(const ConstantFP *CFP, MVT VT) { unsigned PPCFastISel::PPCMaterializeFP(const ConstantFP *CFP, MVT VT) {
// If this is a PC-Rel function, let SDISel handle constant pool.
if (Subtarget->isUsingPCRelativeCalls())
return false;
// No plans to handle long double here. // No plans to handle long double here.
if (VT != MVT::f32 && VT != MVT::f64) if (VT != MVT::f32 && VT != MVT::f64)
return 0; return 0;
@ -2055,6 +2063,10 @@ unsigned PPCFastISel::PPCMaterializeFP(const ConstantFP *CFP, MVT VT) {
// Materialize the address of a global value into a register, and return // Materialize the address of a global value into a register, and return
// the register number (or zero if we failed to handle it). // the register number (or zero if we failed to handle it).
unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) { unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) {
// If this is a PC-Rel function, let SDISel handle GV materialization.
if (Subtarget->isUsingPCRelativeCalls())
return false;
assert(VT == MVT::i64 && "Non-address!"); assert(VT == MVT::i64 && "Non-address!");
const TargetRegisterClass *RC = &PPC::G8RC_and_G8RC_NOX0RegClass; const TargetRegisterClass *RC = &PPC::G8RC_and_G8RC_NOX0RegClass;
unsigned DestReg = createResultReg(RC); unsigned DestReg = createResultReg(RC);

View File

@ -13,17 +13,21 @@
; Function Attrs: noinline nounwind optnone ; Function Attrs: noinline nounwind optnone
define internal void @loadFP(double* %d) #0 { define internal void @loadFP(double* %d) #0 {
; CHECK-LABEL: loadFP: ; CHECK-LABEL: loadFP:
; CHECK: # %bb.0: # %entry ; CHECK: .localentry loadFP, 1
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: mflr r0 ; CHECK-NEXT: mflr r0
; CHECK-NEXT: std r0, 16(r1) ; CHECK-NEXT: std r0, 16(r1)
; CHECK-NEXT: stdu r1, -112(r1) ; CHECK-NEXT: stdu r1, -112(r1)
; CHECK-NEXT: std r3, 104(r1) ; CHECK-NEXT: std r3, 104(r1)
; CHECK-NEXT: paddi r3, 0, .L.str@PCREL, 1 ; CHECK-NEXT: paddi r3, 0, .L.str@PCREL, 1
; CHECK-NEXT: bl printf@notoc ; CHECK-NEXT: bl printf@notoc
; CHECK-NEXT: addis r4, r2, .LCPI0_0@toc@ha
; CHECK-NEXT: lfd f0, .LCPI0_0@toc@l(r4)
; CHECK-NEXT: ld r4, 104(r1) ; CHECK-NEXT: ld r4, 104(r1)
; CHECK-NEXT: stfd f0, 0(r4) ; CHECK-NEXT: lis r5, 16403
; CHECK-NEXT: ori r5, r5, 62914
; CHECK-NEXT: sldi r5, r5, 32
; CHECK-NEXT: oris r5, r5, 36700
; CHECK-NEXT: ori r5, r5, 10486
; CHECK-NEXT: std r5, 0(r4)
; CHECK-NEXT: addi r1, r1, 112 ; CHECK-NEXT: addi r1, r1, 112
; CHECK-NEXT: ld r0, 16(r1) ; CHECK-NEXT: ld r0, 16(r1)
; CHECK-NEXT: mtlr r0 ; CHECK-NEXT: mtlr r0
@ -42,21 +46,19 @@ declare signext i32 @printf(i8*, ...)
; Function Attrs: noinline nounwind optnone ; Function Attrs: noinline nounwind optnone
define internal void @loadGV() #0 { define internal void @loadGV() #0 {
; CHECK-LABEL: loadGV: ; CHECK-LABEL: loadGV:
; CHECK: # %bb.0: # %entry ; CHECK: .localentry loadGV, 1
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: mflr r0 ; CHECK-NEXT: mflr r0
; CHECK-NEXT: std r0, 16(r1) ; CHECK-NEXT: std r0, 16(r1)
; CHECK-NEXT: stdu r1, -112(r1) ; CHECK-NEXT: stdu r1, -112(r1)
; CHECK-NEXT: paddi r3, 0, .L.str.1@PCREL, 1 ; CHECK-NEXT: paddi r3, 0, .L.str.1@PCREL, 1
; CHECK-NEXT: bl printf@notoc ; CHECK-NEXT: bl printf@notoc
; CHECK-NEXT: addis r4, r2, .LC0@toc@ha ; CHECK-NEXT: pld r4, stdout@got@pcrel(0), 1
; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
; CHECK-NEXT: ld r4, 0(r4) ; CHECK-NEXT: ld r4, 0(r4)
; CHECK-NEXT: li r5, 97 ; CHECK-NEXT: li r5, 97
; CHECK-NEXT: extsw r5, r5
; CHECK-NEXT: std r3, 104(r1) # 8-byte Folded Spill ; CHECK-NEXT: std r3, 104(r1) # 8-byte Folded Spill
; CHECK-NEXT: mr r3, r5 ; CHECK-NEXT: mr r3, r5
; CHECK-NEXT: bl _IO_putc ; CHECK-NEXT: bl _IO_putc@notoc
; CHECK-NEXT: nop
; CHECK-NEXT: addi r1, r1, 112 ; CHECK-NEXT: addi r1, r1, 112
; CHECK-NEXT: ld r0, 16(r1) ; CHECK-NEXT: ld r0, 16(r1)
; CHECK-NEXT: mtlr r0 ; CHECK-NEXT: mtlr r0