aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/SparcV9/SparcV9AsmPrinter.cpp21
-rw-r--r--lib/Target/SparcV9/SparcV9InstrInfo.cpp297
-rw-r--r--lib/Target/SparcV9/SparcV9InstrSelection.cpp615
-rw-r--r--lib/Target/SparcV9/SparcV9InstrSelectionSupport.h27
-rw-r--r--lib/Target/SparcV9/SparcV9Internals.h123
-rw-r--r--lib/Target/SparcV9/SparcV9RegClassInfo.cpp55
-rw-r--r--lib/Target/SparcV9/SparcV9RegClassInfo.h20
-rw-r--r--lib/Target/SparcV9/SparcV9RegInfo.cpp733
8 files changed, 1004 insertions, 887 deletions
diff --git a/lib/Target/SparcV9/SparcV9AsmPrinter.cpp b/lib/Target/SparcV9/SparcV9AsmPrinter.cpp
index 868f8710d8..74b7f73da3 100644
--- a/lib/Target/SparcV9/SparcV9AsmPrinter.cpp
+++ b/lib/Target/SparcV9/SparcV9AsmPrinter.cpp
@@ -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
diff --git a/lib/Target/SparcV9/SparcV9InstrInfo.cpp b/lib/Target/SparcV9/SparcV9InstrInfo.cpp
index fd18841dc1..5fbced0f9f 100644
--- a/lib/Target/SparcV9/SparcV9InstrInfo.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrInfo.cpp
@@ -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);
}
diff --git a/lib/Target/SparcV9/SparcV9InstrSelection.cpp b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
index 7109ba4a35..668ac4a566 100644
--- a/lib/Target/SparcV9/SparcV9InstrSelection.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
@@ -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);
@@ -327,31 +331,6 @@ CreateConvertToIntInstr(OpLabel vopCode, Value* srcVal, Value* destVal)
}
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)
{
return ChooseAddInstructionByType(instrNode->getInstruction()->getType());
@@ -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,