*** empty log message ***
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9InstrInfo.cpp
index ffec82445dce15f4038f0934099be25c16b1d806..134bdacae07ce6faf68a3ad4dbb2c5605cfb0651 100644 (file)
@@ -6,11 +6,12 @@
 #include "SparcInstrSelectionSupport.h"
 #include "llvm/CodeGen/InstrSelection.h"
 #include "llvm/CodeGen/InstrSelectionSupport.h"
-#include "llvm/CodeGen/MachineCodeForMethod.h"
+#include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineCodeForInstruction.h"
 #include "llvm/Function.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
+#include <stdlib.h>
 using std::vector;
 
 static const uint32_t MAXLO   = (1 << 10) - 1; // set bits set by %lo(*)
@@ -257,6 +258,61 @@ CreateIntSetInstruction(const TargetMachine& target,
 }
 
 
+//---------------------------------------------------------------------------
+// Create a table of LLVM opcode -> max. immediate constant likely to
+// be usable for that operation.
+//---------------------------------------------------------------------------
+
+// Entry == 0 ==> no immediate constant field exists at all.
+// Entry >  0 ==> abs(immediate constant) <= Entry
+// 
+vector<int> MaxConstantsTable(Instruction::OtherOpsEnd);
+
+static int
+MaxConstantForInstr(unsigned llvmOpCode)
+{
+  int modelOpCode = -1;
+
+  if (llvmOpCode >= Instruction::BinaryOpsBegin &&
+      llvmOpCode <  Instruction::BinaryOpsEnd)
+    modelOpCode = ADD;
+  else
+    switch(llvmOpCode) {
+    case Instruction::Ret:   modelOpCode = JMPLCALL; break;
+
+    case Instruction::Malloc:         
+    case Instruction::Alloca:         
+    case Instruction::GetElementPtr:  
+    case Instruction::PHINode:       
+    case Instruction::Cast:
+    case Instruction::Call:  modelOpCode = ADD; break;
+
+    case Instruction::Shl:
+    case Instruction::Shr:   modelOpCode = SLLX; break;
+
+    default: break;
+    };
+
+  return (modelOpCode < 0)? 0: SparcMachineInstrDesc[modelOpCode].maxImmedConst;
+}
+
+static void
+InitializeMaxConstantsTable()
+{
+  unsigned op;
+  assert(MaxConstantsTable.size() == Instruction::OtherOpsEnd &&
+         "assignments below will be illegal!");
+  for (op = Instruction::TermOpsBegin; op < Instruction::TermOpsEnd; ++op)
+    MaxConstantsTable[op] = MaxConstantForInstr(op);
+  for (op = Instruction::BinaryOpsBegin; op < Instruction::BinaryOpsEnd; ++op)
+    MaxConstantsTable[op] = MaxConstantForInstr(op);
+  for (op = Instruction::MemoryOpsBegin; op < Instruction::MemoryOpsEnd; ++op)
+    MaxConstantsTable[op] = MaxConstantForInstr(op);
+  for (op = Instruction::OtherOpsBegin; op < Instruction::OtherOpsEnd; ++op)
+    MaxConstantsTable[op] = MaxConstantForInstr(op);
+}
+
+
 //---------------------------------------------------------------------------
 // class UltraSparcInstrInfo 
 // 
@@ -268,11 +324,35 @@ CreateIntSetInstruction(const TargetMachine& target,
 //---------------------------------------------------------------------------
 
 /*ctor*/
-UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
-  : MachineInstrInfo(tgt, SparcMachineInstrDesc,
+UltraSparcInstrInfo::UltraSparcInstrInfo()
+  : MachineInstrInfo(SparcMachineInstrDesc,
                     /*descSize = */ NUM_TOTAL_OPCODES,
                     /*numRealOpCodes = */ NUM_REAL_OPCODES)
 {
+  InitializeMaxConstantsTable();
+}
+
+bool
+UltraSparcInstrInfo::ConstantMayNotFitInImmedField(const Constant* CV,
+                                                   const Instruction* I) const
+{
+  if (I->getOpcode() >= MaxConstantsTable.size()) // user-defined op (or bug!)
+    return true;
+
+  if (isa<ConstantPointerNull>(CV))               // can always use %g0
+    return false;
+
+  if (const ConstantUInt* U = dyn_cast<ConstantUInt>(CV))
+    /* Large unsigned longs may really just be small negative signed longs */
+    return (labs((int64_t) U->getValue()) > MaxConstantsTable[I->getOpcode()]);
+
+  if (const ConstantSInt* S = dyn_cast<ConstantSInt>(CV))
+    return (labs(S->getValue()) > MaxConstantsTable[I->getOpcode()]);
+
+  if (isa<ConstantBool>(CV))
+    return (1 > MaxConstantsTable[I->getOpcode()]);
+
+  return true;
 }
 
 // 
@@ -281,7 +361,7 @@ UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
 // GlobalValue, viz., the constant address of a global variable or function.
 // The generated instructions are returned in `mvec'.
 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineCodeForMethod.
+// Any stack space required is allocated via MachineFunction.
 // 
 void
 UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
@@ -301,6 +381,11 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
   // 
   const Type* valType = val->getType();
   
+  // Unfortunate special case: a ConstantPointerRef is just a
+  // reference to GlobalValue.
+  if (isa<ConstantPointerRef>(val))
+    val = cast<ConstantPointerRef>(val)->getValue();
+
   if (isa<GlobalValue>(val))
     {
       TmpInstruction* tmpReg =
@@ -376,7 +461,7 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
       mvec.push_back(MI);
       
       // Make sure constant is emitted to constant pool in assembly code.
-      MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
+      MachineFunction::get(F).addToConstantPool(cast<Constant>(val));
     }
 }
 
@@ -386,7 +471,7 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
 // val must be an integral type.  dest must be a Float or Double.
 // The generated instructions are returned in `mvec'.
 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineCodeForMethod.
+// Any stack space required is allocated via MachineFunction.
 // 
 void
 UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
@@ -402,7 +487,7 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
          && "Dest type must be float/double");
 
   // Get a stack slot to use for the copy
-  int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
+  int offset = MachineFunction::get(F).allocateLocalVar(target, val); 
 
   // Get the size of the source value being copied. 
   size_t srcSize = target.DataLayout.getTypeSize(val->getType());
@@ -418,10 +503,10 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
     { // sign- or zero-extend respectively
       storeVal = new TmpInstruction(storeType, val);
       if (val->getType()->isSigned())
-        CreateSignExtensionInstructions(target, F, val, 8*srcSize, storeVal,
+        CreateSignExtensionInstructions(target, F, val, storeVal, 8*srcSize,
                                         mvec, mcfi);
       else
-        CreateZeroExtensionInstructions(target, F, val, 8*srcSize, storeVal,
+        CreateZeroExtensionInstructions(target, F, val, storeVal, 8*srcSize,
                                         mvec, mcfi);
     }
   MachineInstr* store=new MachineInstr(ChooseStoreInstruction(storeType));
@@ -447,7 +532,7 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
 // `val' to an integer register `dest' by copying to memory and back.
 // The generated instructions are returned in `mvec'.
 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineCodeForMethod.
+// Any stack space required is allocated via MachineFunction.
 // 
 void
 UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
@@ -464,7 +549,7 @@ UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
   assert((destTy->isIntegral() || isa<PointerType>(destTy))
          && "Dest type must be integer, bool or pointer");
 
-  int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
+  int offset = MachineFunction::get(F).allocateLocalVar(target, val); 
 
   // Store instruction stores `val' to [%fp+offset].
   // The store opCode is based only the source value being copied.
@@ -494,7 +579,7 @@ UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
 // Create instruction(s) to copy src to dest, for arbitrary types
 // The generated instructions are returned in `mvec'.
 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineCodeForMethod.
+// Any stack space required is allocated via MachineFunction.
 // 
 void
 UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
@@ -561,27 +646,27 @@ CreateBitExtensionInstructions(bool signExtend,
                                const TargetMachine& target,
                                Function* F,
                                Value* srcVal,
-                               unsigned int srcSizeInBits,
-                               Value* dest,
+                               Value* destVal,
+                               unsigned int numLowBits,
                                vector<MachineInstr*>& mvec,
                                MachineCodeForInstruction& mcfi)
 {
   MachineInstr* M;
-  assert(srcSizeInBits <= 32 &&
-         "Hmmm... 32 < srcSizeInBits < 64 unexpected but could be handled.");
 
-  if (srcSizeInBits < 32)
+  assert(numLowBits <= 32 && "Otherwise, nothing should be done here!");
+
+  if (numLowBits < 32)
     { // SLL is needed since operand size is < 32 bits.
-      TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
-                                                srcVal, dest,"make32");
+      TmpInstruction *tmpI = new TmpInstruction(destVal->getType(),
+                                                srcVal, destVal, "make32");
       mcfi.addTemp(tmpI);
-      M = Create3OperandInstr_UImmed(SLLX, srcVal, 32-srcSizeInBits, tmpI);
+      M = Create3OperandInstr_UImmed(SLLX, srcVal, 32-numLowBits, tmpI);
       mvec.push_back(M);
       srcVal = tmpI;
     }
 
   M = Create3OperandInstr_UImmed(signExtend? SRA : SRL,
-                                 srcVal, 32-srcSizeInBits, dest);
+                                 srcVal, 32-numLowBits, destVal);
   mvec.push_back(M);
 }
 
@@ -590,20 +675,20 @@ CreateBitExtensionInstructions(bool signExtend,
 // from an arbitrary-sized integer value (sized in bits, not bytes).
 // The generated instructions are returned in `mvec'.
 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineCodeForMethod.
+// Any stack space required is allocated via MachineFunction.
 // 
 void
 UltraSparcInstrInfo::CreateSignExtensionInstructions(
                                         const TargetMachine& target,
                                         Function* F,
                                         Value* srcVal,
-                                        unsigned int srcSizeInBits,
-                                        Value* dest,
+                                        Value* destVal,
+                                        unsigned int numLowBits,
                                         vector<MachineInstr*>& mvec,
                                         MachineCodeForInstruction& mcfi) const
 {
   CreateBitExtensionInstructions(/*signExtend*/ true, target, F, srcVal,
-                                 srcSizeInBits, dest, mvec, mcfi);
+                                 destVal, numLowBits, mvec, mcfi);
 }
 
 
@@ -612,18 +697,18 @@ UltraSparcInstrInfo::CreateSignExtensionInstructions(
 // For SPARC v9, we sign-extend the given operand using SLL; SRL.
 // The generated instructions are returned in `mvec'.
 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineCodeForMethod.
+// Any stack space required is allocated via MachineFunction.
 // 
 void
 UltraSparcInstrInfo::CreateZeroExtensionInstructions(
                                         const TargetMachine& target,
                                         Function* F,
                                         Value* srcVal,
-                                        unsigned int srcSizeInBits,
-                                        Value* dest,
+                                        Value* destVal,
+                                        unsigned int numLowBits,
                                         vector<MachineInstr*>& mvec,
                                         MachineCodeForInstruction& mcfi) const
 {
   CreateBitExtensionInstructions(/*signExtend*/ false, target, F, srcVal,
-                                 srcSizeInBits, dest, mvec, mcfi);
+                                 destVal, numLowBits, mvec, mcfi);
 }