Implement ADJCALLSTACKUP and ADJCALLSTACKDOWN
authorReed Kotler <rkotler@mips.com>
Wed, 31 Oct 2012 05:21:10 +0000 (05:21 +0000)
committerReed Kotler <rkotler@mips.com>
Wed, 31 Oct 2012 05:21:10 +0000 (05:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167107 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/Mips16FrameLowering.cpp
lib/Target/Mips/Mips16InstrInfo.cpp
lib/Target/Mips/Mips16InstrInfo.h
lib/Target/Mips/Mips16InstrInfo.td
lib/Target/Mips/Mips16RegisterInfo.cpp
lib/Target/Mips/Mips16RegisterInfo.h
test/CodeGen/Mips/alloca16.ll

index 74cffd202ce47da686e520d6491c5f78e905aea1..4e6b21feb55dddf4dba8dc58bc519225e27cf5c4 100644 (file)
@@ -115,8 +115,10 @@ bool Mips16FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
 
 bool
 Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
-  // FIXME: implement.
-  return true;
+  const MachineFrameInfo *MFI = MF.getFrameInfo();
+  // Reserve call frame if the size of the maximum call frame fits into 15-bit
+  // immediate field and there are no variable sized objects on the stack.
+  return isInt<15>(MFI->getMaxCallFrameSize()) && !MFI->hasVarSizedObjects();
 }
 
 void Mips16FrameLowering::
index fa0876a4ebec7d15278b7994e933aca5df4c4e56..619646b3178a2d30b490c06478b50bbf4e1c2311 100644 (file)
@@ -26,7 +26,7 @@ using namespace llvm;
 
 Mips16InstrInfo::Mips16InstrInfo(MipsTargetMachine &tm)
   : MipsInstrInfo(tm, Mips::BimmX16),
-    RI(*tm.getSubtargetImpl()) {}
+    RI(*tm.getSubtargetImpl(), *this) {}
 
 const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const {
   return RI;
@@ -160,6 +160,22 @@ unsigned Mips16InstrInfo::GetOppositeBranchOpc(unsigned Opc) const {
   return 0;
 }
 
+/// Adjust SP by Amount bytes.
+void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
+                                     MachineBasicBlock &MBB,
+                                     MachineBasicBlock::iterator I) const {
+  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
+  if (isInt<16>(Amount)) {
+    if (Amount < 0)
+      BuildMI(MBB, I, DL, get(Mips::SaveDecSpF16)). addImm(-Amount);
+    else if (Amount > 0)
+      BuildMI(MBB, I, DL, get(Mips::RestoreIncSpF16)).addImm(Amount);
+  }
+  else
+    // not implemented for large values yet
+    assert(false && "adjust stack pointer amount exceeded");
+}
+
 unsigned Mips16InstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {
   return (Opc == Mips::BeqzRxImmX16   || Opc == Mips::BimmX16  ||
           Opc == Mips::BnezRxImmX16   || Opc == Mips::BteqzX16 ||
index 260c5b69b25f0239857b8783ba706c0d4ff7ccc3..e06ccfe61c525d58320375f7b75beaa67ddd1680 100644 (file)
@@ -64,6 +64,10 @@ public:
 
   virtual unsigned GetOppositeBranchOpc(unsigned Opc) const;
 
+  /// Adjust SP by Amount bytes.
+  void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
+                      MachineBasicBlock::iterator I) const;
+
 private:
   virtual unsigned GetAnalyzableBrOpc(unsigned Opc) const;
 
index 5f8af05f0c515d80c768f38b06b31750ff95a0df..5defc75ea6ef9f0998f9385635a32f9cfa22ef41 100644 (file)
@@ -686,7 +686,17 @@ def OrRxRxRy16: FRxRxRy16_ins<0b01101, "or", IIAlu>, ArithLogic16Defs<1>;
 let ra=1, s=0,s0=1,s1=1 in
 def RestoreRaF16:
   FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
-             "restore \t$$ra,  $$s0, $$s1, $frame_size", [], IILoad >, MayLoad {
+             "restore\t$$ra,  $$s0, $$s1, $frame_size", [], IILoad >, MayLoad {
+  let isCodeGenOnly = 1;
+}
+
+// Use Restore to increment SP since SP is not a Mip 16 register, this
+// is an easy way to do that which does not require a register.
+//
+let ra=0, s=0,s0=0,s1=0 in
+def RestoreIncSpF16:
+  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
+             "restore\t$frame_size", [], IILoad >, MayLoad {
   let isCodeGenOnly = 1;
 }
 
@@ -700,7 +710,18 @@ def RestoreRaF16:
 let ra=1, s=1,s0=1,s1=1 in
 def SaveRaF16:
   FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
-             "save \t$$ra, $$s0, $$s1, $frame_size", [], IIStore >, MayStore {
+             "save\t$$ra, $$s0, $$s1, $frame_size", [], IIStore >, MayStore {
+  let isCodeGenOnly = 1;
+}
+
+//
+// Use Save to decrement the SP by a constant since SP is not
+// a Mips16 register.
+//
+let ra=0, s=0,s0=0,s1=0 in
+def SaveDecSpF16:
+  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
+             "save\t$frame_size", [], IIStore >, MayStore {
   let isCodeGenOnly = 1;
 }
 //
index 47a41d6fa846783499d1c74379281b3f71e0053a..d7397a32f07469477a71e5c234fa61be2af52970 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Mips16RegisterInfo.h"
+#include "Mips16InstrInfo.h"
 #include "Mips.h"
 #include "MipsAnalyzeImmediate.h"
 #include "MipsInstrInfo.h"
 
 using namespace llvm;
 
-Mips16RegisterInfo::Mips16RegisterInfo(const MipsSubtarget &ST)
-  : MipsRegisterInfo(ST) {}
+Mips16RegisterInfo::Mips16RegisterInfo(const MipsSubtarget &ST,
+    const Mips16InstrInfo &I)
+  : MipsRegisterInfo(ST), TII(I) {}
 
 // This function eliminate ADJCALLSTACKDOWN,
 // ADJCALLSTACKUP pseudo instructions
 void Mips16RegisterInfo::
 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator I) const {
-  // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
+  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
+
+  if (!TFI->hasReservedCallFrame(MF)) {
+    int64_t Amount = I->getOperand(0).getImm();
+
+    if (I->getOpcode() == Mips::ADJCALLSTACKDOWN)
+      Amount = -Amount;
+
+    const Mips16InstrInfo *II = static_cast<const Mips16InstrInfo*>(&TII);
+
+    II->adjustStackPtr(Mips::SP, Amount, MBB, I);
+  }
+
   MBB.erase(I);
 }
 
index c702a15f60f0829a63d6491750bea8604c69ac88..153def20d085aa824c00d0a94ec77b4d0ec8d904 100644 (file)
@@ -20,8 +20,9 @@ namespace llvm {
 class Mips16InstrInfo;
 
 class Mips16RegisterInfo : public MipsRegisterInfo {
+  const Mips16InstrInfo &TII;
 public:
-  Mips16RegisterInfo(const MipsSubtarget &Subtarget);
+  Mips16RegisterInfo(const MipsSubtarget &Subtarget, const Mips16InstrInfo &TII);
 
   void eliminateCallFramePseudoInstr(MachineFunction &MF,
                                      MachineBasicBlock &MBB,
index ce2e634b93b9c342c3ca9af8d475ea8eb8ebd12a..731edae43cbb30463c9401f3a2bb69b4ca3c9552 100644 (file)
@@ -3,41 +3,73 @@
 @iiii = global i32 25, align 4
 @jjjj = global i32 35, align 4
 @kkkk = global i32 100, align 4
+@t = global i32 25, align 4
 @riii = common global i32 0, align 4
 @rjjj = common global i32 0, align 4
 @rkkk = common global i32 0, align 4
 
+define void @temp(i32 %foo) nounwind {
+entry:
+  %foo.addr = alloca i32, align 4
+  store i32 %foo, i32* %foo.addr, align 4
+  %0 = load i32* %foo.addr, align 4
+  store i32 %0, i32* @t, align 4
+  ret void
+}
+
 define void @test() nounwind {
 entry:
-; 16:  .frame  $16,16,$ra
-; 16:  save    $ra, $s0, $s1, 16
+; 16:  .frame  $16,24,$ra
+; 16:  save    $ra, $s0, $s1, 24
 ; 16:  move    $16, $sp
 ; 16:  move    ${{[0-9]+}}, $sp
 ; 16:  subu    $[[REGISTER:[0-9]+]], ${{[0-9]+}}, ${{[0-9]+}}
 ; 16:  move    $sp, $[[REGISTER]]
-  %0 = load i32* @kkkk, align 4
-  %1 = mul i32 %0, 25
-  %2 = alloca i32, i32 %1, align 4
-  %3 = load i32* @jjjj, align 4
-  %4 = load i32* @iiii, align 4
-  %arrayidx = getelementptr inbounds i32* %2, i32 %4
-  store i32 %3, i32* %arrayidx, align 4
-  %arrayidx1 = getelementptr inbounds i32* %2, i32 %3
-  store i32 %0, i32* %arrayidx1, align 4
-  %arrayidx2 = getelementptr inbounds i32* %2, i32 %0
-  store i32 %4, i32* %arrayidx2, align 4
-  %arrayidx3 = getelementptr inbounds i32* %2, i32 25
-  %5 = load i32* %arrayidx3, align 4
-  store i32 %5, i32* @riii, align 4
-  %arrayidx4 = getelementptr inbounds i32* %2, i32 35
-  %6 = load i32* %arrayidx4, align 4
-  store i32 %6, i32* @rjjj, align 4
-  %arrayidx5 = getelementptr inbounds i32* %2, i32 100
-  %7 = load i32* %arrayidx5, align 4
-  store i32 %7, i32* @rkkk, align 4
-; 16:  move    $sp, $16
-; 16:  restore         $ra,  $s0, $s1, 16
+  %sssi = alloca i32, align 4
+  %ip = alloca i32*, align 4
+  %sssj = alloca i32, align 4
+  %0 = load i32* @iiii, align 4
+  store i32 %0, i32* %sssi, align 4
+  %1 = load i32* @kkkk, align 4
+  %mul = mul nsw i32 %1, 100
+  %2 = alloca i8, i32 %mul
+  %3 = bitcast i8* %2 to i32*
+  store i32* %3, i32** %ip, align 4
+  %4 = load i32* @jjjj, align 4
+  store i32 %4, i32* %sssj, align 4
+  %5 = load i32* @jjjj, align 4
+  %6 = load i32* @iiii, align 4
+  %7 = load i32** %ip, align 4
+  %arrayidx = getelementptr inbounds i32* %7, i32 %6
+  store i32 %5, i32* %arrayidx, align 4
+  %8 = load i32* @kkkk, align 4
+  %9 = load i32* @jjjj, align 4
+  %10 = load i32** %ip, align 4
+  %arrayidx1 = getelementptr inbounds i32* %10, i32 %9
+  store i32 %8, i32* %arrayidx1, align 4
+  %11 = load i32* @iiii, align 4
+  %12 = load i32* @kkkk, align 4
+  %13 = load i32** %ip, align 4
+  %arrayidx2 = getelementptr inbounds i32* %13, i32 %12
+  store i32 %11, i32* %arrayidx2, align 4
+  %14 = load i32** %ip, align 4
+  %arrayidx3 = getelementptr inbounds i32* %14, i32 25
+  %15 = load i32* %arrayidx3, align 4
+  store i32 %15, i32* @riii, align 4
+  %16 = load i32** %ip, align 4
+  %arrayidx4 = getelementptr inbounds i32* %16, i32 35
+  %17 = load i32* %arrayidx4, align 4
+  store i32 %17, i32* @rjjj, align 4
+  %18 = load i32** %ip, align 4
+  %arrayidx5 = getelementptr inbounds i32* %18, i32 100
+  %19 = load i32* %arrayidx5, align 4
+  store i32 %19, i32* @rkkk, align 4
+  %20 = load i32* @t, align 4
+  %21 = load i32** %ip, align 4
+  %arrayidx6 = getelementptr inbounds i32* %21, i32 %20
+  %22 = load i32* %arrayidx6, align 4
+; 16:  save    16
+  call void @temp(i32 %22)
+; 16:  restore 16
   ret void
 }
-
-