mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-13 23:18:58 +00:00
Unify all constant evaluations that depend on register size
in ConvertConstantToIntType. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7395 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
deb9634f0e
commit
e6124d3b7c
@ -20,47 +20,97 @@ static const uint32_t MAXSIMM = (1 << 12) - 1; // set bits in simm13 field of OR
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
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();
|
||||
|
||||
isValidConstant = false;
|
||||
return 0;
|
||||
}
|
||||
uint64_t C = 0;
|
||||
|
||||
int64_t
|
||||
GetConstantValueAsSignedInt(const Value *V, bool &isValidConstant)
|
||||
{
|
||||
uint64_t C = GetConstantValueAsUnsignedInt(V, isValidConstant);
|
||||
if (isValidConstant) {
|
||||
if (V->getType()->isSigned() || C < INT64_MAX) // safe to cast to signed
|
||||
return (int64_t) C;
|
||||
else
|
||||
isValidConstant = false;
|
||||
if (! destType->isIntegral() && ! isa<PointerType>(destType))
|
||||
return C;
|
||||
|
||||
if (! isa<Constant>(V))
|
||||
return C;
|
||||
|
||||
// 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));
|
||||
}
|
||||
return 0;
|
||||
|
||||
// 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) {
|
||||
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 C;
|
||||
}
|
||||
|
||||
|
||||
@ -410,49 +460,25 @@ 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))
|
||||
// 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");
|
||||
else
|
||||
CreateIntSetInstruction(target, (int64_t) C, dest, mvec, mcfi);
|
||||
|
||||
if (opSize > destSize)
|
||||
// operand is larger than dest: mask high bits
|
||||
C = C & ((1U << 8*destSize) - 1);
|
||||
|
||||
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
|
||||
@ -465,10 +491,10 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
|
||||
// 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());
|
||||
|
@ -823,7 +823,8 @@ CreateMulConstInstruction(const TargetMachine &target, Function* F,
|
||||
|
||||
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;
|
||||
@ -976,14 +977,15 @@ CreateDivConstInstruction(TargetMachine &target,
|
||||
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));
|
||||
@ -1085,7 +1087,9 @@ CreateCodeForVariableSizeAlloca(const TargetMachine& target,
|
||||
// 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())
|
||||
@ -1634,7 +1638,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||
|
||||
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...
|
||||
@ -2240,7 +2245,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||
|
||||
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...
|
||||
|
Loading…
Reference in New Issue
Block a user