#include "Support/NonCopyable.h"
#include "Support/DataTypes.h"
+#include "llvm/Constant.h"
+#include "llvm/DerivedTypes.h"
#include <string>
#include <vector>
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<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
//-------------------------------------------------------------------------
#include "Support/NonCopyable.h"
#include "Support/DataTypes.h"
+#include "llvm/Constant.h"
+#include "llvm/DerivedTypes.h"
#include <string>
#include <vector>
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<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
//-------------------------------------------------------------------------
#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(*)
}
+//---------------------------------------------------------------------------
+// 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
//
/*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;
}
//