diff --git a/include/llvm/Target/MachineInstrInfo.h b/include/llvm/Target/MachineInstrInfo.h index 855840caf7f..24d13634531 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 #include @@ -239,6 +241,27 @@ public: return getDescriptor(opCode).maxImmedConst; } + //------------------------------------------------------------------------- + // 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(CV->getType())); + return !(CV->getType()->isIntegral() || isa(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 855840caf7f..24d13634531 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 #include @@ -239,6 +241,27 @@ public: return getDescriptor(opCode).maxImmedConst; } + //------------------------------------------------------------------------- + // 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(CV->getType())); + return !(CV->getType()->isIntegral() || isa(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 ffec82445dc..6a1373174e0 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 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 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 // @@ -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(CV)) // can always use %g0 + return false; + + if (const ConstantUInt* U = dyn_cast(CV)) + return (U->getValue() > MaxConstantsTable[I->getOpcode()]); + + if (const ConstantSInt* S = dyn_cast(CV)) + return (labs(S->getValue()) > (int) MaxConstantsTable[I->getOpcode()]); + + if (isa(CV)) + return (1U > MaxConstantsTable[I->getOpcode()]); + + return true; } //