Move all the code that creates code generation passes from Sparc.cpp to
authorVikram S. Adve <vadve@cs.uiuc.edu>
Mon, 16 Sep 2002 15:39:26 +0000 (15:39 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Mon, 16 Sep 2002 15:39:26 +0000 (15:39 +0000)
TargetMachine.cpp, since it is entirely machine-independent.
Also, add options to disable optional back-end passes (preselection and
instr. scheduling).

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

lib/Target/SparcV9/SparcV9Internals.h
lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp
lib/Target/SparcV9/SparcV9TargetMachine.cpp
lib/Target/TargetMachine.cpp

index 1d9641d013e9198bc627b2ac4016dd0e9b96a4a8..4ff60644cd506be2baa6017638ec2f17dc48f2fe 100644 (file)
@@ -21,8 +21,6 @@ class UltraSparc;
 class PhyRegAlloc;
 class Pass;
 
-Pass *createPrologEpilogCodeInserter(TargetMachine &TM);
-
 // OpCodeMask definitions for the Sparc V9
 // 
 const OpCodeMask       Immed           = 0x00002000; // immed or reg operand?
@@ -88,7 +86,7 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
 
   //
   // All immediate constants are in position 1 except the
-  // store instructions.
+  // store instructions and SETxx.
   // 
   virtual int getImmedConstantPos(MachineOpCode opCode) const {
     bool ignore;
@@ -96,7 +94,11 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
       {
         assert(! this->isStore((MachineOpCode) STB - 1)); // 1st  store opcode
         assert(! this->isStore((MachineOpCode) STXFSR+1));// last store opcode
-        return (opCode >= STB && opCode <= STXFSR)? 2 : 1;
+        if (opCode==SETSW || opCode==SETUW || opCode==SETX || opCode==SETHI)
+          return 0;
+        if (opCode >= STB && opCode <= STXFSR)
+          return 2;
+        return 1;
       }
     else
       return -1;
@@ -113,6 +115,13 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
     return (opCode == FCMPS || opCode == FCMPD || opCode == FCMPQ);
   }
 
+  //-------------------------------------------------------------------------
+  // Queries about representation of LLVM quantities (e.g., constants)
+  //-------------------------------------------------------------------------
+
+  virtual bool ConstantMayNotFitInImmedField(const Constant* CV,
+                                             const Instruction* I) const;
+
   //-------------------------------------------------------------------------
   // Code generation support for creating individual machine instructions
   //-------------------------------------------------------------------------
@@ -538,13 +547,22 @@ public:
   UltraSparcFrameInfo(const TargetMachine &tgt) : MachineFrameInfo(tgt) {}
   
 public:
+  // These methods provide constant parameters of the frame layout.
+  // 
   int  getStackFrameSizeAlignment() const { return StackFrameSizeAlignment;}
   int  getMinStackFrameSize()       const { return MinStackFrameSize; }
   int  getNumFixedOutgoingArgs()    const { return NumFixedOutgoingArgs; }
   int  getSizeOfEachArgOnStack()    const { return SizeOfEachArgOnStack; }
   bool argsOnStackHaveFixedSize()   const { return true; }
 
-  //
+  // This method adjusts a stack offset to meet alignment rules of target.
+  // The fixed OFFSET (0x7ff) must be subtracted and the result aligned.
+  virtual int  adjustAlignment                  (int unalignedOffset,
+                                                 bool growUp,
+                                                 unsigned int align) const {
+    return unalignedOffset + (growUp? +1:-1)*((unalignedOffset-OFFSET) % align);
+  }
+
   // These methods compute offsets using the frame contents for a
   // particular function.  The frame contents are obtained from the
   // MachineCodeInfoForMethod object for the given function.
@@ -601,15 +619,58 @@ public:
   }
   
 private:
+  /*----------------------------------------------------------------------
+    This diagram shows the stack frame layout used by llc on Sparc V9.
+    Note that only the location of automatic variables, spill area,
+    temporary storage, and dynamically allocated stack area are chosen
+    by us.  The rest conform to the Sparc V9 ABI.
+    All stack addresses are offset by OFFSET = 0x7ff (2047).
+
+    Alignment assumpteions and other invariants:
+    (1) %sp+OFFSET and %fp+OFFSET are always aligned on 16-byte boundary
+    (2) Variables in automatic, spill, temporary, or dynamic regions
+        are aligned according to their size as in all memory accesses.
+    (3) Everything below the dynamically allocated stack area is only used
+        during a call to another function, so it is never needed when
+        the current function is active.  This is why space can be allocated
+        dynamically by incrementing %sp any time within the function.
+    
+    STACK FRAME LAYOUT:
+
+       ...
+       %fp+OFFSET+176      Optional extra incoming arguments# 1..N
+       %fp+OFFSET+168      Incoming argument #6
+       ...                 ...
+       %fp+OFFSET+128      Incoming argument #1
+       ...                 ...
+    ---%fp+OFFSET-0--------Bottom of caller's stack frame--------------------
+       %fp+OFFSET-8        Automatic variables <-- ****TOP OF STACK FRAME****
+                           Spill area
+                           Temporary storage
+       ...
+
+       %sp+OFFSET+176+8N   Bottom of dynamically allocated stack area
+       %sp+OFFSET+168+8N   Optional extra outgoing argument# N
+       ...                 ...
+       %sp+OFFSET+176      Optional extra outgoing argument# 1
+       %sp+OFFSET+168      Outgoing argument #6
+       ...                 ...
+       %sp+OFFSET+128      Outgoing argument #1
+       %sp+OFFSET+120      Save area for %i7
+       ...                 ...
+       %sp+OFFSET+0        Save area for %l0 <-- ****BOTTOM OF STACK FRAME****
+
+   *----------------------------------------------------------------------*/
+
   // All stack addresses must be offset by 0x7ff (2047) on Sparc V9.
   static const int OFFSET                                  = (int) 0x7ff;
   static const int StackFrameSizeAlignment                 =  16;
   static const int MinStackFrameSize                       = 176;
   static const int NumFixedOutgoingArgs                    =   6;
   static const int SizeOfEachArgOnStack                    =   8;
-  static const int StaticAreaOffsetFromFP                  =  0 + OFFSET;
   static const int FirstIncomingArgOffsetFromFP            = 128 + OFFSET;
   static const int FirstOptionalIncomingArgOffsetFromFP    = 176 + OFFSET;
+  static const int StaticAreaOffsetFromFP                  =   0 + OFFSET;
   static const int FirstOutgoingArgOffsetFromSP            = 128 + OFFSET;
   static const int FirstOptionalOutgoingArgOffsetFromSP    = 176 + OFFSET;
 };
@@ -655,16 +716,17 @@ public:
   virtual const MachineFrameInfo &getFrameInfo() const { return frameInfo; }
   virtual const MachineCacheInfo &getCacheInfo() const { return cacheInfo; }
 
-  //
-  // addPassesToEmitAssembly - Add passes to the specified pass manager to get
-  // assembly langage code emited.  For sparc, we have to do ...
-  //
-  virtual void addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
+  // getPrologEpilogCodeInserter - Inserts prolog/epilog code.
+  virtual Pass* getPrologEpilogInsertionPass();
 
-private:
-  Pass *getFunctionAsmPrinterPass(PassManager &PM, std::ostream &Out);
-  Pass *getModuleAsmPrinterPass(PassManager &PM, std::ostream &Out);
-  Pass *getEmitBytecodeToAsmPass(std::ostream &Out);
+  // getFunctionAsmPrinterPass - Writes out machine code for a single function
+  virtual Pass* getFunctionAsmPrinterPass(std::ostream &Out);
+
+  // getModuleAsmPrinterPass - Writes generated machine code to assembly file.
+  virtual Pass* getModuleAsmPrinterPass(std::ostream &Out);
+
+  // getEmitBytecodeToAsmPass - Emits final LLVM bytecode to assembly file.
+  virtual Pass* getEmitBytecodeToAsmPass(std::ostream &Out);
 };
 
 #endif
index a355f2ff6349d9564b2cce1f585af0127453c564..cfa71f663c3d881ea48c9e4db9ea8f14b1d57441 100644 (file)
@@ -162,6 +162,6 @@ void InsertPrologEpilogCode::InsertEpilogCode(Function &F)
   }
 }
 
-Pass *createPrologEpilogCodeInserter(TargetMachine &TM) {
-  return new InsertPrologEpilogCode(TM);
+Pass* UltraSparc::getPrologEpilogInsertionPass() {
+  return new InsertPrologEpilogCode(*this);
 }
index be9159a86cc782e9d768fc59c6a9212b96d66593..98c013100855fe21b0de0187efb62e853594f8c7 100644 (file)
@@ -7,16 +7,9 @@
 
 #include "SparcInternals.h"
 #include "llvm/Target/Sparc.h"
-#include "llvm/CodeGen/InstrScheduling.h"
-#include "llvm/CodeGen/InstrSelection.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineCodeForMethod.h"
-#include "llvm/CodeGen/RegisterAllocation.h"
-#include "llvm/Reoptimizer/Mapping/MappingInfo.h" 
-#include "llvm/Reoptimizer/Mapping/FInfo.h" 
 #include "llvm/Function.h"
 #include "llvm/BasicBlock.h"
-#include "llvm/PassManager.h"
+#include "llvm/CodeGen/MachineCodeForMethod.h"
 #include <iostream>
 using std::cerr;
 
@@ -90,6 +83,8 @@ UltraSparcFrameInfo::getDynamicAreaOffset(MachineCodeForMethod& mcInfo,
   // dynamic-size alloca.
   pos = false;
   unsigned int optArgsSize = mcInfo.getMaxOptionalArgsSize();
+  if (int extra = optArgsSize % getStackFrameSizeAlignment())
+    optArgsSize += (getStackFrameSizeAlignment() - extra);
   int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP;
   assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0);
   return offset;
@@ -120,84 +115,3 @@ UltraSparc::UltraSparc()
   maxAtomicMemOpWordSize = 8;
 }
 
-
-
-//===---------------------------------------------------------------------===//
-// GenerateCodeForTarget Pass
-// 
-// Native code generation for a specified target.
-//===---------------------------------------------------------------------===//
-
-class ConstructMachineCodeForFunction : public FunctionPass {
-  TargetMachine &Target;
-public:
-  inline ConstructMachineCodeForFunction(TargetMachine &T) : Target(T) {}
-
-  const char *getPassName() const {
-    return "Sparc ConstructMachineCodeForFunction";
-  }
-
-  bool runOnFunction(Function &F) {
-    MachineCodeForMethod::construct(&F, Target);
-    return false;
-  }
-};
-
-struct FreeMachineCodeForFunction : public FunctionPass {
-  const char *getPassName() const { return "Sparc FreeMachineCodeForFunction"; }
-
-  static void freeMachineCode(Instruction &I) {
-    MachineCodeForInstruction::destroy(&I);
-  }
-  
-  bool runOnFunction(Function &F) {
-    for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
-      for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
-        MachineCodeForInstruction::get(I).dropAllReferences();
-    
-    for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
-      for_each(FI->begin(), FI->end(), freeMachineCode);
-    
-    return false;
-  }
-};
-
-// addPassesToEmitAssembly - This method controls the entire code generation
-// process for the ultra sparc.
-//
-void UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) {
-  // Construct and initialize the MachineCodeForMethod object for this fn.
-  PM.add(new ConstructMachineCodeForFunction(*this));
-
-  PM.add(createInstructionSelectionPass(*this));
-
-  PM.add(createInstructionSchedulingWithSSAPass(*this));
-
-  PM.add(getRegisterAllocator(*this));
-  
-  //PM.add(new OptimizeLeafProcedures());
-  //PM.add(new DeleteFallThroughBranches());
-  //PM.add(new RemoveChainedBranches());    // should be folded with previous
-  //PM.add(new RemoveRedundantOps());       // operations with %g0, NOP, etc.
-  
-  PM.add(createPrologEpilogCodeInserter(*this));
-
-  PM.add(MappingInfoForFunction(Out));  
-
-  // Output assembly language to the .s file.  Assembly emission is split into
-  // two parts: Function output and Global value output.  This is because
-  // function output is pipelined with all of the rest of code generation stuff,
-  // allowing machine code representations for functions to be free'd after the
-  // function has been emitted.
-  //
-  PM.add(getFunctionAsmPrinterPass(PM, Out));
-  PM.add(new FreeMachineCodeForFunction());  // Free stuff no longer needed
-  // Emit Module level assembly after all of the functions have been processed.
-  PM.add(getModuleAsmPrinterPass(PM, Out));
-
-  // Emit bytecode to the sparc assembly file into its special section next
-  PM.add(getEmitBytecodeToAsmPass(Out));
-  PM.add(getFunctionInfo(Out)); 
-}
-
index 69c7cfd428343309aa8fc4ca39deeae976c5be16..84149f8934b131a9b2061b9e0057d776cde7b1e3 100644 (file)
@@ -8,8 +8,30 @@
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/MachineInstrInfo.h"
 #include "llvm/Target/MachineCacheInfo.h"
+#include "llvm/CodeGen/PreSelection.h"
+#include "llvm/CodeGen/InstrSelection.h"
+#include "llvm/CodeGen/InstrScheduling.h"
+#include "llvm/CodeGen/RegisterAllocation.h"
+#include "llvm/CodeGen/MachineCodeForMethod.h"
+#include "llvm/CodeGen/MachineCodeForInstruction.h"
+#include "llvm/Reoptimizer/Mapping/MappingInfo.h" 
+#include "llvm/Reoptimizer/Mapping/FInfo.h" 
+#include "llvm/Transforms/Scalar.h"
+#include "Support/CommandLine.h"
+#include "llvm/PassManager.h"
+#include "llvm/Function.h"
 #include "llvm/DerivedTypes.h"
 
+//---------------------------------------------------------------------------
+// Command line options to control choice of code generation passes.
+//---------------------------------------------------------------------------
+
+static cl::opt<bool> DisablePreSelect("nopreselect",
+                                      cl::desc("Disable preselection pass"));
+
+static cl::opt<bool> DisableSched("nosched",
+                                  cl::desc("Disable local scheduling pass"));
+
 //---------------------------------------------------------------------------
 // class TargetMachine
 // 
@@ -44,6 +66,99 @@ TargetMachine::findOptimalStorageSize(const Type* ty) const
 }
 
 
+//===---------------------------------------------------------------------===//
+// Default code generation passes.
+// 
+// Native code generation for a specified target.
+//===---------------------------------------------------------------------===//
+
+class ConstructMachineCodeForFunction : public FunctionPass {
+  TargetMachine &Target;
+public:
+  inline ConstructMachineCodeForFunction(TargetMachine &T) : Target(T) {}
+
+  const char *getPassName() const {
+    return "ConstructMachineCodeForFunction";
+  }
+
+  bool runOnFunction(Function &F) {
+    MachineCodeForMethod::construct(&F, Target);
+    return false;
+  }
+};
+
+struct FreeMachineCodeForFunction : public FunctionPass {
+  const char *getPassName() const { return "FreeMachineCodeForFunction"; }
+
+  static void freeMachineCode(Instruction &I) {
+    MachineCodeForInstruction::destroy(&I);
+  }
+  
+  bool runOnFunction(Function &F) {
+    for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
+      for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
+        MachineCodeForInstruction::get(I).dropAllReferences();
+    
+    for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
+      for_each(FI->begin(), FI->end(), freeMachineCode);
+    
+    return false;
+  }
+};
+
+// addPassesToEmitAssembly - This method controls the entire code generation
+// process for the ultra sparc.
+//
+void
+TargetMachine::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out)
+{
+  // Construct and initialize the MachineCodeForMethod object for this fn.
+  PM.add(new ConstructMachineCodeForFunction(*this));
+
+  // Specialize LLVM code for this target machine and then
+  // run basic dataflow optimizations on LLVM code.
+  if (!DisablePreSelect)
+    {
+      PM.add(createPreSelectionPass(*this));
+      PM.add(createReassociatePass());
+      PM.add(createGCSEPass());
+      PM.add(createLICMPass());
+    }
+
+  PM.add(createInstructionSelectionPass(*this));
+
+  if (!DisableSched)
+    PM.add(createInstructionSchedulingWithSSAPass(*this));
+
+  PM.add(getRegisterAllocator(*this));
+
+  //PM.add(new OptimizeLeafProcedures());
+  //PM.add(new DeleteFallThroughBranches());
+  //PM.add(new RemoveChainedBranches());    // should be folded with previous
+  //PM.add(new RemoveRedundantOps());       // operations with %g0, NOP, etc.
+
+  PM.add(getPrologEpilogInsertionPass());
+
+  PM.add(MappingInfoForFunction(Out));  
+
+  // Output assembly language to the .s file.  Assembly emission is split into
+  // two parts: Function output and Global value output.  This is because
+  // function output is pipelined with all of the rest of code generation stuff,
+  // allowing machine code representations for functions to be free'd after the
+  // function has been emitted.
+  //
+  PM.add(getFunctionAsmPrinterPass(Out));
+  PM.add(new FreeMachineCodeForFunction());  // Free stuff no longer needed
+
+  // Emit Module level assembly after all of the functions have been processed.
+  PM.add(getModuleAsmPrinterPass(Out));
+
+  // Emit bytecode to the assembly file into its special section next
+  PM.add(getEmitBytecodeToAsmPass(Out));
+  PM.add(getFunctionInfo(Out)); 
+}
+
+
 //---------------------------------------------------------------------------
 // class MachineInstructionInfo
 //     Interface to description of machine instructions
@@ -79,6 +194,10 @@ MachineInstrInfo::constantFitsInImmedField(MachineOpCode opCode,
   uint64_t maxImmedValue = maxImmedConstant(opCode, isSignExtended);
   if (maxImmedValue != 0)
     {
+      // NEED TO HANDLE UNSIGNED VALUES SINCE THEY MAY BECOME MUCH
+      // SMALLER AFTER CASTING TO SIGN-EXTENDED int, short, or char.
+      // See CreateUIntSetInstruction in SparcInstrInfo.cpp.
+      
       // Now check if the constant fits
       if (intValue <= (int64_t) maxImmedValue &&
          intValue >= -((int64_t) maxImmedValue+1))