Reserve G1 for frame offset stuff and use it to handle large stack frames.
authorChris Lattner <sabre@nondot.org>
Tue, 20 Dec 2005 07:56:31 +0000 (07:56 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 20 Dec 2005 07:56:31 +0000 (07:56 +0000)
For example, instead of emitting this:

test:
        save -40112, %o6, %o6   ;; imm too large
        add %i6, -40016, %o0    ;; imm too large
        call caller
        nop
        restore %g0, %g0, %g0
        retl
        nop

emit this:

test:
        sethi 4194264, %g1
        or %g1, 848, %g1
        save %o6, %g1, %o6
        sethi 4194264, %g1
        add %g1, %i6, %g1
        add %i1, 944, %o0
        call caller
        nop
        restore %g0, %g0, %g0
        retl
        nop

which doesn't cause the assembler to barf.

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

lib/Target/Sparc/SparcRegisterInfo.cpp
lib/Target/Sparc/SparcRegisterInfo.td
lib/Target/SparcV8/SparcV8RegisterInfo.cpp
lib/Target/SparcV8/SparcV8RegisterInfo.td

index 7b258567304afe95c3e29a3ddf3baff5244f13f4..49cbbc091d7ee3fd7752791fde31d28c72cca651 100644 (file)
@@ -96,15 +96,30 @@ SparcV8RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
 
   int FrameIndex = MI.getOperand(i).getFrameIndex();
 
-  // Replace frame index with a frame pointer reference
-  MI.SetMachineOperandReg (i, V8::I6);
-
   // Addressable stack objects are accessed using neg. offsets from %fp
   MachineFunction &MF = *MI.getParent()->getParent();
   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
                MI.getOperand(i+1).getImmedValue();
-  // note: Offset < 0
-  MI.SetMachineOperandConst (i+1, MachineOperand::MO_SignExtendedImmed, Offset);
+
+  // Replace frame index with a frame pointer reference.
+  if (Offset >= -4096 && Offset <= 4095) {
+    // If the offset is small enough to fit in the immediate field, directly
+    // encode it.
+    MI.SetMachineOperandReg(i, V8::I6);
+    MI.SetMachineOperandConst(i+1, MachineOperand::MO_SignExtendedImmed,Offset);
+  } else {
+    // Otherwise, emit a G1 = SETHI %hi(offset).  FIXME: it would be better to 
+    // scavenge a register here instead of reserving G1 all of the time.
+    unsigned OffHi = (unsigned)Offset >> 10U;
+    BuildMI(*MI.getParent(), II, V8::SETHIi, 1, V8::G1).addImm(OffHi);
+    // Emit G1 = G1 + I6
+    BuildMI(*MI.getParent(), II, V8::ADDrr, 2, 
+            V8::G1).addReg(V8::G1).addReg(V8::I6);
+    // Insert: G1+%lo(offset) into the user.
+    MI.SetMachineOperandReg(i, V8::I1);
+    MI.SetMachineOperandConst(i+1, MachineOperand::MO_SignExtendedImmed,
+                              Offset & ((1 << 10)-1));
+  }
 }
 
 void SparcV8RegisterInfo::
@@ -128,8 +143,23 @@ void SparcV8RegisterInfo::emitPrologue(MachineFunction &MF) const {
   // Round up to next doubleword boundary -- a double-word boundary
   // is required by the ABI.
   NumBytes = (NumBytes + 7) & ~7;
-  BuildMI(MBB, MBB.begin(), V8::SAVEri, 2,
-          V8::O6).addImm(-NumBytes).addReg(V8::O6);
+  NumBytes = -NumBytes;
+  
+  if (NumBytes >= -4096) {
+    BuildMI(MBB, MBB.begin(), V8::SAVEri, 2,
+            V8::O6).addImm(NumBytes).addReg(V8::O6);
+  } else {
+    MachineBasicBlock::iterator InsertPt = MBB.begin();
+    // Emit this the hard way.  This clobbers G1 which we always know is 
+    // available here.
+    unsigned OffHi = (unsigned)NumBytes >> 10U;
+    BuildMI(MBB, InsertPt, V8::SETHIi, 1, V8::G1).addImm(OffHi);
+    // Emit G1 = G1 + I6
+    BuildMI(MBB, InsertPt, V8::ORri, 2, V8::G1)
+      .addReg(V8::G1).addImm(NumBytes & ((1 << 10)-1));
+    BuildMI(MBB, InsertPt, V8::SAVErr, 2,
+            V8::O6).addReg(V8::O6).addReg(V8::G1);
+  }
 }
 
 void SparcV8RegisterInfo::emitEpilogue(MachineFunction &MF,
index aa79e2837ea1b341828d8a016d7c459d1384f731..07012b1626fef513cd8451e790ed9a5deb72749e 100644 (file)
@@ -84,8 +84,10 @@ def FLAGS_REGS : RegisterClass<"V8", [FlagVT], 32, [ICC, FCC]> {
 //
 def IntRegs : RegisterClass<"V8", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7,
                                      I0, I1, I2, I3, I4, I5,
-                                     G1,
                                      O0, O1, O2, O3, O4, O5, O7,
+
+   // FIXME: G1 reserved for now for large imm generation by frame code.
+                                     G1,
                                      // Non-allocatable regs:
                                      G2, G3, G4, // FIXME: OK for use only in
                                                  // applications, not libraries.
@@ -102,7 +104,8 @@ def IntRegs : RegisterClass<"V8", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7,
     IntRegsClass::iterator
     IntRegsClass::allocation_order_end(MachineFunction &MF) const {
       // FIXME: These special regs should be taken out of the regclass!
-      return end()-10;  // Don't allocate special registers
+      return end()-10  // Don't allocate special registers
+         -1;  // FIXME: G1 reserved for large imm generation by frame code.
     }
   }];
 }
index 7b258567304afe95c3e29a3ddf3baff5244f13f4..49cbbc091d7ee3fd7752791fde31d28c72cca651 100644 (file)
@@ -96,15 +96,30 @@ SparcV8RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
 
   int FrameIndex = MI.getOperand(i).getFrameIndex();
 
-  // Replace frame index with a frame pointer reference
-  MI.SetMachineOperandReg (i, V8::I6);
-
   // Addressable stack objects are accessed using neg. offsets from %fp
   MachineFunction &MF = *MI.getParent()->getParent();
   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
                MI.getOperand(i+1).getImmedValue();
-  // note: Offset < 0
-  MI.SetMachineOperandConst (i+1, MachineOperand::MO_SignExtendedImmed, Offset);
+
+  // Replace frame index with a frame pointer reference.
+  if (Offset >= -4096 && Offset <= 4095) {
+    // If the offset is small enough to fit in the immediate field, directly
+    // encode it.
+    MI.SetMachineOperandReg(i, V8::I6);
+    MI.SetMachineOperandConst(i+1, MachineOperand::MO_SignExtendedImmed,Offset);
+  } else {
+    // Otherwise, emit a G1 = SETHI %hi(offset).  FIXME: it would be better to 
+    // scavenge a register here instead of reserving G1 all of the time.
+    unsigned OffHi = (unsigned)Offset >> 10U;
+    BuildMI(*MI.getParent(), II, V8::SETHIi, 1, V8::G1).addImm(OffHi);
+    // Emit G1 = G1 + I6
+    BuildMI(*MI.getParent(), II, V8::ADDrr, 2, 
+            V8::G1).addReg(V8::G1).addReg(V8::I6);
+    // Insert: G1+%lo(offset) into the user.
+    MI.SetMachineOperandReg(i, V8::I1);
+    MI.SetMachineOperandConst(i+1, MachineOperand::MO_SignExtendedImmed,
+                              Offset & ((1 << 10)-1));
+  }
 }
 
 void SparcV8RegisterInfo::
@@ -128,8 +143,23 @@ void SparcV8RegisterInfo::emitPrologue(MachineFunction &MF) const {
   // Round up to next doubleword boundary -- a double-word boundary
   // is required by the ABI.
   NumBytes = (NumBytes + 7) & ~7;
-  BuildMI(MBB, MBB.begin(), V8::SAVEri, 2,
-          V8::O6).addImm(-NumBytes).addReg(V8::O6);
+  NumBytes = -NumBytes;
+  
+  if (NumBytes >= -4096) {
+    BuildMI(MBB, MBB.begin(), V8::SAVEri, 2,
+            V8::O6).addImm(NumBytes).addReg(V8::O6);
+  } else {
+    MachineBasicBlock::iterator InsertPt = MBB.begin();
+    // Emit this the hard way.  This clobbers G1 which we always know is 
+    // available here.
+    unsigned OffHi = (unsigned)NumBytes >> 10U;
+    BuildMI(MBB, InsertPt, V8::SETHIi, 1, V8::G1).addImm(OffHi);
+    // Emit G1 = G1 + I6
+    BuildMI(MBB, InsertPt, V8::ORri, 2, V8::G1)
+      .addReg(V8::G1).addImm(NumBytes & ((1 << 10)-1));
+    BuildMI(MBB, InsertPt, V8::SAVErr, 2,
+            V8::O6).addReg(V8::O6).addReg(V8::G1);
+  }
 }
 
 void SparcV8RegisterInfo::emitEpilogue(MachineFunction &MF,
index aa79e2837ea1b341828d8a016d7c459d1384f731..07012b1626fef513cd8451e790ed9a5deb72749e 100644 (file)
@@ -84,8 +84,10 @@ def FLAGS_REGS : RegisterClass<"V8", [FlagVT], 32, [ICC, FCC]> {
 //
 def IntRegs : RegisterClass<"V8", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7,
                                      I0, I1, I2, I3, I4, I5,
-                                     G1,
                                      O0, O1, O2, O3, O4, O5, O7,
+
+   // FIXME: G1 reserved for now for large imm generation by frame code.
+                                     G1,
                                      // Non-allocatable regs:
                                      G2, G3, G4, // FIXME: OK for use only in
                                                  // applications, not libraries.
@@ -102,7 +104,8 @@ def IntRegs : RegisterClass<"V8", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7,
     IntRegsClass::iterator
     IntRegsClass::allocation_order_end(MachineFunction &MF) const {
       // FIXME: These special regs should be taken out of the regclass!
-      return end()-10;  // Don't allocate special registers
+      return end()-10  // Don't allocate special registers
+         -1;  // FIXME: G1 reserved for large imm generation by frame code.
     }
   }];
 }