Add the necessary support to the ISel to allow targets to codegen the new
authorNate Begeman <natebegeman@mac.com>
Sun, 6 Nov 2005 09:00:38 +0000 (09:00 +0000)
committerNate Begeman <natebegeman@mac.com>
Sun, 6 Nov 2005 09:00:38 +0000 (09:00 +0000)
alignment information appropriately.  Includes code for PowerPC to support
fixed-size allocas with alignment larger than the stack.  Support for
arbitrarily aligned dynamic allocas coming soon.

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

include/llvm/CodeGen/MachineFrameInfo.h
lib/CodeGen/PrologEpilogInserter.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/PowerPC/PPCRegisterInfo.cpp

index 8f8a852480d8354211ddaee75587d385edc6898d..6720758e646b527495c9c0685588ab9f04ce3d4a 100644 (file)
@@ -85,6 +85,13 @@ class MachineFrameInfo {
   /// to be allocated on entry to the function.
   ///
   unsigned StackSize;
+  
+  /// MaxAlignment - The prolog/epilog code inserter may process objects 
+  /// that require greater alignment than the default alignment the target
+  /// provides. In these cases, MaxAlignment is set to the new alignment 
+  /// necessary to easily calculate fixed offsets for each stack object.
+  ///
+  unsigned MaxAlignment;
 
   /// HasCalls - Set to true if this function has any function calls.  This is
   /// only valid during and after prolog/epilog code insertion.
@@ -99,7 +106,7 @@ class MachineFrameInfo {
   unsigned MaxCallFrameSize;
 public:
   MachineFrameInfo() {
-    NumFixedObjects = StackSize = 0;
+    NumFixedObjects = StackSize = MaxAlignment = 0;
     HasVarSizedObjects = false;
     HasCalls = false;
     MaxCallFrameSize = 0;
@@ -163,6 +170,16 @@ public:
   ///
   void setStackSize(unsigned Size) { StackSize = Size; }
 
+  /// getMaxAlignment - Return the alignment in bytes that this function must be 
+  /// aligned to, which is greater than the default stack alignment provided by 
+  /// the target.
+  ///
+  unsigned getMaxAlignment() const { return MaxAlignment; }
+  
+  /// setMaxAlignment - Set the preferred alignment.
+  ///
+  void setMaxAlignment(unsigned Align) { MaxAlignment = Align; }
+  
   /// hasCalls - Return true if the current function has no function calls.
   /// This is only valid during or after prolog/epilog code emission.
   ///
index e38c740e8dd5aea9778a83305e04b4e2ea090db0..95932207a585caaaafa5d3f3ad823020866bf305 100644 (file)
@@ -258,6 +258,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
   MachineFrameInfo *FFI = Fn.getFrameInfo();
 
   unsigned StackAlignment = TFI.getStackAlignment();
+  unsigned MaxAlign = StackAlignment;
 
   // Start at the beginning of the local area.
   // The Offset is the distance from the stack top in the direction
@@ -295,9 +296,11 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
       Offset += FFI->getObjectSize(i);
 
     unsigned Align = FFI->getObjectAlignment(i);
-    assert(Align <= StackAlignment && "Cannot align stack object to higher "
-           "alignment boundary than the stack itself!");
-    Offset = (Offset+Align-1)/Align*Align;   // Adjust to Alignment boundary...
+    // If the alignment of this object is greater than that of the stack, then
+    // increase the stack alignment to match.
+    MaxAlign = std::max(MaxAlign, Align);
+    // Adjust to alignment boundary
+    Offset = (Offset+Align-1)/Align*Align;
 
     if (StackGrowsDown) {
       FFI->setObjectOffset(i, -Offset);        // Set the computed offset
@@ -315,6 +318,11 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
 
   // Set the final value of the stack pointer...
   FFI->setStackSize(Offset+TFI.getOffsetOfLocalArea());
+  // If we have a new stack alignment, set the preferred stack alignment so that
+  // the targets can do the appropriate thing to properly align the stack above
+  // the default alignment.
+  if (MaxAlign > StackAlignment)
+    FFI->setMaxAlignment(MaxAlign);
 }
 
 
index 3b5ef32e3c34f856566a8167ad24cb09e63a5ece..64256c963ebc8963146915d86a2c5e0c3ee81244 100644 (file)
@@ -147,7 +147,9 @@ FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli,
       if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(AI->getArraySize())) {
         const Type *Ty = AI->getAllocatedType();
         uint64_t TySize = TLI.getTargetData().getTypeSize(Ty);
-        unsigned Align = TLI.getTargetData().getTypeAlignment(Ty);
+        unsigned Align = 
+          std::max((unsigned)TLI.getTargetData().getTypeAlignment(Ty),
+                   AI->getAlignment());
 
         // If the alignment of the value is smaller than the size of the value,
         // and if the size of the value is particularly small (<= 8 bytes),
@@ -636,7 +638,8 @@ void SelectionDAGLowering::visitAlloca(AllocaInst &I) {
 
   const Type *Ty = I.getAllocatedType();
   uint64_t TySize = TLI.getTargetData().getTypeSize(Ty);
-  unsigned Align = TLI.getTargetData().getTypeAlignment(Ty);
+  unsigned Align = std::max((unsigned)TLI.getTargetData().getTypeAlignment(Ty),
+                            I.getAlignment());
 
   SDOperand AllocSize = getValue(I.getArraySize());
   MVT::ValueType IntPtr = TLI.getPointerTy();
index 658e294ec829db9f20daff17f0b5a91e84d4f84e..ae136cbc420a58bc449b1f55798a26973e78ff2c 100644 (file)
@@ -26,6 +26,7 @@
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/ADT/STLExtras.h"
 #include <cstdlib>
 #include <iostream>
@@ -294,6 +295,11 @@ void PPCRegisterInfo::emitPrologue(MachineFunction &MF) const {
 
   // Get the number of bytes to allocate from the FrameInfo
   unsigned NumBytes = MFI->getStackSize();
+  
+  // Get the alignments provided by the target, and the maximum alignment
+  // (if any) of the fixed frame objects.
+  unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
+  unsigned MaxAlign = MFI->getMaxAlignment();
 
   // If we have calls, we cannot use the red zone to store callee save registers
   // and we must set up a stack frame, so calculate the necessary size here.
@@ -307,14 +313,15 @@ void PPCRegisterInfo::emitPrologue(MachineFunction &MF) const {
   // If we are a leaf function, and use up to 224 bytes of stack space,
   // and don't have a frame pointer, then we do not need to adjust the stack
   // pointer (we fit in the Red Zone).
-  if ((NumBytes == 0) || (NumBytes <= 224 && !hasFP(MF) && !MFI->hasCalls())) {
+  if ((NumBytes == 0) || (NumBytes <= 224 && !hasFP(MF) && !MFI->hasCalls() &&
+                          MaxAlign <= TargetAlign)) {
     MFI->setStackSize(0);
     return;
   }
 
   // Add the size of R1 to  NumBytes size for the store of R1 to the bottom
   // of the stack and round the size to a multiple of the alignment.
-  unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
+  unsigned Align = std::max(TargetAlign, MaxAlign);
   unsigned GPRSize = 4;
   unsigned Size = hasFP(MF) ? GPRSize + GPRSize : GPRSize;
   NumBytes = (NumBytes+Size+Align-1)/Align*Align;
@@ -336,7 +343,23 @@ void PPCRegisterInfo::emitPrologue(MachineFunction &MF) const {
     MI = BuildMI(PPC::STWUX, 3).addReg(PPC::R1).addReg(PPC::R1).addReg(PPC::R0);
     MBB.insert(MBBI, MI);
   }
-
+  
+  // If there is a preferred stack alignment, align R1 now
+  // FIXME: If this ever matters, this could be made more efficient by folding
+  // this into the code above, so that we don't issue two store+update
+  // instructions.
+  if (MaxAlign > TargetAlign) {
+    assert(isPowerOf2_32(MaxAlign) && MaxAlign < 32767 && "Invalid alignment!");
+    MI = BuildMI(PPC::RLWINM, 4, PPC::R0).addReg(PPC::R1).addImm(0)
+      .addImm(32-Log2_32(MaxAlign)).addImm(31);
+    MBB.insert(MBBI, MI);
+    MI = BuildMI(PPC::SUBFIC, 2, PPC::R0).addReg(PPC::R0).addImm(MaxAlign);
+    MBB.insert(MBBI, MI);
+    MI = BuildMI(PPC::STWUX, 3).addReg(PPC::R1).addReg(PPC::R1).addReg(PPC::R0);
+    MBB.insert(MBBI, MI);
+  }
+  
+  // If there is a frame pointer, copy R1 (SP) into R31 (FP)
   if (hasFP(MF)) {
     MI = BuildMI(PPC::STW, 3).addReg(PPC::R31).addSImm(GPRSize).addReg(PPC::R1);
     MBB.insert(MBBI, MI);