1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 03:23:01 +02:00

Numerous bug fixes:

-- correct sign extensions for integer casts and for shift-by-constant
   instructions generated for integer multiply
-- passing FP arguments to functions with more than 6 arguments
-- passing FP arguments to varargs functions
-- passing FP arguments to functions with no prototypes
-- incorrect stack frame size when padding a section
-- folding getelementptr operations with mixed array and struct indexes
-- use uint64_t instead of uint for constant offsets in mem operands
-- incorrect coloring for CC registers (both int and FP): interferences
   were being completely ignored for int CC and were considered but no
   spills were marked for fp CC!

Also some code improvements:
-- better interface to generating machine instr for common cases
   (many places still need to be updated to use this interface)
-- annotations on MachineInstr to communicate information from
   one codegen phase to another (now used to pass information about
   CALL/JMPLCALL operands from selection to register allocation)
-- all sizes and offests in class TargetData are uint64_t instead of uint

llvm-svn: 2640
This commit is contained in:
Vikram S. Adve 2002-05-19 15:25:51 +00:00
parent 4d98351cea
commit fa6c24db76
8 changed files with 1005 additions and 888 deletions

View File

@ -312,9 +312,9 @@ SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &op)
case MachineOperand::MO_PCRelativeDisp:
{
const Value *Val = op.getVRegValue();
if (!Val)
toAsm << "\t<*NULL Value*>";
else if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val))
assert(Val && "\tNULL Value in SparcFunctionAsmPrinter");
if (const BasicBlock *BB = dyn_cast<const BasicBlock>(Val))
toAsm << getID(BB);
else if (const Function *M = dyn_cast<Function>(Val))
toAsm << getID(M);
@ -323,13 +323,16 @@ SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &op)
else if (const Constant *CV = dyn_cast<Constant>(Val))
toAsm << getID(CV);
else
toAsm << "<unknown value=" << Val << ">";
assert(0 && "Unrecognized value in SparcFunctionAsmPrinter");
break;
}
case MachineOperand::MO_SignExtendedImmed:
toAsm << op.getImmedValue();
break;
case MachineOperand::MO_UnextendedImmed:
toAsm << (long)op.getImmedValue();
toAsm << (uint64_t) op.getImmedValue();
break;
default:
@ -486,7 +489,9 @@ static string getAsCString(ConstantArray *CPA) {
(unsigned char)cast<ConstantSInt>(CPA->getOperand(i))->getValue() :
(unsigned char)cast<ConstantUInt>(CPA->getOperand(i))->getValue();
if (isprint(C)) {
if (C == '"') {
Result += "\\\"";
} else if (isprint(C)) {
Result += C;
} else {
switch(C) {
@ -666,13 +671,13 @@ SparcModuleAsmPrinter::printConstantValueOnly(const Constant* CV)
else if (CPA)
{ // Not a string. Print the values in successive locations
const std::vector<Use> &constValues = CPA->getValues();
for (unsigned i=1; i < constValues.size(); i++)
for (unsigned i=0; i < constValues.size(); i++)
this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
}
else if (ConstantStruct *CPS = dyn_cast<ConstantStruct>(CV))
{ // Print the fields in successive locations
const std::vector<Use>& constValues = CPS->getValues();
for (unsigned i=1; i < constValues.size(); i++)
for (unsigned i=0; i < constValues.size(); i++)
this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
}
else

View File

@ -16,7 +16,10 @@
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/InstrSelectionSupport.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/Function.h"
#include "llvm/BasicBlock.h"
#include "llvm/Instruction.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
@ -24,56 +27,87 @@
//************************ Internal Functions ******************************/
static inline MachineInstr*
CreateIntSetInstruction(int64_t C, Value* dest,
std::vector<TmpInstruction*>& tempVec)
static inline void
CreateIntSetInstruction(const TargetMachine& target, Function* F,
int64_t C, Instruction* dest,
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi)
{
MachineInstr* minstr;
assert(dest->getType()->isSigned() && "Use CreateUIntSetInstruction()");
MachineInstr* M;
uint64_t absC = (C >= 0)? C : -C;
if (absC > (unsigned int) ~0)
{ // C does not fit in 32 bits
TmpInstruction* tmpReg = new TmpInstruction(Type::IntTy);
tempVec.push_back(tmpReg);
mcfi.addTemp(tmpReg);
minstr = new MachineInstr(SETX);
minstr->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed, C);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
/*isdef*/ true);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
M = new MachineInstr(SETX);
M->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
/*isdef*/ true);
M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
mvec.push_back(M);
}
else
{
minstr = new MachineInstr(SETSW);
minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
M = Create2OperandInstr_SImmed(SETSW, C, dest);
mvec.push_back(M);
}
return minstr;
}
static inline MachineInstr*
CreateUIntSetInstruction(uint64_t C, Value* dest,
std::vector<TmpInstruction*>& tempVec)
static inline void
CreateUIntSetInstruction(const TargetMachine& target, Function* F,
uint64_t C, Instruction* dest,
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi)
{
MachineInstr* minstr;
assert(! dest->getType()->isSigned() && "Use CreateIntSetInstruction()");
unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
MachineInstr* M;
if (C > (unsigned int) ~0)
{ // C does not fit in 32 bits
assert(dest->getType() == Type::ULongTy && "Sign extension problems");
TmpInstruction *tmpReg = new TmpInstruction(Type::IntTy);
tempVec.push_back(tmpReg);
mcfi.addTemp(tmpReg);
minstr = new MachineInstr(SETX);
minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
tmpReg, /*isdef*/ true);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
M = new MachineInstr(SETX);
M->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
/*isdef*/ true);
M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
mvec.push_back(M);
}
else if (dest->getType() == Type::ULongTy)
else
{
minstr = new MachineInstr(SETUW);
minstr->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
// If the destination is smaller than the standard integer reg. size,
// we have to extend the sign-bit into upper bits of dest, so we
// need to put the result of the SETUW into a temporary.
//
Value* setuwDest = dest;
if (destSize < target.DataLayout.getIntegerRegize())
{
setuwDest = new TmpInstruction(dest, NULL, "setTmp");
mcfi.addTemp(setuwDest);
}
M = Create2OperandInstr_UImmed(SETUW, C, setuwDest);
mvec.push_back(M);
if (setuwDest != dest)
{ // extend the sign-bit of the result into all upper bits of dest
assert(8*destSize <= 32 &&
"Unexpected type size > 4 and < IntRegSize?");
target.getInstrInfo().
CreateSignExtensionInstructions(target, F,
setuwDest, 8*destSize, dest,
mvec, mcfi);
}
}
#define USE_DIRECT_SIGN_EXTENSION_INSTRS
#ifndef USE_DIRECT_SIGN_EXTENSION_INSTRS
else
{ // cast to signed type of the right length and use signed op (SETSW)
// to get correct sign extension
@ -103,8 +137,7 @@ CreateUIntSetInstruction(uint64_t C, Value* dest,
break;
}
}
return minstr;
#endif USE_DIRECT_SIGN_EXTENSION_INSTRS
}
//************************* External Classes *******************************/
@ -131,17 +164,18 @@ UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
// Create an instruction sequence to put the constant `val' into
// the virtual register `dest'. `val' may be a Constant or a
// GlobalValue, viz., the constant address of a global variable or function.
// The generated instructions are returned in `minstrVec'.
// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via MachineCodeForMethod.
//
void
UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
Function* F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>&minstrVec,
std::vector<TmpInstruction*>& tempVec) const
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const
{
MachineInstr* minstr;
assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
"I only know about constant values and global addresses");
@ -153,19 +187,18 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
if (valType->isIntegral() || valType == Type::BoolTy)
{
if (ConstantUInt* uval = dyn_cast<ConstantUInt>(val))
if (! val->getType()->isSigned())
{
uint64_t C = uval->getValue();
minstr = CreateUIntSetInstruction(C, dest, tempVec);
uint64_t C = cast<ConstantUInt>(val)->getValue();
CreateUIntSetInstruction(target, F, C, dest, mvec, mcfi);
}
else
{
bool isValidConstant;
int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
assert(isValidConstant && "Unrecognized constant");
minstr = CreateIntSetInstruction(C, dest, tempVec);
CreateIntSetInstruction(target, F, C, dest, mvec, mcfi);
}
minstrVec.push_back(minstr);
}
else
{
@ -180,42 +213,35 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
TmpInstruction* tmpReg =
new TmpInstruction(PointerType::get(val->getType()), val);
tempVec.push_back(tmpReg);
mcfi.addTemp(tmpReg);
if (isa<Constant>(val))
{
// Create another TmpInstruction for the hidden integer register
TmpInstruction* addrReg =
new TmpInstruction(PointerType::get(val->getType()), val);
tempVec.push_back(addrReg);
mcfi.addTemp(addrReg);
addrVal = addrReg;
}
else
addrVal = dest;
minstr = new MachineInstr(SETX);
minstr->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,tmpReg,
/*isdef*/ true);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
addrVal);
minstrVec.push_back(minstr);
MachineInstr* M = new MachineInstr(SETX);
M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
/*isdef*/ true);
M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, addrVal);
mvec.push_back(M);
if (isa<Constant>(val))
{
// Make sure constant is emitted to constant pool in assembly code.
MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
mcinfo.addToConstantPool(cast<Constant>(val));
MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
// Generate the load instruction
minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
addrVal);
minstr->SetMachineOperandConst(1,MachineOperand::MO_SignExtendedImmed,
zeroOffset);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
dest);
minstrVec.push_back(minstr);
M = Create3OperandInstr_SImmed(ChooseLoadInstruction(val->getType()),
addrVal, zeroOffset, dest);
mvec.push_back(M);
}
}
}
@ -224,24 +250,24 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
// Create an instruction sequence to copy an integer value `val'
// to a floating point value `dest' by copying to memory and back.
// val must be an integral type. dest must be a Float or Double.
// The generated instructions are returned in `minstrVec'.
// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via MachineCodeForMethod.
//
void
UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& minstrVec,
std::vector<TmpInstruction*>& tempVec,
TargetMachine& target) const
UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
Function* F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const
{
assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
&& "Source type must be integral");
assert(dest->getType()->isFloatingPoint()
&& "Dest type must be float/double");
MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
int offset = mcinfo.allocateLocalVar(target, val);
int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
// Store instruction stores `val' to [%fp+offset].
// The store and load opCodes are based on the value being copied, and
@ -254,8 +280,8 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed, offset);
minstrVec.push_back(store);
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
mvec.push_back(store);
// Load instruction loads [%fp+offset] to `dest'.
//
@ -263,29 +289,30 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
minstrVec.push_back(load);
mvec.push_back(load);
}
// Similarly, create an instruction sequence to copy an FP value
// `val' to an integer value `dest' by copying to memory and back.
// See the previous function for information about return values.
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via MachineCodeForMethod.
//
void
UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Function *F,
UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
Function* F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& minstrVec,
std::vector<TmpInstruction*>& tempVec,
TargetMachine& target) const
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const
{
assert(val->getType()->isFloatingPoint()
&& "Source type must be float/double");
assert((dest->getType()->isIntegral() || isa<PointerType>(dest->getType()))
&& "Dest type must be integral");
MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
int offset = mcinfo.allocateLocalVar(target, val);
int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
// Store instruction stores `val' to [%fp+offset].
// The store and load opCodes are based on the value being copied, and
@ -298,13 +325,113 @@ UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Function *F,
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
minstrVec.push_back(store);
mvec.push_back(store);
// Load instruction loads [%fp+offset] to `dest'.
//
MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed, offset);
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
minstrVec.push_back(load);
mvec.push_back(load);
}
// Create instruction(s) to copy src to dest, for arbitrary types
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via MachineCodeForMethod.
//
void
UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
Function *F,
Value* src,
Instruction* dest,
vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const
{
bool loadConstantToReg = false;
const Type* resultType = dest->getType();
MachineOpCode opCode = ChooseAddInstructionByType(resultType);
if (opCode == INVALID_OPCODE)
{
assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
return;
}
// if `src' is a constant that doesn't fit in the immed field or if it is
// a global variable (i.e., a constant address), generate a load
// instruction instead of an add
//
if (isa<Constant>(src))
{
unsigned int machineRegNum;
int64_t immedValue;
MachineOperand::MachineOperandType opType =
ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
machineRegNum, immedValue);
if (opType == MachineOperand::MO_VirtualRegister)
loadConstantToReg = true;
}
else if (isa<GlobalValue>(src))
loadConstantToReg = true;
if (loadConstantToReg)
{ // `src' is constant and cannot fit in immed field for the ADD
// Insert instructions to "load" the constant into a register
target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
mvec, mcfi);
}
else
{ // Create an add-with-0 instruction of the appropriate type.
// Make `src' the second operand, in case it is a constant
// Use (unsigned long) 0 for a NULL pointer value.
//
const Type* zeroValueType =
isa<PointerType>(resultType) ? Type::ULongTy : resultType;
MachineInstr* minstr =
Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
src, dest);
mvec.push_back(minstr);
}
}
// Create instruction sequence to produce a sign-extended register value
// from an arbitrary sized value (sized in bits, not bytes).
// For SPARC v9, we sign-extend the given unsigned operand using SLL; SRA.
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via MachineCodeForMethod.
//
void
UltraSparcInstrInfo::CreateSignExtensionInstructions(
const TargetMachine& target,
Function* F,
Value* unsignedSrcVal,
unsigned int srcSizeInBits,
Value* dest,
vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const
{
MachineInstr* M;
assert(srcSizeInBits > 0 && srcSizeInBits <= 32
&& "Hmmm... srcSizeInBits > 32 unexpected but could be handled here.");
if (srcSizeInBits < 32)
{ // SLL is needed since operand size is < 32 bits.
TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
unsignedSrcVal, dest,"make32");
mcfi.addTemp(tmpI);
M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
mvec.push_back(M);
unsignedSrcVal = tmpI;
}
M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);
mvec.push_back(M);
}

View File

@ -15,6 +15,7 @@
#include "SparcRegClassInfo.h"
#include "llvm/CodeGen/InstrSelectionSupport.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrAnnot.h"
#include "llvm/CodeGen/InstrForest.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
@ -38,6 +39,7 @@ static void SetMemOperands_Internal (vector<MachineInstr*>& mvec,
const InstructionNode* vmInstrNode,
Value* ptrVal,
std::vector<Value*>& idxVec,
bool allConstantIndices,
const TargetMachine& target);
@ -176,7 +178,9 @@ ChooseBccInstruction(const InstructionNode* instrNode,
BinaryOperator* setCCInstr = (BinaryOperator*) setCCNode->getInstruction();
const Type* setCCType = setCCInstr->getOperand(0)->getType();
if (setCCType->isFloatingPoint())
isFPBranch = setCCType->isFloatingPoint(); // Return value: don't delete!
if (isFPBranch)
return ChooseBFpccInstruction(instrNode, setCCInstr);
else
return ChooseBpccInstruction(instrNode, setCCInstr);
@ -326,31 +330,6 @@ CreateConvertToIntInstr(OpLabel vopCode, Value* srcVal, Value* destVal)
return M;
}
static inline MachineOpCode
ChooseAddInstructionByType(const Type* resultType)
{
MachineOpCode opCode = INVALID_OPCODE;
if (resultType->isIntegral() ||
isa<PointerType>(resultType) ||
isa<FunctionType>(resultType) ||
resultType == Type::LabelTy ||
resultType == Type::BoolTy)
{
opCode = ADD;
}
else
switch(resultType->getPrimitiveID())
{
case Type::FloatTyID: opCode = FADDS; break;
case Type::DoubleTyID: opCode = FADDD; break;
default: assert(0 && "Invalid type for ADD instruction"); break;
}
return opCode;
}
static inline MachineOpCode
ChooseAddInstruction(const InstructionNode* instrNode)
{
@ -383,12 +362,11 @@ CreateAddConstInstruction(const InstructionNode* instrNode)
// (1) Add with 0 for float or double: use an FMOV of appropriate type,
// instead of an FADD (1 vs 3 cycles). There is no integer MOV.
//
const Type* resultType = instrNode->getInstruction()->getType();
if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
double dval = FPC->getValue();
if (dval == 0.0)
minstr = CreateMovFloatInstruction(instrNode, resultType);
minstr = CreateMovFloatInstruction(instrNode,
instrNode->getInstruction()->getType());
}
return minstr;
@ -428,12 +406,11 @@ CreateSubConstInstruction(const InstructionNode* instrNode)
// (1) Sub with 0 for float or double: use an FMOV of appropriate type,
// instead of an FSUB (1 vs 3 cycles). There is no integer MOV.
//
const Type* resultType = instrNode->getInstruction()->getType();
if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
double dval = FPC->getValue();
if (dval == 0.0)
minstr = CreateMovFloatInstruction(instrNode, resultType);
minstr = CreateMovFloatInstruction(instrNode,
instrNode->getInstruction()->getType());
}
return minstr;
@ -506,19 +483,71 @@ CreateIntNegInstruction(const TargetMachine& target,
}
// Create instruction sequence for any shift operation.
// SLL or SLLX on an operand smaller than the integer reg. size (64bits)
// requires a second instruction for explicit sign-extension.
// Note that we only have to worry about a sign-bit appearing in the
// most significant bit of the operand after shifting (e.g., bit 32 of
// Int or bit 16 of Short), so we do not have to worry about results
// that are as large as a normal integer register.
//
static inline void
CreateShiftInstructions(const TargetMachine& target,
Function* F,
MachineOpCode shiftOpCode,
Value* argVal1,
Value* optArgVal2, /* Use optArgVal2 if not NULL */
unsigned int optShiftNum, /* else use optShiftNum */
Instruction* destVal,
vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi)
{
assert((optArgVal2 != NULL || optShiftNum <= 64) &&
"Large shift sizes unexpected, but can be handled below: "
"You need to check whether or not it fits in immed field below");
// If this is a logical left shift of a type smaller than the standard
// integer reg. size, we have to extend the sign-bit into upper bits
// of dest, so we need to put the result of the SLL into a temporary.
//
Value* shiftDest = destVal;
const Type* opType = argVal1->getType();
unsigned opSize = target.DataLayout.getTypeSize(argVal1->getType());
if ((shiftOpCode == SLL || shiftOpCode == SLLX)
&& opSize < target.DataLayout.getIntegerRegize())
{ // put SLL result into a temporary
shiftDest = new TmpInstruction(argVal1, optArgVal2, "sllTmp");
mcfi.addTemp(shiftDest);
}
MachineInstr* M = (optArgVal2 != NULL)
? Create3OperandInstr(shiftOpCode, argVal1, optArgVal2, shiftDest)
: Create3OperandInstr_UImmed(shiftOpCode, argVal1, optShiftNum, shiftDest);
mvec.push_back(M);
if (shiftDest != destVal)
{ // extend the sign-bit of the result into all upper bits of dest
assert(8*opSize <= 32 && "Unexpected type size > 4 and < IntRegSize?");
target.getInstrInfo().
CreateSignExtensionInstructions(target, F, shiftDest, 8*opSize,
destVal, mvec, mcfi);
}
}
// Does not create any instructions if we cannot exploit constant to
// create a cheaper instruction.
// This returns the approximate cost of the instructions generated,
// which is used to pick the cheapest when both operands are constant.
static inline unsigned int
CreateMulConstInstruction(const TargetMachine &target,
Value* lval, Value* rval, Value* destVal,
vector<MachineInstr*>& mvec)
CreateMulConstInstruction(const TargetMachine &target, Function* F,
Value* lval, Value* rval, Instruction* destVal,
vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi)
{
/* An integer multiply is generally more costly than FP multiply */
/* Use max. multiply cost, viz., cost of MULX */
unsigned int cost = target.getInstrInfo().minLatency(MULX);
MachineInstr* minstr1 = NULL;
MachineInstr* minstr2 = NULL;
unsigned int firstNewInstr = mvec.size();
Value* constOp = rval;
if (! isa<Constant>(constOp))
@ -532,11 +561,11 @@ CreateMulConstInstruction(const TargetMachine &target,
if (resultType->isIntegral() || isa<PointerType>(resultType))
{
unsigned pow;
bool isValidConst;
int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
if (isValidConst)
{
unsigned pow;
bool needNeg = false;
if (C < 0)
{
@ -547,30 +576,28 @@ CreateMulConstInstruction(const TargetMachine &target,
if (C == 0 || C == 1)
{
cost = target.getInstrInfo().minLatency(ADD);
minstr1 = new MachineInstr(ADD);
if (C == 0)
minstr1->SetMachineOperandReg(0,
target.getRegInfo().getZeroRegNum());
else
minstr1->SetMachineOperandVal(0,
MachineOperand::MO_VirtualRegister, lval);
minstr1->SetMachineOperandReg(1,
target.getRegInfo().getZeroRegNum());
MachineInstr* M = (C == 0)
? Create3OperandInstr_Reg(ADD,
target.getRegInfo().getZeroRegNum(),
target.getRegInfo().getZeroRegNum(),
destVal)
: Create3OperandInstr_Reg(ADD, lval,
target.getRegInfo().getZeroRegNum(),
destVal);
mvec.push_back(M);
}
else if (IsPowerOf2(C, pow))
{
minstr1 = new MachineInstr((resultType == Type::LongTy)
? SLLX : SLL);
minstr1->SetMachineOperandVal(0,
MachineOperand::MO_VirtualRegister, lval);
minstr1->SetMachineOperandConst(1,
MachineOperand::MO_UnextendedImmed, pow);
unsigned int opSize = target.DataLayout.getTypeSize(resultType);
MachineOpCode opCode = (opSize <= 32)? SLL : SLLX;
CreateShiftInstructions(target, F, opCode, lval, NULL, pow,
destVal, mvec, mcfi);
}
if (minstr1 && needNeg)
if (mvec.size() > 0 && needNeg)
{ // insert <reg = SUB 0, reg> after the instr to flip the sign
minstr2 = CreateIntNegInstruction(target, destVal);
cost += target.getInstrInfo().minLatency(minstr2->getOpCode());
MachineInstr* M = CreateIntNegInstruction(target, destVal);
mvec.push_back(M);
}
}
}
@ -581,34 +608,20 @@ CreateMulConstInstruction(const TargetMachine &target,
double dval = FPC->getValue();
if (fabs(dval) == 1)
{
bool needNeg = (dval < 0);
MachineOpCode opCode = needNeg
MachineOpCode opCode = (dval < 0)
? (resultType == Type::FloatTy? FNEGS : FNEGD)
: (resultType == Type::FloatTy? FMOVS : FMOVD);
minstr1 = new MachineInstr(opCode);
minstr1->SetMachineOperandVal(0,
MachineOperand::MO_VirtualRegister,
lval);
MachineInstr* M = Create2OperandInstr(opCode, lval, destVal);
mvec.push_back(M);
}
}
}
if (minstr1 != NULL)
minstr1->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
destVal);
if (minstr1)
if (firstNewInstr < mvec.size())
{
mvec.push_back(minstr1);
cost = target.getInstrInfo().minLatency(minstr1->getOpCode());
}
if (minstr2)
{
assert(minstr1 && "Otherwise cost needs to be initialized to 0");
cost += target.getInstrInfo().minLatency(minstr2->getOpCode());
mvec.push_back(minstr2);
cost = 0;
for (unsigned int i=firstNewInstr; i < mvec.size(); ++i)
cost += target.getInstrInfo().minLatency(mvec[i]->getOpCode());
}
return cost;
@ -620,17 +633,20 @@ CreateMulConstInstruction(const TargetMachine &target,
//
static inline void
CreateCheapestMulConstInstruction(const TargetMachine &target,
Value* lval, Value* rval, Value* destVal,
vector<MachineInstr*>& mvec)
Function* F,
Value* lval, Value* rval,
Instruction* destVal,
vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi)
{
Value* constOp;
if (isa<Constant>(lval) && isa<Constant>(rval))
{ // both operands are constant: try both orders!
vector<MachineInstr*> mvec1, mvec2;
unsigned int lcost = CreateMulConstInstruction(target, lval, rval,
destVal, mvec1);
unsigned int rcost = CreateMulConstInstruction(target, rval, lval,
destVal, mvec2);
unsigned int lcost = CreateMulConstInstruction(target, F, lval, rval,
destVal, mvec1, mcfi);
unsigned int rcost = CreateMulConstInstruction(target, F, rval, lval,
destVal, mvec2, mcfi);
vector<MachineInstr*>& mincostMvec = (lcost <= rcost)? mvec1 : mvec2;
vector<MachineInstr*>& maxcostMvec = (lcost <= rcost)? mvec2 : mvec1;
mvec.insert(mvec.end(), mincostMvec.begin(), mincostMvec.end());
@ -639,9 +655,9 @@ CreateCheapestMulConstInstruction(const TargetMachine &target,
delete maxcostMvec[i];
}
else if (isa<Constant>(rval)) // rval is constant, but not lval
CreateMulConstInstruction(target, lval, rval, destVal, mvec);
CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
else if (isa<Constant>(lval)) // lval is constant, but not rval
CreateMulConstInstruction(target, lval, rval, destVal, mvec);
CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
// else neither is constant
return;
@ -649,13 +665,14 @@ CreateCheapestMulConstInstruction(const TargetMachine &target,
// Return NULL if we cannot exploit constant to create a cheaper instruction
static inline void
CreateMulInstruction(const TargetMachine &target,
Value* lval, Value* rval, Value* destVal,
CreateMulInstruction(const TargetMachine &target, Function* F,
Value* lval, Value* rval, Instruction* destVal,
vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi,
MachineOpCode forceMulOp = INVALID_MACHINE_OPCODE)
{
unsigned int L = mvec.size();
CreateCheapestMulConstInstruction(target, lval, rval, destVal, mvec);
CreateCheapestMulConstInstruction(target,F, lval, rval, destVal, mvec, mcfi);
if (mvec.size() == L)
{ // no instructions were added so create MUL reg, reg, reg.
// Use FSMULD if both operands are actually floats cast to doubles.
@ -889,6 +906,8 @@ CreateCodeForFixedSizeAlloca(const TargetMachine& target,
//------------------------------------------------------------------------
// Function SetOperandsForMemInstr
//
@ -913,15 +932,14 @@ SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
{
MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
// Variables to hold the index vector, ptr value, and offset value.
// Variables to hold the index vector and ptr value.
// The major work here is to extract these for all 3 instruction types
// and then call the common function SetMemOperands_Internal().
//
Value* ptrVal = memInst->getPointerOperand();
// Start with the index vector of this instruction, if any.
// and to try to fold chains of constant indices into a single offset.
// After that, we call SetMemOperands_Internal(), which creates the
// appropriate operands for the machine instruction.
vector<Value*> idxVec;
idxVec.insert(idxVec.end(), memInst->idx_begin(), memInst->idx_end());
bool allConstantIndices = true;
Value* ptrVal = memInst->getPointerOperand();
// If there is a GetElemPtr instruction to fold in to this instr,
// it must be in the left child for Load and GetElemPtr, and in the
@ -930,17 +948,40 @@ SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
? vmInstrNode->rightChild()
: vmInstrNode->leftChild());
// Fold chains of GetElemPtr instructions for structure references.
if (isa<StructType>(cast<PointerType>(ptrVal->getType())->getElementType())
&& (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
ptrChild->getOpLabel() == GetElemPtrIdx))
// Check if all indices are constant for this instruction
for (MemAccessInst::op_iterator OI=memInst->idx_begin();
OI != memInst->idx_end(); ++OI)
if (! isa<ConstantUInt>(*OI))
{
allConstantIndices = false;
break;
}
// If we have only constant indices, fold chains of constant indices
// in this and any preceding GetElemPtr instructions.
if (allConstantIndices &&
ptrChild->getOpLabel() == Instruction::GetElementPtr ||
ptrChild->getOpLabel() == GetElemPtrIdx)
{
Value* newPtr = FoldGetElemChain((InstructionNode*) ptrChild, idxVec);
if (newPtr)
ptrVal = newPtr;
}
SetMemOperands_Internal(mvec, mvecI, vmInstrNode, ptrVal, idxVec, target);
// Append the index vector of the current instruction, if any.
// Discard any leading [0] index.
if (memInst->idx_begin() != memInst->idx_end())
{
ConstantUInt* CV = dyn_cast<ConstantUInt>(* memInst->idx_begin());
unsigned zeroOrIOne = (CV && CV->getType() == Type::UIntTy &&
(CV->getValue() == 0))? 1 : 0;
idxVec.insert(idxVec.end(),
memInst->idx_begin()+zeroOrIOne, memInst->idx_end());
}
// Now create the appropriate operands for the machine instruction
SetMemOperands_Internal(mvec, mvecI, vmInstrNode,
ptrVal, idxVec, allConstantIndices, target);
}
@ -953,6 +994,7 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
const InstructionNode* vmInstrNode,
Value* ptrVal,
vector<Value*>& idxVec,
bool allConstantIndices,
const TargetMachine& target)
{
MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
@ -967,35 +1009,31 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
//
if (idxVec.size() > 0)
{
unsigned offset = 0;
const PointerType* ptrType = cast<PointerType>(ptrVal->getType());
// Handle special common case of leading [0] index.
bool firstIndexIsZero =
bool(isa<ConstantUInt>(idxVec.front()) &&
cast<ConstantUInt>(idxVec.front())->getValue() == 0);
// This is a real structure reference if the ptr target is a
// structure type, and the first offset is [0] (eliminate that offset).
if (firstIndexIsZero && isa<StructType>(ptrType->getElementType()))
// If all indices are constant, compute the combined offset directly.
if (allConstantIndices)
{
// Compute the offset value using the index vector. Create a
// virtual reg. for it since it may not fit in the immed field.
assert(idxVec.size() >= 2);
idxVec.erase(idxVec.begin());
unsigned offset = target.DataLayout.getIndexedOffset(ptrType,idxVec);
valueForRegOffset = ConstantSInt::get(Type::IntTy, offset);
uint64_t offset = target.DataLayout.getIndexedOffset(ptrType,idxVec);
valueForRegOffset = ConstantSInt::get(Type::LongTy, offset);
}
else
{
// It is an array ref, and must have been lowered to a single offset.
// There is at least one non-constant offset. Therefore, this must
// be an array ref, and must have been lowered to a single offset.
assert((memInst->getNumOperands()
== (unsigned) 1 + memInst->getFirstIndexOperandNumber())
&& "Array refs must be lowered before Instruction Selection");
Value* arrayOffsetVal = * memInst->idx_begin();
// Handle special common case of leading [0] index.
ConstantUInt* CV = dyn_cast<ConstantUInt>(idxVec.front());
bool firstIndexIsZero = bool(CV && CV->getType() == Type::UIntTy &&
(CV->getValue() == 0));
// If index is 0, the offset value is just 0. Otherwise,
// generate a MUL instruction to compute address from index.
// The call to getTypeSize() will fail if size is not constant.
@ -1018,10 +1056,13 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
ConstantUInt* eltVal = ConstantUInt::get(Type::UIntTy, eltSize);
CreateMulInstruction(target,
memInst->getParent()->getParent(),
arrayOffsetVal, /* lval, not likely const */
eltVal, /* rval, likely constant */
addr, /* result*/
mulVec, INVALID_MACHINE_OPCODE);
mulVec,
MachineCodeForInstruction::get(memInst),
INVALID_MACHINE_OPCODE);
assert(mulVec.size() > 0 && "No multiply instruction created?");
for (vector<MachineInstr*>::const_iterator I = mulVec.begin();
I != mulVec.end(); ++I)
@ -1116,7 +1157,6 @@ ForwardOperand(InstructionNode* treeNode,
}
else
{
bool fwdSuccessful = false;
for (unsigned i=0, N=mvec.size(); i < N; i++)
{
MachineInstr* minstr = mvec[i];
@ -1125,93 +1165,32 @@ ForwardOperand(InstructionNode* treeNode,
const MachineOperand& mop = minstr->getOperand(i);
if (mop.getOperandType() == MachineOperand::MO_VirtualRegister &&
mop.getVRegValue() == unusedOp)
{
minstr->SetMachineOperandVal(i,
minstr->SetMachineOperandVal(i,
MachineOperand::MO_VirtualRegister, fwdOp);
fwdSuccessful = true;
}
}
for (unsigned i=0,numOps=minstr->getNumImplicitRefs(); i<numOps; ++i)
if (minstr->getImplicitRef(i) == unusedOp)
{
minstr->setImplicitRef(i, fwdOp,
minstr->implicitRefIsDefined(i));
fwdSuccessful = true;
}
minstr->setImplicitRef(i, fwdOp,
minstr->implicitRefIsDefined(i));
}
assert(fwdSuccessful && "Value to be forwarded is never used!");
}
}
void UltraSparcInstrInfo::
CreateCopyInstructionsByType(const TargetMachine& target,
Function *F,
Value* src,
Instruction* dest,
vector<MachineInstr*>& minstrVec) const
inline bool
AllUsesAreBranches(const Instruction* setccI)
{
bool loadConstantToReg = false;
const Type* resultType = dest->getType();
MachineOpCode opCode = ChooseAddInstructionByType(resultType);
if (opCode == INVALID_OPCODE)
{
assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
return;
}
// if `src' is a constant that doesn't fit in the immed field or if it is
// a global variable (i.e., a constant address), generate a load
// instruction instead of an add
//
if (isa<Constant>(src))
{
unsigned int machineRegNum;
int64_t immedValue;
MachineOperand::MachineOperandType opType =
ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
machineRegNum, immedValue);
if (opType == MachineOperand::MO_VirtualRegister)
loadConstantToReg = true;
}
else if (isa<GlobalValue>(src))
loadConstantToReg = true;
if (loadConstantToReg)
{ // `src' is constant and cannot fit in immed field for the ADD
// Insert instructions to "load" the constant into a register
vector<TmpInstruction*> tempVec;
target.getInstrInfo().CreateCodeToLoadConst(F, src, dest,
minstrVec, tempVec);
for (unsigned i=0; i < tempVec.size(); i++)
MachineCodeForInstruction::get(dest).addTemp(tempVec[i]);
}
else
{ // Create an add-with-0 instruction of the appropriate type.
// Make `src' the second operand, in case it is a constant
// Use (unsigned long) 0 for a NULL pointer value.
//
const Type* zeroValueType =
isa<PointerType>(resultType) ? Type::ULongTy : resultType;
MachineInstr* minstr = new MachineInstr(opCode);
minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
Constant::getNullValue(zeroValueType));
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, src);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
minstrVec.push_back(minstr);
}
for (Value::use_const_iterator UI=setccI->use_begin(), UE=setccI->use_end();
UI != UE; ++UI)
if (! isa<TmpInstruction>(*UI) // ignore tmp instructions here
&& cast<Instruction>(*UI)->getOpcode() != Instruction::Br)
return false;
return true;
}
//******************* Externally Visible Functions *************************/
//------------------------------------------------------------------------
// External Function: ThisIsAChainRule
//
@ -1521,11 +1500,33 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
case 27: // reg: ToUIntTy(reg)
case 29: // reg: ToULongTy(reg)
{
Instruction* destI = subtreeRoot->getInstruction();
Value* opVal = subtreeRoot->leftChild()->getValue();
const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
assert(opType->isIntegral() ||
isa<PointerType>(opType) ||
opType == Type::BoolTy && "Cast is illegal for other types");
forwardOperandNum = 0; // forward first operand to user
unsigned opSize = target.DataLayout.getTypeSize(opType);
unsigned destSize = target.DataLayout.getTypeSize(destI->getType());
if (opSize > destSize ||
(opType->isSigned()
&& destSize < target.DataLayout.getIntegerRegize()))
{ // 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 using AND
//
M = Create3OperandInstr(AND, opVal,
ConstantUInt::get(Type::ULongTy,
((uint64_t) 1 << 8*destSize) - 1),
destI);
mvec.push_back(M);
}
else
forwardOperandNum = 0; // forward first operand to user
break;
}
@ -1534,18 +1535,49 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
case 28: // reg: ToIntTy(reg)
case 30: // reg: ToLongTy(reg)
{
const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
unsigned int oldMvecSize = mvec.size(); // to check if it grew
Instruction* destI = subtreeRoot->getInstruction();
Value* opVal = subtreeRoot->leftChild()->getValue();
MachineCodeForInstruction& mcfi =MachineCodeForInstruction::get(destI);
const Type* opType = opVal->getType();
if (opType->isIntegral()
|| isa<PointerType>(opType)
|| opType == Type::BoolTy)
{
forwardOperandNum = 0; // forward first operand to user
// These operand types have the same format as the destination,
// but may have different size: add sign bits or mask as needed.
//
const Type* destType = destI->getType();
unsigned opSize = target.DataLayout.getTypeSize(opType);
unsigned destSize = target.DataLayout.getTypeSize(destType);
if (opSize <= destSize && !opType->isSigned())
{ // operand is smaller than or same size as dest:
// -- if operand is signed (checked above), nothing to do
// -- if operand is unsigned, sign-extend the value:
//
target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), opVal, 8*opSize, destI, mvec, mcfi);
}
else if (opSize > destSize)
{ // operand is larger than dest: mask high bits using AND
// and then sign-extend using SRA by 0!
//
TmpInstruction *tmpI = new TmpInstruction(destType, opVal,
destI, "maskHi");
mcfi.addTemp(tmpI);
M = Create3OperandInstr(AND, opVal,
ConstantUInt::get(Type::UIntTy,
((uint64_t) 1 << 8*destSize)-1),
tmpI);
mvec.push_back(M);
target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), tmpI, 8*destSize, destI, mvec, mcfi);
}
}
else
{
// If the source operand is an FP type, the int result must be
// copied from float to int register via memory!
Instruction *dest = subtreeRoot->getInstruction();
Value* leftVal = subtreeRoot->leftChild()->getValue();
Value* destForCast;
vector<MachineInstr*> minstrVec;
@ -1559,21 +1591,18 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
// double-prec for a 64-bit int.
//
const Type* destTypeToUse =
(dest->getType() == Type::LongTy)? Type::DoubleTy
(destI->getType() == Type::LongTy)? Type::DoubleTy
: Type::FloatTy;
destForCast = new TmpInstruction(destTypeToUse, leftVal);
MachineCodeForInstruction &destMCFI =
MachineCodeForInstruction::get(dest);
MachineCodeForInstruction::get(destI);
destMCFI.addTemp(destForCast);
vector<TmpInstruction*> tempVec;
target.getInstrInfo().CreateCodeToCopyFloatToInt(
dest->getParent()->getParent(),
(TmpInstruction*) destForCast, dest,
minstrVec, tempVec, target);
for (unsigned i=0; i < tempVec.size(); ++i)
destMCFI.addTemp(tempVec[i]);
target.getInstrInfo().
CreateCodeToCopyFloatToInt(target,
destI->getParent()->getParent(),
(TmpInstruction*) destForCast,
destI, minstrVec, destMCFI);
}
else
destForCast = leftVal;
@ -1585,6 +1614,10 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
// Append the copy code, if any, after the conversion instr.
mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
}
if (oldMvecSize == mvec.size()) // no instruction was generated
forwardOperandNum = 0; // forward first operand to user
break;
}
@ -1620,7 +1653,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
Instruction *dest = subtreeRoot->getInstruction();
Value* srcForCast;
int n = 0;
if (opType->isFloatingPoint())
if (! opType->isFloatingPoint())
{
// Create a temporary to represent the FP register
// into which the integer will be copied via memory.
@ -1637,17 +1670,10 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
MachineCodeForInstruction::get(dest);
destMCFI.addTemp(srcForCast);
vector<MachineInstr*> minstrVec;
vector<TmpInstruction*> tempVec;
target.getInstrInfo().CreateCodeToCopyIntToFloat(
target.getInstrInfo().CreateCodeToCopyIntToFloat(target,
dest->getParent()->getParent(),
leftVal, (TmpInstruction*) srcForCast,
minstrVec, tempVec, target);
mvec.insert(mvec.end(), minstrVec.begin(),minstrVec.end());
for (unsigned i=0; i < tempVec.size(); ++i)
destMCFI.addTemp(tempVec[i]);
mvec, destMCFI);
}
else
srcForCast = leftVal;
@ -1705,11 +1731,12 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
? FSMULD
: INVALID_MACHINE_OPCODE);
CreateMulInstruction(target,
Instruction* mulInstr = subtreeRoot->getInstruction();
CreateMulInstruction(target, mulInstr->getParent()->getParent(),
subtreeRoot->leftChild()->getValue(),
subtreeRoot->rightChild()->getValue(),
subtreeRoot->getInstruction(),
mvec, forceOp);
mulInstr, mvec,
MachineCodeForInstruction::get(mulInstr),forceOp);
break;
}
case 335: // reg: Mul(todouble, todoubleConst)
@ -1721,11 +1748,13 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
? FSMULD
: INVALID_MACHINE_OPCODE);
CreateMulInstruction(target,
Instruction* mulInstr = subtreeRoot->getInstruction();
CreateMulInstruction(target, mulInstr->getParent()->getParent(),
subtreeRoot->leftChild()->getValue(),
subtreeRoot->rightChild()->getValue(),
subtreeRoot->getInstruction(),
mvec, forceOp);
mulInstr, mvec,
MachineCodeForInstruction::get(mulInstr),
forceOp);
break;
}
case 236: // reg: Div(reg, Constant)
@ -1793,7 +1822,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
case 239: // bool: Or(bool, boolconst)
case 339: // reg : BOr(reg, reg)
case 539: // reg : BOr(reg, Constant)
mvec.push_back(new MachineInstr(ORN));
mvec.push_back(new MachineInstr(OR));
Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
break;
@ -1829,7 +1858,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
// a result register, and setting a condition code.
//
// If the boolean result of the SetCC is used by anything other
// than a single branch instruction, the boolean must be
// than a branch instruction, the boolean must be
// computed and stored in the result register. Otherwise, discard
// the difference (by using %g0) and keep only the condition code.
//
@ -1840,9 +1869,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
//
InstructionNode* parentNode = (InstructionNode*) subtreeRoot->parent();
Instruction* setCCInstr = subtreeRoot->getInstruction();
bool keepBoolVal = (parentNode == NULL ||
parentNode->getInstruction()->getOpcode()
!= Instruction::Br);
bool keepBoolVal = ! AllUsesAreBranches(setCCInstr);
bool subValIsBoolVal = setCCInstr->getOpcode() == Instruction::SetNE;
bool keepSubVal = keepBoolVal && subValIsBoolVal;
bool computeBoolVal = keepBoolVal && ! subValIsBoolVal;
@ -2008,7 +2036,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
Value *callee = callInstr->getCalledValue();
// Create hidden virtual register for return address, with type void*.
Instruction* retAddrReg =
TmpInstruction* retAddrReg =
new TmpInstruction(PointerType::get(Type::VoidTy), callInstr);
MachineCodeForInstruction::get(callInstr).addTemp(retAddrReg);
@ -2036,49 +2064,68 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
mvec.push_back(M);
// WARNING: Operands 0..N-1 must go in slots 0..N-1 of implicitUses.
// The result value must go in slot N. This is assumed
// in register allocation.
//
// Add the call operands and return value as implicit refs
// const Type* funcType = isa<Function>(callee)? callee->getType()
// : cast<PointerType>(callee->getType())->getElementType();
const Type* funcType = callee->getType();
bool isVarArgs = cast<FunctionType>(cast<PointerType>(funcType)
->getElementType())->isVarArg();
const FunctionType* funcType =
cast<FunctionType>(cast<PointerType>(callee->getType())
->getElementType());
bool isVarArgs = funcType->isVarArg();
bool noPrototype = isVarArgs && funcType->getNumParams() == 0;
for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
if (callInstr->getOperand(i) != callee)
{
Value* argVal = callInstr->getOperand(i);
// Check for FP arguments to varargs functions
if (isVarArgs && argVal->getType()->isFloatingPoint())
{ // Add a copy-float-to-int instruction
MachineCodeForInstruction &destMCFI =
MachineCodeForInstruction::get(callInstr);
Instruction* intArgReg =
new TmpInstruction(Type::IntTy, argVal);
destMCFI.addTemp(intArgReg);
vector<MachineInstr*> minstrVec;
vector<TmpInstruction*> tempVec;
target.getInstrInfo().CreateCodeToCopyFloatToInt(
callInstr->getParent()->getParent(),
argVal, (TmpInstruction*) intArgReg,
minstrVec, tempVec, target);
mvec.insert(mvec.begin(), minstrVec.begin(),minstrVec.end());
for (unsigned i=0; i < tempVec.size(); ++i)
destMCFI.addTemp(tempVec[i]);
argVal = intArgReg;
}
mvec.back()->addImplicitRef(argVal);
}
// Use an annotation to pass information about call arguments
// to the register allocator.
CallArgsDescriptor* argDesc = new CallArgsDescriptor(callInstr,
retAddrReg, isVarArgs, noPrototype);
M->addAnnotation(argDesc);
assert(callInstr->getOperand(0) == callee
&& "This is assumed in the loop below!");
for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i)
{
Value* argVal = callInstr->getOperand(i);
Instruction* intArgReg = NULL;
// Check for FP arguments to varargs functions.
// Any such argument in the first $K$ args must be passed in an
// integer register, where K = #integer argument registers.
if (isVarArgs && argVal->getType()->isFloatingPoint())
{
// If it is a function with no prototype, pass value
// as an FP value as well as a varargs value
if (noPrototype)
argDesc->getArgInfo(i-1).setUseFPArgReg();
// If this arg. is in the first $K$ regs, add a copy
// float-to-int instruction to pass the value as an integer.
if (i < target.getRegInfo().GetNumOfIntArgRegs())
{
MachineCodeForInstruction &destMCFI =
MachineCodeForInstruction::get(callInstr);
intArgReg = new TmpInstruction(Type::IntTy, argVal);
destMCFI.addTemp(intArgReg);
vector<MachineInstr*> copyMvec;
target.getInstrInfo().CreateCodeToCopyFloatToInt(target,
callInstr->getParent()->getParent(),
argVal, (TmpInstruction*) intArgReg,
copyMvec, destMCFI);
mvec.insert(mvec.begin(),copyMvec.begin(),copyMvec.end());
argDesc->getArgInfo(i-1).setUseIntArgReg();
argDesc->getArgInfo(i-1).setArgCopy(intArgReg);
}
else
// Cannot fit in first $K$ regs so pass the arg on the stack
argDesc->getArgInfo(i-1).setUseStackSlot();
}
if (intArgReg)
mvec.back()->addImplicitRef(intArgReg);
mvec.back()->addImplicitRef(argVal);
}
// Add the return value as an implicit ref. The call operands
// were added above.
if (callInstr->getType() != Type::VoidTy)
mvec.back()->addImplicitRef(callInstr, /*isDef*/ true);
@ -2090,20 +2137,29 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
mvec.push_back(new MachineInstr(NOP));
break;
}
case 62: // reg: Shl(reg, reg)
{ const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
{
Value* argVal1 = subtreeRoot->leftChild()->getValue();
Value* argVal2 = subtreeRoot->rightChild()->getValue();
Instruction* shlInstr = subtreeRoot->getInstruction();
const Type* opType = argVal1->getType();
assert(opType->isIntegral()
|| isa<PointerType>(opType)&& "Shl unsupported for other types");
mvec.push_back(new MachineInstr((opType == Type::LongTy)? SLLX : SLL));
Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
|| opType == Type::BoolTy
|| isa<PointerType>(opType)&&"Shl unsupported for other types");
CreateShiftInstructions(target, shlInstr->getParent()->getParent(),
(opType == Type::LongTy)? SLLX : SLL,
argVal1, argVal2, 0, shlInstr, mvec,
MachineCodeForInstruction::get(shlInstr));
break;
}
case 63: // reg: Shr(reg, reg)
{ const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
assert(opType->isIntegral()
|| isa<PointerType>(opType) &&"Shr unsupported for other types");
|| isa<PointerType>(opType)&&"Shr unsupported for other types");
mvec.push_back(new MachineInstr((opType->isSigned()
? ((opType == Type::LongTy)? SRAX : SRA)
: ((opType == Type::LongTy)? SRLX : SRL))));
@ -2150,14 +2206,15 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
else
{
vector<MachineInstr*> minstrVec;
target.getInstrInfo().CreateCopyInstructionsByType(target,
subtreeRoot->getInstruction()->getParent()->getParent(),
subtreeRoot->getInstruction()->getOperand(forwardOperandNum),
subtreeRoot->getInstruction(), minstrVec);
Instruction* instr = subtreeRoot->getInstruction();
target.getInstrInfo().
CreateCopyInstructionsByType(target,
instr->getParent()->getParent(),
instr->getOperand(forwardOperandNum),
instr, minstrVec,
MachineCodeForInstruction::get(instr));
assert(minstrVec.size() > 0);
mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
}
}
}

View File

@ -12,6 +12,8 @@
#ifndef SPARC_INSTR_SELECTION_SUPPORT_h
#define SPARC_INSTR_SELECTION_SUPPORT_h
#include "llvm/DerivedTypes.h"
#include "llvm/Value.h"
inline MachineOpCode
ChooseLoadInstruction(const Type *DestTy)
@ -58,4 +60,29 @@ ChooseStoreInstruction(const Type *DestTy)
return 0;
}
inline MachineOpCode
ChooseAddInstructionByType(const Type* resultType)
{
MachineOpCode opCode = INVALID_OPCODE;
if (resultType->isIntegral() ||
isa<PointerType>(resultType) ||
isa<FunctionType>(resultType) ||
resultType == Type::LabelTy ||
resultType == Type::BoolTy)
{
opCode = ADD;
}
else
switch(resultType->getPrimitiveID())
{
case Type::FloatTyID: opCode = FADDS; break;
case Type::DoubleTyID: opCode = FADDD; break;
default: assert(0 && "Invalid type for ADD instruction"); break;
}
return opCode;
}
#endif

View File

@ -123,47 +123,69 @@ public:
//-------------------------------------------------------------------------
// Create an instruction sequence to put the constant `val' into
// the virtual register `dest'. The generated instructions are
// returned in `minstrVec'. Any temporary registers (TmpInstruction)
// created are returned in `tempVec'.
// the virtual register `dest'. `val' may be a Constant or a
// GlobalValue, viz., the constant address of a global variable or function.
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via mcff.
//
virtual void CreateCodeToLoadConst(Function *F,
virtual void CreateCodeToLoadConst(const TargetMachine& target,
Function* F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& minstrVec,
std::vector<TmpInstruction*>& tmp) const;
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const;
// Create an instruction sequence to copy an integer value `val'
// to a floating point value `dest' by copying to memory and back.
// val must be an integral type. dest must be a Float or Double.
// The generated instructions are returned in `minstrVec'.
// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via mcff.
//
virtual void CreateCodeToCopyIntToFloat(Function* F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& minstr,
std::vector<TmpInstruction*>& temp,
TargetMachine& target) const;
virtual void CreateCodeToCopyIntToFloat(const TargetMachine& target,
Function* F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const;
// Similarly, create an instruction sequence to copy an FP value
// `val' to an integer value `dest' by copying to memory and back.
// See the previous function for information about return values.
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via mcff.
//
virtual void CreateCodeToCopyFloatToInt(const TargetMachine& target,
Function* F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const;
// Create instruction(s) to copy src to dest, for arbitrary types
// The generated instructions are returned in `mvec'.
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
// Any stack space required is allocated via mcff.
//
virtual void CreateCodeToCopyFloatToInt(Function* F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& minstr,
std::vector<TmpInstruction*>& temp,
TargetMachine& target) const;
// create copy instruction(s)
virtual void CreateCopyInstructionsByType(const TargetMachine& target,
Function* F,
Value* src,
Instruction* dest,
std::vector<MachineInstr*>& minstr) const;
Function* F,
Value* src,
Instruction* dest,
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const;
// Create instruction sequence to produce a sign-extended register value
// from an arbitrary sized value (sized in bits, not bytes).
// Any stack space required is allocated via mcff.
//
virtual void CreateSignExtensionInstructions(const TargetMachine& target,
Function* F,
Value* unsignedSrcVal,
unsigned int srcSizeInBits,
Value* dest,
std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const;
};
@ -240,18 +262,16 @@ class UltraSparcRegInfo : public MachineRegInfo {
void suggestReg4CallAddr(const MachineInstr *CallMI, LiveRangeInfo &LRI,
std::vector<RegClass *> RCList) const;
// The following methods are used to find the addresses etc. contained
// in specail machine instructions like CALL/RET
//
Value *getValue4ReturnAddr(const MachineInstr *MInst) const;
const Value *getCallInstRetAddr(const MachineInstr *CallMI) const;
unsigned getCallInstNumArgs(const MachineInstr *CallMI) const;
// The following 3 methods are used to find the RegType (see enum above)
void InitializeOutgoingArg(const MachineInstr* CallMI, AddedInstrns *CallAI,
PhyRegAlloc &PRA, LiveRange* LR,
unsigned regType, unsigned RegClassID,
int UniArgReg, unsigned int argNo,
std::vector<MachineInstr *>& AddedInstrnsBefore)
const;
// The following 4 methods are used to find the RegType (see enum above)
// of a LiveRange, Value and using the unified RegClassID
int getRegType(unsigned regClassID, const Type* type) const;
int getRegType(const LiveRange *LR) const;
int getRegType(const Value *Val) const;
int getRegType(int reg) const;
@ -353,8 +373,12 @@ public:
//
unsigned getReturnAddressReg() const;
// Number of registers used for passing int args (usually 6: %o0 - %o5)
// and float args (usually 32: %f0 - %f31)
//
unsigned const GetNumOfIntArgRegs() const { return NumOfIntArgRegs; }
unsigned const GetNumOfFloatArgRegs() const { return NumOfFloatArgRegs; }
// The following methods are used to color special live ranges (e.g.
// function args and return values etc.) with specific hardware registers
// as required. See SparcRegInfo.cpp for the implementation for Sparc.
@ -427,21 +451,20 @@ public:
const Value * getCallInstRetVal(const MachineInstr *CallMI) const;
const Value * getCallInstIndirectAddrVal(const MachineInstr *CallMI) const;
// The following methods are used to generate "copy" machine instructions
// for an architecture.
//
MachineInstr * cpReg2RegMI(unsigned SrcReg, unsigned DestReg,
int RegType) const;
void cpReg2RegMI(unsigned SrcReg, unsigned DestReg,
int RegType, vector<MachineInstr*>& mvec) const;
MachineInstr * cpReg2MemMI(unsigned SrcReg, unsigned DestPtrReg,
int Offset, int RegType) const;
void cpReg2MemMI(unsigned SrcReg, unsigned DestPtrReg,
int Offset, int RegType, vector<MachineInstr*>& mvec) const;
MachineInstr * cpMem2RegMI(unsigned SrcPtrReg, int Offset,
unsigned DestReg, int RegType) const;
MachineInstr* cpValue2Value(Value *Src, Value *Dest) const;
void cpMem2RegMI(unsigned SrcPtrReg, int Offset, unsigned DestReg,
int RegType, vector<MachineInstr*>& mvec) const;
void cpValue2Value(Value *Src, Value *Dest,
vector<MachineInstr*>& mvec) const;
// To see whether a register is a volatile (i.e., whehter it must be
// preserved acorss calls)

View File

@ -20,22 +20,6 @@ using std::cerr;
//-----------------------------------------------------------------------------
void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const {
LiveRange *LR = Node->getParentLR();
unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
for (unsigned n=0; n < NumNeighbors; n++) { // for each neigh
IGNode *NeighIGNode = Node->getAdjIGNode(n);
LiveRange *NeighLR = NeighIGNode->getParentLR();
if(NeighLR->hasColor()) // if has a color
IsColorUsedArr[NeighLR->getColor()] = true; // record that color
else if (NeighLR->hasSuggestedColor()) {
// if the neighbout can use the suggested color
if(NeighLR->isSuggestedColorUsable())
IsColorUsedArr[NeighLR->getSuggestedColor()] = true;
}
}
if( DEBUG_RA ) {
cerr << "\nColoring LR [CallInt=" << LR->isCallInterference() <<"]:";
@ -148,38 +132,35 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const {
//----------------------------------------------------------------------------
void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const{
LiveRange *LR = Node->getParentLR();
unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
// Mark the second color for double-precision registers:
// This is UGLY and should be merged into nearly identical code
// in RegClass::colorIGNode that handles the first color.
//
unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh
IGNode *NeighIGNode = Node->getAdjIGNode(n);
LiveRange *NeighLR = NeighIGNode->getParentLR();
if( NeighLR->hasColor() &&
NeighLR->getType() == Type::DoubleTy) {
IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true;
} else if (NeighLR->hasSuggestedColor() &&
NeighLR-> isSuggestedColorUsable() ) {
if( NeighLR->hasColor() ) { // if neigh has a color
IsColorUsedArr[ NeighLR->getColor() ] = true; // record that color
if (NeighLR->getType() == Type::DoubleTy)
IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true;
}
else if( NeighLR->hasSuggestedColor() ) { // if neigh has sugg color
if( NeighLR-> isSuggestedColorUsable() ) {
// if the neighbout can use the suggested color
// if the neighbour can use the suggested color
IsColorUsedArr[ NeighLR->getSuggestedColor() ] = true;
if (NeighLR->getType() == Type::DoubleTy)
IsColorUsedArr[ (NeighLR->getSuggestedColor()) + 1 ] = true;
}
}
}
}
// **NOTE: We don't check for call interferences in allocating suggested
// color in this class since ALL registers are volatile. If this fact
// changes, we should change the following part
//- see SparcIntRegClass::colorIGNode()
//
if( LR->hasSuggestedColor() ) {
if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) {
LR->setColor( LR->getSuggestedColor() );
@ -244,10 +225,8 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const{
IsColorUsedArr);
}
if( ColorFound >= 0 ) {
LR->setColor(ColorFound); // first color found in preffered order
LR->setColor(ColorFound); // first color found in prefered order
LR->markForSaveAcrossCalls();
} else {
// we are here because no color could be found

View File

@ -191,15 +191,17 @@ struct SparcIntCCRegOrder {
struct SparcIntCCRegClass : public MachineRegClassInfo {
SparcIntCCRegClass(unsigned ID)
: MachineRegClassInfo(ID, 1, 2) { }
inline void colorIGNode(IGNode *Node, bool IsColorUsedArr[]) const {
Node->setColor(0); // only one int cc reg is available
if (IsColorUsedArr[0])
Node->getParentLR()->markForSpill();
else
Node->setColor(0); // only one int cc reg is available
}
// according to Sparc 64 ABI, %ccr is volatile
//
inline bool isRegVolatile(int Reg) const { return true; }
};
@ -231,11 +233,13 @@ struct SparcFloatCCRegClass : public MachineRegClassInfo {
void colorIGNode(IGNode *Node, bool IsColorUsedArr[]) const {
int c;
for(c=0; c < 4 && IsColorUsedArr[c] ; ++c) ; // find color
assert ((c < 4) && "Can allocate only 4 float cc registers");
Node->setColor(c);
for(c=0; c < 4 && IsColorUsedArr[c] ; ++c) ; // find unused color
if (c < 4)
Node->setColor(c);
else
Node->getParentLR()->markForSpill();
}
// according to Sparc 64 ABI, all %fp CC regs are volatile
//
inline bool isRegVolatile(int Reg) const { return true; }

File diff suppressed because it is too large Load Diff