]> granicus.if.org Git - llvm/commitdiff
AMDGPU: Make frame register caller preserved
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 14 Sep 2017 17:14:57 +0000 (17:14 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 14 Sep 2017 17:14:57 +0000 (17:14 +0000)
Using SplitCSR for the frame register was very broken. Often
the copies in the prolog and epilog were optimized out, in addition
to them being inserted after the true prolog where the FP
was clobbered.

I have a hacky solution which works that continues to use
split CSR, but for now this is simpler and will get to working
programs.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313274 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AMDGPU/AMDGPURegisterInfo.cpp
lib/Target/AMDGPU/SIISelLowering.cpp
test/CodeGen/AMDGPU/call-preserved-registers.ll
test/CodeGen/AMDGPU/ipra.ll
test/CodeGen/AMDGPU/sibling-call.ll

index f0900c8bb3e389c3be3e89a50fa15e759c13305c..8454dede0e1e303302aa73009fa405f9f53836ab 100644 (file)
@@ -59,16 +59,7 @@ const MCPhysReg *SIRegisterInfo::getCalleeSavedRegs(
 
 const MCPhysReg *
 SIRegisterInfo::getCalleeSavedRegsViaCopy(const MachineFunction *MF) const {
-  // FIXME
-  static MCPhysReg Regs[2];
-
-  const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
-  assert(!MFI->isEntryFunction());
-
-  Regs[0] = MFI->getFrameOffsetReg();
-  Regs[1] = AMDGPU::NoRegister;
-
-  return Regs;
+  return nullptr;
 }
 
 const uint32_t *SIRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
index 48faee9bb995e94d5936625bec3d972d141f0416..a5c5ecc694e192cd6ed8bbe7c32db22fadbab7d3 100644 (file)
@@ -2148,6 +2148,8 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
   MachineFrameInfo &MFI = MF.getFrameInfo();
   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
 
+  SDValue CallerSavedFP;
+
   // Adjust the stack pointer for the new arguments...
   // These operations are automatically eliminated by the prolog/epilog pass
   if (!IsSibCall) {
@@ -2164,6 +2166,13 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
     SDValue ScratchWaveOffsetReg
       = DAG.getCopyFromReg(Chain, DL, OffsetReg, MVT::i32);
     RegsToPass.emplace_back(AMDGPU::SGPR4, ScratchWaveOffsetReg);
+
+    if (!Info->isEntryFunction()) {
+      // Avoid clobbering this function's FP value. In the current convention
+      // callee will overwrite this, so do save/restore around the call site.
+      CallerSavedFP = DAG.getCopyFromReg(Chain, DL,
+                                         Info->getFrameOffsetReg(), MVT::i32);
+    }
   }
 
   // Stack pointer relative accesses are done by changing the offset SGPR. This
@@ -2344,6 +2353,12 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
   Chain = Call.getValue(0);
   InFlag = Call.getValue(1);
 
+  if (CallerSavedFP) {
+    SDValue FPReg = DAG.getRegister(Info->getFrameOffsetReg(), MVT::i32);
+    Chain = DAG.getCopyToReg(Chain, DL, FPReg, CallerSavedFP, InFlag);
+    InFlag = Chain.getValue(1);
+  }
+
   uint64_t CalleePopBytes = 0;
   Chain = DAG.getCALLSEQ_END(Chain, DAG.getTargetConstant(NumBytes, DL, MVT::i32),
                              DAG.getTargetConstant(CalleePopBytes, DL, MVT::i32),
index 18122613d43fca32af3dc6008cffa6f65f92f971..98a4f1320849af8b899c411eab06ff4b535aa69f 100644 (file)
@@ -32,11 +32,13 @@ define amdgpu_kernel void @test_kernel_call_external_void_func_void_clobber_s30_
 ; GCN: v_writelane_b32 v32, s37, 4
 
 ; GCN: s_mov_b32 s33, s5
-; GCN: s_swappc_b64
+; GCN-NEXT: s_swappc_b64
+; GCN-NEXT: s_mov_b32 s5, s33
 ; GCN-NEXT: ;;#ASMSTART
 ; GCN-NEXT: ;;#ASMEND
+; GCN-NEXT: s_mov_b32 s33, s5
 ; GCN-NEXT: s_swappc_b64
-; GCN: s_mov_b32 s5, s33
+; GCN-NEXT: s_mov_b32 s5, s33
 ; GCN: v_readlane_b32 s37, v32, 4
 ; GCN: v_readlane_b32 s36, v32, 3
 ; GCN: v_readlane_b32 s35, v32, 2
@@ -50,6 +52,20 @@ define void @test_func_call_external_void_func_void_clobber_s30_s31_call_externa
   ret void
 }
 
+; FIXME: Avoid extra restore of FP in between calls.
+; GCN-LABEL: {{^}}test_func_call_external_void_funcx2:
+; GCN: s_mov_b32 s33, s5
+; GCN-NEXT: s_swappc_b64
+; GCN-NEXT: s_mov_b32 s5, s33
+; GCN-NEXT: s_mov_b32 s33, s5
+; GCN-NEXT: s_swappc_b64
+; GCN-NEXT: s_mov_b32 s5, s33
+define void @test_func_call_external_void_funcx2() #0 {
+  call void @external_void_func_void()
+  call void @external_void_func_void()
+  ret void
+}
+
 ; GCN-LABEL: {{^}}void_func_void_clobber_s30_s31:
 ; GCN: s_waitcnt
 ; GCN-NEXT: s_mov_b64 [[SAVEPC:s\[[0-9]+:[0-9]+\]]], s[30:31]
index 803855cd0327a23dd333f7e6da55a324babe6a50..9615ddd07cdbfb2cb574921c7e98b03c93035bd8 100644 (file)
@@ -90,5 +90,19 @@ define void @func_call_tail_call() #1 {
   ret void
 }
 
+define void @void_func_void() noinline {
+  ret void
+}
+
+; Make sure we don't get save/restore of FP between calls.
+; GCN-LABEL: {{^}}test_funcx2:
+; GCN-NOT: s5
+; GCN-NOT: s32
+define void @test_funcx2() #0 {
+  call void @void_func_void()
+  call void @void_func_void()
+  ret void
+}
+
 attributes #0 = { nounwind }
 attributes #1 = { nounwind noinline }
index d5b56ace32cd804e61c55a916a7927626d4c7d22..833de07095b8b111a8087168d500c13764997131 100644 (file)
@@ -13,8 +13,8 @@ define fastcc i32 @i32_fastcc_i32_i32(i32 %arg0, i32 %arg1) #1 {
 
 ; GCN-LABEL: {{^}}i32_fastcc_i32_i32_stack_object:
 ; GCN: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GCN: s_mov_b32 s5, s32
 ; GCN: v_add_i32_e32 v0, vcc, v1, v
+; GCN: s_mov_b32 s5, s32
 ; GCN: buffer_store_dword v{{[0-9]+}}, off, s[0:3], s5 offset:24
 ; GCN: s_waitcnt vmcnt(0)
 ; GCN: s_setpc_b64