[llvm] r327938 - [RISCV] Preserve stack space for outgoing arguments when the function contain variable size objects

Shiva Chen via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 19 18:39:17 PDT 2018


Author: shiva
Date: Mon Mar 19 18:39:17 2018
New Revision: 327938

URL: http://llvm.org/viewvc/llvm-project?rev=327938&view=rev
Log:
[RISCV] Preserve stack space for outgoing arguments when the function contain variable size objects

E.g.

bar (int x)
{
  char p[x];

  push outgoing variables for foo.
  call foo
}

We need to generate stack adjustment instructions for outgoing arguments by
eliminateCallFramePseudoInstr when the function contains variable size
objects to avoid outgoing variables corrupt the variable size object.

Default hasReservedCallFrame will return !hasFP().
We don't want to generate extra sp adjustment instructions when hasFP()
return true, So We override hasReservedCallFrame as !hasVarSizedObjects().

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

Modified:
    llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.cpp
    llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.h
    llvm/trunk/test/CodeGen/RISCV/alloca.ll
    llvm/trunk/test/CodeGen/RISCV/calling-conv.ll

Modified: llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.cpp?rev=327938&r1=327937&r2=327938&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.cpp Mon Mar 19 18:39:17 2018
@@ -43,21 +43,6 @@ void RISCVFrameLowering::determineFrameL
   uint64_t StackAlign = RI->needsStackRealignment(MF) ? MFI.getMaxAlignment()
                                                       : getStackAlignment();
 
-  // Get the maximum call frame size of all the calls.
-  uint64_t MaxCallFrameSize = MFI.getMaxCallFrameSize();
-
-  // If we have dynamic alloca then MaxCallFrameSize needs to be aligned so
-  // that allocations will be aligned.
-  if (MFI.hasVarSizedObjects())
-    MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign);
-
-  // Update maximum call frame size.
-  MFI.setMaxCallFrameSize(MaxCallFrameSize);
-
-  // Include call frame size in total.
-  if (!(hasReservedCallFrame(MF) && MFI.adjustsStack()))
-    FrameSize += MaxCallFrameSize;
-
   // Make sure the frame is aligned.
   FrameSize = alignTo(FrameSize, StackAlign);
 
@@ -246,3 +231,39 @@ void RISCVFrameLowering::processFunction
     RS->addScavengingFrameIndex(RegScavFI);
   }
 }
+
+// Not preserve stack space within prologue for outgoing variables when the
+// function contains variable size objects and let eliminateCallFramePseudoInstr
+// preserve stack space for it.
+bool RISCVFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+  return !MF.getFrameInfo().hasVarSizedObjects();
+}
+
+// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions.
+MachineBasicBlock::iterator RISCVFrameLowering::eliminateCallFramePseudoInstr(
+    MachineFunction &MF, MachineBasicBlock &MBB,
+    MachineBasicBlock::iterator MI) const {
+  unsigned SPReg = RISCV::X2;
+  DebugLoc DL = MI->getDebugLoc();
+
+  if (!hasReservedCallFrame(MF)) {
+    // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and
+    // ADJCALLSTACKUP must be converted to instructions manipulating the stack
+    // pointer. This is necessary when there is a variable length stack
+    // allocation (e.g. alloca), which means it's not possible to allocate
+    // space for outgoing arguments from within the function prologue.
+    int64_t Amount = MI->getOperand(0).getImm();
+
+    if (Amount != 0) {
+      // Ensure the stack remains aligned after adjustment.
+      Amount = alignSPAdjust(Amount);
+
+      if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
+        Amount = -Amount;
+
+      adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags);
+    }
+  }
+
+  return MBB.erase(MI);
+}

Modified: llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.h?rev=327938&r1=327937&r2=327938&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.h (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.h Mon Mar 19 18:39:17 2018
@@ -41,11 +41,10 @@ public:
 
   bool hasFP(const MachineFunction &MF) const override;
 
+  bool hasReservedCallFrame(const MachineFunction &MF) const override;
   MachineBasicBlock::iterator
   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
-                                MachineBasicBlock::iterator MI) const override {
-    return MBB.erase(MI);
-  }
+                                MachineBasicBlock::iterator MI) const override;
 
 protected:
   const RISCVSubtarget &STI;

Modified: llvm/trunk/test/CodeGen/RISCV/alloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/alloca.ll?rev=327938&r1=327937&r2=327938&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/alloca.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/alloca.ll Mon Mar 19 18:39:17 2018
@@ -63,3 +63,49 @@ define void @scoped_alloca(i32 %n) nounw
   call void @llvm.stackrestore(i8* %sp)
   ret void
 }
+
+declare void @func(i8*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)
+
+; Check that outgoing arguments passed on the stack do not corrupt a
+; variable-sized stack object.
+define void @alloca_callframe(i32 %n) nounwind {
+; RV32I-LABEL: alloca_callframe:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    sw ra, 12(sp)
+; RV32I-NEXT:    sw s0, 8(sp)
+; RV32I-NEXT:    addi s0, sp, 16
+; RV32I-NEXT:    addi a0, a0, 15
+; RV32I-NEXT:    andi a0, a0, -16
+; RV32I-NEXT:    sub a0, sp, a0
+; RV32I-NEXT:    mv sp, a0
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    addi a1, zero, 12
+; RV32I-NEXT:    sw a1, 12(sp)
+; RV32I-NEXT:    addi a1, zero, 11
+; RV32I-NEXT:    sw a1, 8(sp)
+; RV32I-NEXT:    addi a1, zero, 10
+; RV32I-NEXT:    sw a1, 4(sp)
+; RV32I-NEXT:    addi a1, zero, 9
+; RV32I-NEXT:    sw a1, 0(sp)
+; RV32I-NEXT:    lui a1, %hi(func)
+; RV32I-NEXT:    addi t0, a1, %lo(func)
+; RV32I-NEXT:    addi a1, zero, 2
+; RV32I-NEXT:    addi a2, zero, 3
+; RV32I-NEXT:    addi a3, zero, 4
+; RV32I-NEXT:    addi a4, zero, 5
+; RV32I-NEXT:    addi a5, zero, 6
+; RV32I-NEXT:    addi a6, zero, 7
+; RV32I-NEXT:    addi a7, zero, 8
+; RV32I-NEXT:    jalr t0
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    addi sp, s0, -16
+; RV32I-NEXT:    lw s0, 8(sp)
+; RV32I-NEXT:    lw ra, 12(sp)
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    ret
+  %1 = alloca i8, i32 %n
+  call void @func(i8* %1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8,
+                  i32 9, i32 10, i32 11, i32 12)
+  ret void
+}

Modified: llvm/trunk/test/CodeGen/RISCV/calling-conv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/calling-conv.ll?rev=327938&r1=327937&r2=327938&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/calling-conv.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/calling-conv.ll Mon Mar 19 18:39:17 2018
@@ -504,10 +504,10 @@ define i32 @caller_many_scalars() nounwi
 ;
 ; RV32I-WITHFP-LABEL: caller_many_scalars:
 ; RV32I-WITHFP:       # %bb.0:
-; RV32I-WITHFP-NEXT:    addi sp, sp, -32
-; RV32I-WITHFP-NEXT:    sw ra, 28(sp)
-; RV32I-WITHFP-NEXT:    sw s0, 24(sp)
-; RV32I-WITHFP-NEXT:    addi s0, sp, 32
+; RV32I-WITHFP-NEXT:    addi sp, sp, -16
+; RV32I-WITHFP-NEXT:    sw ra, 12(sp)
+; RV32I-WITHFP-NEXT:    sw s0, 8(sp)
+; RV32I-WITHFP-NEXT:    addi s0, sp, 16
 ; RV32I-WITHFP-NEXT:    addi a0, zero, 8
 ; RV32I-WITHFP-NEXT:    sw a0, 4(sp)
 ; RV32I-WITHFP-NEXT:    sw zero, 0(sp)
@@ -522,9 +522,9 @@ define i32 @caller_many_scalars() nounwi
 ; RV32I-WITHFP-NEXT:    addi a7, zero, 7
 ; RV32I-WITHFP-NEXT:    mv a4, zero
 ; RV32I-WITHFP-NEXT:    jalr t0
-; RV32I-WITHFP-NEXT:    lw s0, 24(sp)
-; RV32I-WITHFP-NEXT:    lw ra, 28(sp)
-; RV32I-WITHFP-NEXT:    addi sp, sp, 32
+; RV32I-WITHFP-NEXT:    lw s0, 8(sp)
+; RV32I-WITHFP-NEXT:    lw ra, 12(sp)
+; RV32I-WITHFP-NEXT:    addi sp, sp, 16
 ; RV32I-WITHFP-NEXT:    ret
   %1 = call i32 @callee_many_scalars(i8 1, i16 2, i32 3, i64 4, i32 5, i32 6, i64 7, i32 8)
   ret i32 %1




More information about the llvm-commits mailing list