diff options
-rw-r--r-- | include/llvm/Target/MachineInstrInfo.h | 23 | ||||
-rw-r--r-- | include/llvm/Target/TargetInstrInfo.h | 23 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9InstrInfo.cpp | 79 |
3 files changed, 125 insertions, 0 deletions
diff --git a/include/llvm/Target/MachineInstrInfo.h b/include/llvm/Target/MachineInstrInfo.h index 855840caf7..24d1363453 100644 --- a/include/llvm/Target/MachineInstrInfo.h +++ b/include/llvm/Target/MachineInstrInfo.h @@ -9,6 +9,8 @@ #include "Support/NonCopyable.h" #include "Support/DataTypes.h" +#include "llvm/Constant.h" +#include "llvm/DerivedTypes.h" #include <string> #include <vector> @@ -240,6 +242,27 @@ public: } //------------------------------------------------------------------------- + // Queries about representation of LLVM quantities (e.g., constants) + //------------------------------------------------------------------------- + + // Test if this type of constant must be loaded from memory into + // a register, i.e., cannot be set bitwise in register and cannot + // use immediate fields of instructions. Note that this only makes + // sense for primitive types. + virtual bool ConstantTypeMustBeLoaded(const Constant* CV) const { + assert(CV->getType()->isPrimitiveType() || isa<PointerType>(CV->getType())); + return !(CV->getType()->isIntegral() || isa<PointerType>(CV->getType())); + } + + // Test if this constant may not fit in the immediate field of the + // machine instructions (probably) generated for this instruction. + // + virtual bool ConstantMayNotFitInImmedField(const Constant* CV, + const Instruction* I) const { + return true; // safe but very conservative + } + + //------------------------------------------------------------------------- // Code generation support for creating individual machine instructions //------------------------------------------------------------------------- diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 855840caf7..24d1363453 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -9,6 +9,8 @@ #include "Support/NonCopyable.h" #include "Support/DataTypes.h" +#include "llvm/Constant.h" +#include "llvm/DerivedTypes.h" #include <string> #include <vector> @@ -240,6 +242,27 @@ public: } //------------------------------------------------------------------------- + // Queries about representation of LLVM quantities (e.g., constants) + //------------------------------------------------------------------------- + + // Test if this type of constant must be loaded from memory into + // a register, i.e., cannot be set bitwise in register and cannot + // use immediate fields of instructions. Note that this only makes + // sense for primitive types. + virtual bool ConstantTypeMustBeLoaded(const Constant* CV) const { + assert(CV->getType()->isPrimitiveType() || isa<PointerType>(CV->getType())); + return !(CV->getType()->isIntegral() || isa<PointerType>(CV->getType())); + } + + // Test if this constant may not fit in the immediate field of the + // machine instructions (probably) generated for this instruction. + // + virtual bool ConstantMayNotFitInImmedField(const Constant* CV, + const Instruction* I) const { + return true; // safe but very conservative + } + + //------------------------------------------------------------------------- // Code generation support for creating individual machine instructions //------------------------------------------------------------------------- diff --git a/lib/Target/SparcV9/SparcV9InstrInfo.cpp b/lib/Target/SparcV9/SparcV9InstrInfo.cpp index ffec82445d..6a1373174e 100644 --- a/lib/Target/SparcV9/SparcV9InstrInfo.cpp +++ b/lib/Target/SparcV9/SparcV9InstrInfo.cpp @@ -11,6 +11,7 @@ #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(*) @@ -258,6 +259,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<unsigned int> MaxConstantsTable(Instruction::NumOtherOps); + +static int +MaxConstantForInstr(unsigned llvmOpCode) +{ + int modelOpCode = -1; + + if (llvmOpCode >= Instruction::FirstBinaryOp && + llvmOpCode < Instruction::NumBinaryOps) + 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::NumOtherOps && + "assignments below will be illegal!"); + for (op = Instruction::FirstTermOp; op < Instruction::NumTermOps; ++op) + MaxConstantsTable[op] = MaxConstantForInstr(op); + for (op = Instruction::FirstBinaryOp; op < Instruction::NumBinaryOps; ++op) + MaxConstantsTable[op] = MaxConstantForInstr(op); + for (op = Instruction::FirstMemoryOp; op < Instruction::NumMemoryOps; ++op) + MaxConstantsTable[op] = MaxConstantForInstr(op); + for (op = Instruction::FirstOtherOp; op < Instruction::NumOtherOps; ++op) + MaxConstantsTable[op] = MaxConstantForInstr(op); +} + + +//--------------------------------------------------------------------------- // class UltraSparcInstrInfo // // Purpose: @@ -273,6 +329,29 @@ UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt) /*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)) + return (U->getValue() > MaxConstantsTable[I->getOpcode()]); + + if (const ConstantSInt* S = dyn_cast<ConstantSInt>(CV)) + return (labs(S->getValue()) > (int) MaxConstantsTable[I->getOpcode()]); + + if (isa<ConstantBool>(CV)) + return (1U > MaxConstantsTable[I->getOpcode()]); + + return true; } // |