//---------------------------------------------------------------------------
-// Function GetConstantValueAsUnsignedInt
-// Function GetConstantValueAsSignedInt
+// Function ConvertConstantToIntType
//
-// Convenience functions to get the value of an integral constant, for an
-// appropriate integer or non-integer type that can be held in a signed
-// or unsigned integer respectively. The type of the argument must be
-// the following:
-// Signed or unsigned integer
-// Boolean
-// Pointer
+// Function to get the value of an integral constant in the form
+// that must be put into the machine register. The specified constant is
+// interpreted as (i.e., converted if necessary to) the specified destination
+// type. The result is always returned as an uint64_t, since the representation
+// of int64_t and uint64_t are identical. The argument can be any known const.
//
// isValidConstant is set to true if a valid constant was found.
//---------------------------------------------------------------------------
-static uint64_t
-GetConstantValueAsUnsignedInt(const Value *V,
- bool &isValidConstant)
+uint64_t
+UltraSparcInstrInfo::ConvertConstantToIntType(const TargetMachine &target,
+ const Value *V,
+ const Type *destType,
+ bool &isValidConstant) const
{
- isValidConstant = true;
+ isValidConstant = false;
+ uint64_t C = 0;
- if (isa<Constant>(V))
- if (const ConstantBool *CB = dyn_cast<ConstantBool>(V))
- return (int64_t)CB->getValue();
- else if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
- return CI->getRawValue();
+ if (! destType->isIntegral() && ! isa<PointerType>(destType))
+ return C;
- isValidConstant = false;
- return 0;
-}
+ if (! isa<Constant>(V))
+ return C;
-int64_t
-GetConstantValueAsSignedInt(const Value *V, bool &isValidConstant)
-{
- uint64_t C = GetConstantValueAsUnsignedInt(V, isValidConstant);
+ // ConstantPointerRef: no conversions needed: get value and return it
+ if (const ConstantPointerRef* CPR = dyn_cast<ConstantPointerRef>(V)) {
+ // A ConstantPointerRef is just a reference to GlobalValue.
+ isValidConstant = true; // may be overwritten by recursive call
+ return (CPR->isNullValue()? 0
+ : ConvertConstantToIntType(target, CPR->getValue(), destType,
+ isValidConstant));
+ }
+
+ // ConstantBool: no conversions needed: get value and return it
+ if (const ConstantBool *CB = dyn_cast<ConstantBool>(V)) {
+ isValidConstant = true;
+ return (uint64_t) CB->getValue();
+ }
+
+ // For other types of constants, some conversion may be needed.
+ // First, extract the constant operand according to its own type
+ if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ switch(CE->getOpcode()) {
+ case Instruction::Cast: // recursively get the value as cast
+ C = ConvertConstantToIntType(target, CE->getOperand(0), CE->getType(),
+ isValidConstant);
+ break;
+ default: // not simplifying other ConstantExprs
+ break;
+ }
+ else if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ isValidConstant = true;
+ C = CI->getRawValue();
+ }
+ else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
+ isValidConstant = true;
+ double fC = CFP->getValue();
+ C = (destType->isSigned()? (uint64_t) (int64_t) fC
+ : (uint64_t) fC);
+ }
+
+ // Now if a valid value was found, convert it to destType.
if (isValidConstant) {
- if (V->getType()->isSigned() || C < INT64_MAX) // safe to cast to signed
- return (int64_t) C;
- else
- isValidConstant = false;
+ unsigned opSize = target.getTargetData().getTypeSize(V->getType());
+ unsigned destSize = target.getTargetData().getTypeSize(destType);
+ uint64_t maskHi = (destSize < 8)? (1U << 8*destSize) - 1 : ~0;
+ assert(opSize <= 8 && destSize <= 8 && ">8-byte int type unexpected");
+
+ if (destType->isSigned()) {
+ if (opSize > destSize) // operand is larger than dest:
+ C = C & maskHi; // mask high bits
+
+ if (opSize > destSize ||
+ (opSize == destSize && ! V->getType()->isSigned()))
+ if (C & (1U << (8*destSize - 1)))
+ C = C | ~maskHi; // sign-extend from destSize to 64 bits
+ }
+ else {
+ if (opSize > destSize || (V->getType()->isSigned() && destSize < 8)) {
+ // operand is larger than dest,
+ // OR both are equal but smaller than the full register size
+ // AND operand is signed, so it may have extra sign bits:
+ // mask high bits
+ C = C & maskHi;
+ }
+ }
}
- return 0;
+
+ return C;
}
//
const Type* valType = val->getType();
- // Unfortunate special case: a ConstantPointerRef is just a
- // reference to GlobalValue.
- if (isa<ConstantPointerRef>(val))
+ // A ConstantPointerRef is just a reference to GlobalValue.
+ while (isa<ConstantPointerRef>(val))
val = cast<ConstantPointerRef>(val)->getValue();
if (isa<GlobalValue>(val)) {
TmpInstruction* tmpReg =
new TmpInstruction(mcfi, PointerType::get(val->getType()), val);
CreateSETXLabel(target, val, tmpReg, dest, mvec);
- } else if (valType->isIntegral()) {
- bool isValidConstant;
- unsigned opSize = target.getTargetData().getTypeSize(val->getType());
- unsigned destSize = target.getTargetData().getTypeSize(dest->getType());
-
- if (! dest->getType()->isSigned()) {
- uint64_t C = GetConstantValueAsUnsignedInt(val, isValidConstant);
- assert(isValidConstant && "Unrecognized constant");
+ return;
+ }
- if (opSize > destSize || (val->getType()->isSigned() && destSize < 8)) {
- // operand is larger than dest,
- // OR both are equal but smaller than the full register size
- // AND operand is signed, so it may have extra sign bits:
- // mask high bits
- C = C & ((1U << 8*destSize) - 1);
- }
+ bool isValid;
+ uint64_t C = ConvertConstantToIntType(target, val, dest->getType(), isValid);
+ if (isValid) {
+ if (dest->getType()->isSigned())
CreateUIntSetInstruction(target, C, dest, mvec, mcfi);
- } else {
- int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
- assert(isValidConstant && "Unrecognized constant");
-
- if (opSize > destSize)
- // operand is larger than dest: mask high bits
- C = C & ((1U << 8*destSize) - 1);
+ else
+ CreateIntSetInstruction(target, (int64_t) C, dest, mvec, mcfi);
- if (opSize > destSize ||
- (opSize == destSize && !val->getType()->isSigned()))
- // sign-extend from destSize to 64 bits
- C = ((C & (1U << (8*destSize - 1)))
- ? C | ~((1U << 8*destSize) - 1)
- : C);
-
- CreateIntSetInstruction(target, C, dest, mvec, mcfi);
- }
} else {
// Make an instruction sequence to load the constant, viz:
// SETX <addr-of-constant>, tmpReg, addrReg
// Create another TmpInstruction for the address register
TmpInstruction* addrReg =
new TmpInstruction(mcfi, PointerType::get(val->getType()), val);
-
+
// Put the address (a symbolic name) into a register
CreateSETXLabel(target, val, tmpReg, addrReg, mvec);
-
+
// Generate the load instruction
int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
unsigned Opcode = ChooseLoadInstruction(val->getType());
if (resultType->isInteger() || isa<PointerType>(resultType)) {
bool isValidConst;
- int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
+ int64_t C = (int64_t) target.getInstrInfo().ConvertConstantToIntType(target,
+ constOp, constOp->getType(), isValidConst);
if (isValidConst) {
unsigned pow;
bool needNeg = false;
if (resultType->isInteger()) {
unsigned pow;
bool isValidConst;
- int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
+ int64_t C = (int64_t) target.getInstrInfo().ConvertConstantToIntType(target,
+ constOp, constOp->getType(), isValidConst);
if (isValidConst) {
bool needNeg = false;
if (C < 0) {
needNeg = true;
C = -C;
}
-
+
if (C == 1) {
mvec.push_back(BuildMI(V9::ADDr, 3).addReg(LHS).addMReg(ZeroReg)
.addRegDef(destVal));
// compile time if the total size is a known constant.
if (isa<Constant>(numElementsVal)) {
bool isValid;
- int64_t numElem = GetConstantValueAsSignedInt(numElementsVal, isValid);
+ int64_t numElem = (int64_t) target.getInstrInfo().
+ ConvertConstantToIntType(target, numElementsVal,
+ numElementsVal->getType(), isValid);
assert(isValid && "Unexpectedly large array dimension in alloca!");
int64_t total = numElem * tsize;
if (int extra= total % target.getFrameInfo().getStackFrameSizeAlignment())
if ((constVal->getType()->isInteger()
|| isa<PointerType>(constVal->getType()))
- && GetConstantValueAsSignedInt(constVal, isValidConst) == 0
+ && target.getInstrInfo().ConvertConstantToIntType(target,
+ constVal, constVal->getType(), isValidConst) == 0
&& isValidConst)
{
// That constant is a zero after all...
if ((constVal->getType()->isInteger()
|| isa<PointerType>(constVal->getType()))
- && GetConstantValueAsSignedInt(constVal, isValidConst) == 0
+ && target.getInstrInfo().ConvertConstantToIntType(target,
+ constVal, constVal->getType(), isValidConst) == 0
&& isValidConst)
{
// That constant is an integer zero after all...