[llvm] 88073d4 - [PowerPC] Create a FixedStack object for CR save in linkage area.

Sean Fertile via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 7 10:34:14 PST 2020


Author: Sean Fertile
Date: 2020-02-07T13:33:44-05:00
New Revision: 88073d40c7d84d59cffe7703e2a85694936fff68

URL: https://github.com/llvm/llvm-project/commit/88073d40c7d84d59cffe7703e2a85694936fff68
DIFF: https://github.com/llvm/llvm-project/commit/88073d40c7d84d59cffe7703e2a85694936fff68.diff

LOG: [PowerPC] Create a FixedStack object for CR save in linkage area.

hasReservedSpillSlot returns a dummy frame index of '0' on PPC64 for the
non-volatile condition registers, which leads to the CalleSavedInfo
either referencing an unrelated stack object, or an invalid object if
there are no stack objects. The latter case causes the mir-printer to
crash due to assertions that checks if the frame index referenced by a
CalleeSavedInfo is valid.

To fix the problem create an immutable FixedStack object at the correct offset
in the linkage area of the previous stack frame (ie SP + positive offset).

Differential Revision: https://reviews.llvm.org/D73709

Added: 
    llvm/test/CodeGen/PowerPC/ppc64-alloca-crspill.ll
    llvm/test/CodeGen/PowerPC/ppc64-crsave.mir

Modified: 
    llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
    llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
index 467bc70e78d8..19564348bf0f 100644
--- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
@@ -1800,11 +1800,19 @@ void PPCFrameLowering::determineCalleeSaves(MachineFunction &MF,
   }
 
   // For 32-bit SVR4, allocate the nonvolatile CR spill slot iff the
-  // function uses CR 2, 3, or 4.
-  if (Subtarget.is32BitELFABI() &&
+  // function uses CR 2, 3, or 4. For 64-bit SVR4 we create a FixedStack
+  // object at the offset of the CR-save slot in the linkage area. The actual
+  // save and restore of the condition register will be created as part of the
+  // prologue and epilogue insertion, but the FixedStack object is needed to
+  // keep the CalleSavedInfo valid.
+  if (Subtarget.isSVR4ABI() &&
       (SavedRegs.test(PPC::CR2) || SavedRegs.test(PPC::CR3) ||
        SavedRegs.test(PPC::CR4))) {
-    int FrameIdx = MFI.CreateFixedObject((uint64_t)4, (int64_t)-4, true);
+    const uint64_t SpillSize = 4; // Condition register is always 4 bytes.
+    const int64_t SpillOffset = Subtarget.isPPC64() ? 8 : -4;
+    int FrameIdx =
+        MFI.CreateFixedObject(SpillSize, SpillOffset,
+                              /* IsImmutable */ true, /* IsAliased */ false);
     FI->setCRSpillFrameIndex(FrameIdx);
   }
 }

diff  --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index f0e5073e2641..f0c070c89d0f 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -929,16 +929,12 @@ bool PPCRegisterInfo::hasReservedSpillSlot(const MachineFunction &MF,
   const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
   // For the nonvolatile condition registers (CR2, CR3, CR4) in an SVR4
   // ABI, return true to prevent allocating an additional frame slot.
-  // For 64-bit, the CR save area is at SP+8; the value of FrameIdx = 0
-  // is arbitrary and will be subsequently ignored.  For 32-bit, we have
-  // previously created the stack slot if needed, so return its FrameIdx.
+  // For 64-bit, the CR save area is in the linkage area at SP+8; but we have
+  // created a FrameIndex to that spill slot to keep the CalleSaveInfos valid.
+  // For 32-bit, we have previously created the stack slot if needed, so return
+  // its FrameIdx.
   if (Subtarget.isSVR4ABI() && PPC::CR2 <= Reg && Reg <= PPC::CR4) {
-    if (TM.isPPC64())
-      FrameIdx = 0;
-    else {
-      const PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
-      FrameIdx = FI->getCRSpillFrameIndex();
-    }
+    FrameIdx = MF.getInfo<PPCFunctionInfo>()->getCRSpillFrameIndex();
     return true;
   }
   return false;

diff  --git a/llvm/test/CodeGen/PowerPC/ppc64-alloca-crspill.ll b/llvm/test/CodeGen/PowerPC/ppc64-alloca-crspill.ll
new file mode 100644
index 000000000000..e2df5b4c0cda
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/ppc64-alloca-crspill.ll
@@ -0,0 +1,66 @@
+; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu --verify-machineinstrs \
+; RUN: -stop-after=prologepilog < %s | FileCheck %s
+
+define dso_local signext i32 @test(i32 signext %n) {
+entry:
+  %conv = sext i32 %n to i64
+  %0 = alloca double, i64 %conv, align 16
+  tail call void asm sideeffect "", "~{cr2}"()
+  %call = call signext i32 @do_something(double* nonnull %0)
+  ret i32 %call
+}
+
+declare signext i32 @do_something(double*)
+
+; CHECK: name:            test
+; CHECK: alignment:       16
+; CHECK: liveins:
+; CHECK:   - { reg: '$x3', virtual-reg: '' }
+; CHECK: stackSize:       48
+; CHECK: maxCallFrameSize: 32
+
+; CHECK:      fixedStack:
+; CHECK-NEXT:   - { id: 0, type: default, offset: 8, size: 4, alignment: 8, stack-id: default,
+; CHECK-NEXT:       isImmutable: true, isAliased: false, callee-saved-register: '$cr2',
+; CHECK-NEXT:       callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
+; CHECK-NEXT:       debug-info-location: '' }
+; CHECK-NEXT:   - { id: 1, type: default, offset: -8, size: 8, alignment: 8, stack-id: default,
+; CHECK-NEXT:       isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+; CHECK-NEXT:       debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+
+; CHECK-NEXT: stack:
+; CHECK-NEXT:   - { id: 0, name: '<unnamed alloca>', type: variable-sized, offset: -8,
+; CHECK-NEXT:       alignment: 1, stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+; CHECK-NEXT:       local-offset: 0, debug-info-variable: '', debug-info-expression: '',
+; CHECK-NEXT:       debug-info-location: '' }
+; CHECK-NEXT:   - { id: 1, name: '', type: default, offset: -16, size: 8, alignment: 8,
+; CHECK-NEXT:       stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+; CHECK-NEXT:       debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+
+; CHECK:      bb.0.entry:
+; CHECK-NEXT:  liveins: $x3, $cr2
+
+; Prologue:
+; CHECK:       $x0 = MFLR8 implicit $lr8
+; CHECK-NEXT:  $x12 = MFOCRF8 killed $cr2
+; CHECK-DAG:   STD $x31, -8, $x1
+; CHECK-DAG:   STD killed $x0, 16, $x1
+; CHECK-DAG:   STW8 killed $x12, 8, $x1
+; CHECK-NEXT:  $x1 = STDU $x1, -48, $x1
+; CHECK:       $x31 = OR8 $x1, $x1
+
+; CHECK: $[[ORIGSP:x[0-9]+]] = ADDI8 $x31, 48
+; CHECK: $x1 = STDUX killed $[[ORIGSP]], $x1, killed $x{{[0-9]}}
+; CHECK: INLINEASM {{.*}} early-clobber $cr2
+; CHECK: BL8_NOP @do_something
+
+
+; Epilogue:
+; CHECK:       $x1 = LD 0, $x1
+; CHECK-DAG:   $x0 = LD 16, $x1
+; CHECK-DAG:   $x12 = LWZ8 8, $x1
+; CHECK-DAG:   $x31 = LD -8, $x1
+; CHECK:       $cr2 = MTOCRF8 killed $x12
+; CHECK-NEXT:  MTLR8 $x0, implicit-def $lr8
+; CHECK-NEXT:  BLR8 implicit $lr8, implicit $rm, implicit $x3
+

diff  --git a/llvm/test/CodeGen/PowerPC/ppc64-crsave.mir b/llvm/test/CodeGen/PowerPC/ppc64-crsave.mir
new file mode 100644
index 000000000000..6ddaca01eb59
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/ppc64-crsave.mir
@@ -0,0 +1,68 @@
+# RUN: llc -mtriple powerpc64le-unknown-linux-gnu -x mir -mcpu=pwr8 \
+# RUN: -run-pass=prologepilog --verify-machineinstrs < %s | \
+# RUN: FileCheck %s --check-prefixes=CHECK,PWR8
+
+# RUN: llc -mtriple powerpc64-unknown-linux-gnu -x mir -mcpu=pwr7 \
+# RUN: -run-pass=prologepilog --verify-machineinstrs < %s | \
+# RUN: FileCheck %s --check-prefixes=CHECK,PWR7
+
+---
+name:            CRAllSave
+alignment:       16
+tracksRegLiveness: true
+liveins:
+  - { reg: '$x3', virtual-reg: '' }
+body:             |
+  bb.0.entry:
+    liveins: $x3
+    renamable $x29 = ANDI8_rec killed renamable $x3, 1, implicit-def dead $cr0, implicit-def $cr0gt
+    renamable $cr2lt = COPY $cr0gt
+    renamable $cr4lt = COPY $cr0gt
+    renamable $x3 = COPY $x29
+    BLR8 implicit $lr8, implicit $rm, implicit $x3
+
+    ; Verify the proper live-ins have been added in the prologue.
+    ; CHECK:    liveins: $x3, $x29, $cr2, $cr4
+
+    ; CHECK:     $x12 = MFCR8 implicit killed $cr2, implicit killed $cr4
+    ; CHECK-DAG: STD killed $x29, -24, $x1 :: (store 8 into %fixed-stack.0)
+    ; CHECK-DAG: STW8 killed $x12, 8, $x1
+
+    ; CHECK:     $x29 = LD -24, $x1 :: (load 8 from %fixed-stack.0)
+    ; CHECK:     $x12 = LWZ8 8, $x1
+    ; CHECK:     $cr2 = MTOCRF8 $x12
+    ; CHECK:     $cr4 = MTOCRF8 killed $x12
+
+
+...
+---
+name:            CR2Save
+alignment:       16
+tracksRegLiveness: true
+liveins:
+  - { reg: '$x3', virtual-reg: '' }
+body:             |
+  bb.0.entry:
+    liveins: $x3
+    renamable $x14 = ANDI8_rec killed renamable $x3, 1, implicit-def dead $cr0, implicit-def $cr0gt
+    renamable $cr2lt = COPY $cr0gt
+    renamable $x3 = COPY $x14
+    BLR8 implicit $lr8, implicit $rm, implicit $x3
+
+    ; CHECK: CR2Save
+    ; Verify the proper live-ins have been added in the prologue.
+    ; CHECK:    liveins: $x3, $x14, $cr2
+
+    ; PWR8:     $x12 = MFOCRF8 killed $cr2
+    ; PWR7:     $x12 = MFCR8 implicit killed $cr2
+
+    ; CHECK-DAG: STD killed $x14, -144, $x1 :: (store 8 into %fixed-stack.0, align 16)
+    ; CHECK-DAG: STW8 killed $x12, 8, $x1
+
+    ; CHECK:     $x14 = LD -144, $x1 :: (load 8 from %fixed-stack.0, align 16)
+    ; CHECK:     $x12 = LWZ8 8, $x1
+    ; CHECK:     $cr2 = MTOCRF8 killed $x12
+
+
+...
+


        


More information about the llvm-commits mailing list