Index: src/IceTargetLoweringX86BaseImpl.h |
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h |
index 6a0f3b3db52dc5f08a053ee7152c0a298ed481b6..68cbf94d26927089062b3c6aab79a9b8f8f6f2eb 100644 |
--- a/src/IceTargetLoweringX86BaseImpl.h |
+++ b/src/IceTargetLoweringX86BaseImpl.h |
@@ -23,20 +23,16 @@ |
#include "IceDefs.h" |
#include "IceELFObjectWriter.h" |
#include "IceGlobalInits.h" |
-#include "IceInstX8632.h" |
#include "IceLiveness.h" |
#include "IceOperand.h" |
-#include "IceRegistersX8632.h" |
-#include "IceTargetLoweringX8632.def" |
-#include "IceTargetLoweringX8632.h" |
#include "IceUtils.h" |
#include "llvm/Support/MathExtras.h" |
namespace Ice { |
namespace X86Internal { |
-/// A helper class to ease the settings of RandomizationPoolingPause |
-/// to disable constant blinding or pooling for some translation phases. |
+/// A helper class to ease the settings of RandomizationPoolingPause to disable |
+/// constant blinding or pooling for some translation phases. |
class BoolFlagSaver { |
BoolFlagSaver() = delete; |
BoolFlagSaver(const BoolFlagSaver &) = delete; |
@@ -85,8 +81,7 @@ public: |
}; |
/// Currently the actual enum values are not used (other than CK_None), but we |
- /// go |
- /// ahead and produce them anyway for symmetry with the |
+ /// go ahead and produce them anyway for symmetry with the |
/// BoolFoldingProducerKind. |
enum BoolFoldingConsumerKind { CK_None, CK_Br, CK_Select, CK_Sext, CK_Zext }; |
@@ -163,12 +158,11 @@ BoolFolding<MachineTraits>::getConsumerKind(const Inst *Instr) { |
return CK_None; |
} |
-/// Returns true if the producing instruction has a "complex" lowering |
-/// sequence. This generally means that its lowering sequence requires |
-/// more than one conditional branch, namely 64-bit integer compares |
-/// and some floating-point compares. When this is true, and there is |
-/// more than one consumer, we prefer to disable the folding |
-/// optimization because it minimizes branches. |
+/// Returns true if the producing instruction has a "complex" lowering sequence. |
+/// This generally means that its lowering sequence requires more than one |
+/// conditional branch, namely 64-bit integer compares and some floating-point |
+/// compares. When this is true, and there is more than one consumer, we prefer |
+/// to disable the folding optimization because it minimizes branches. |
template <class MachineTraits> |
bool BoolFolding<MachineTraits>::hasComplexLowering(const Inst *Instr) { |
switch (getProducerKind(Instr)) { |
@@ -226,10 +220,10 @@ void BoolFolding<MachineTraits>::init(CfgNode *Node) { |
setInvalid(I.first); |
continue; |
} |
- // Mark as "dead" rather than outright deleting. This is so that |
- // other peephole style optimizations during or before lowering |
- // have access to this instruction in undeleted form. See for |
- // example tryOptimizedCmpxchgCmpBr(). |
+ // Mark as "dead" rather than outright deleting. This is so that other |
+ // peephole style optimizations during or before lowering have access to |
+ // this instruction in undeleted form. See for example |
+ // tryOptimizedCmpxchgCmpBr(). |
I.second.Instr->setDead(); |
} |
} |
@@ -283,24 +277,18 @@ TargetX86Base<Machine>::TargetX86Base(Cfg *Func) |
TargetInstructionSet::X86InstructionSet_Begin) + |
Traits::InstructionSet::Begin); |
} |
- // TODO: Don't initialize IntegerRegisters and friends every time. |
- // Instead, initialize in some sort of static initializer for the |
- // class. |
+ // TODO: Don't initialize IntegerRegisters and friends every time. Instead, |
+ // initialize in some sort of static initializer for the class. |
llvm::SmallBitVector IntegerRegisters(Traits::RegisterSet::Reg_NUM); |
llvm::SmallBitVector IntegerRegistersI8(Traits::RegisterSet::Reg_NUM); |
llvm::SmallBitVector FloatRegisters(Traits::RegisterSet::Reg_NUM); |
llvm::SmallBitVector VectorRegisters(Traits::RegisterSet::Reg_NUM); |
llvm::SmallBitVector InvalidRegisters(Traits::RegisterSet::Reg_NUM); |
ScratchRegs.resize(Traits::RegisterSet::Reg_NUM); |
-#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
- frameptr, isI8, isInt, isFP) \ |
- IntegerRegisters[Traits::RegisterSet::val] = isInt; \ |
- IntegerRegistersI8[Traits::RegisterSet::val] = isI8; \ |
- FloatRegisters[Traits::RegisterSet::val] = isFP; \ |
- VectorRegisters[Traits::RegisterSet::val] = isFP; \ |
- ScratchRegs[Traits::RegisterSet::val] = scratch; |
- REGX8632_TABLE; |
-#undef X |
+ |
+ Traits::initRegisterSet(&IntegerRegisters, &IntegerRegistersI8, |
+ &FloatRegisters, &VectorRegisters, &ScratchRegs); |
+ |
TypeToRegisterSet[IceType_void] = InvalidRegisters; |
TypeToRegisterSet[IceType_i1] = IntegerRegistersI8; |
TypeToRegisterSet[IceType_i8] = IntegerRegistersI8; |
@@ -348,19 +336,18 @@ template <class Machine> void TargetX86Base<Machine>::translateO2() { |
// Argument lowering |
Func->doArgLowering(); |
- // Target lowering. This requires liveness analysis for some parts |
- // of the lowering decisions, such as compare/branch fusing. If |
- // non-lightweight liveness analysis is used, the instructions need |
- // to be renumbered first. TODO: This renumbering should only be |
- // necessary if we're actually calculating live intervals, which we |
- // only do for register allocation. |
+ // Target lowering. This requires liveness analysis for some parts of the |
+ // lowering decisions, such as compare/branch fusing. If non-lightweight |
+ // liveness analysis is used, the instructions need to be renumbered first |
+ // TODO: This renumbering should only be necessary if we're actually |
+ // calculating live intervals, which we only do for register allocation. |
Func->renumberInstructions(); |
if (Func->hasError()) |
return; |
- // TODO: It should be sufficient to use the fastest liveness |
- // calculation, i.e. livenessLightweight(). However, for some |
- // reason that slows down the rest of the translation. Investigate. |
+ // TODO: It should be sufficient to use the fastest liveness calculation, i.e. |
+ // livenessLightweight(). However, for some reason that slows down the rest |
+ // of the translation. Investigate. |
Func->liveness(Liveness_Basic); |
if (Func->hasError()) |
return; |
@@ -376,19 +363,19 @@ template <class Machine> void TargetX86Base<Machine>::translateO2() { |
return; |
Func->dump("After x86 codegen"); |
- // Register allocation. This requires instruction renumbering and |
- // full liveness analysis. |
+ // Register allocation. This requires instruction renumbering and full |
+ // liveness analysis. |
Func->renumberInstructions(); |
if (Func->hasError()) |
return; |
Func->liveness(Liveness_Intervals); |
if (Func->hasError()) |
return; |
- // Validate the live range computations. The expensive validation |
- // call is deliberately only made when assertions are enabled. |
+ // Validate the live range computations. The expensive validation call is |
+ // deliberately only made when assertions are enabled. |
assert(Func->validateLiveness()); |
- // The post-codegen dump is done here, after liveness analysis and |
- // associated cleanup, to make the dump cleaner and more useful. |
+ // The post-codegen dump is done here, after liveness analysis and associated |
+ // cleanup, to make the dump cleaner and more useful. |
Func->dump("After initial x8632 codegen"); |
Func->getVMetadata()->init(VMK_All); |
regAlloc(RAK_Global); |
@@ -397,9 +384,9 @@ template <class Machine> void TargetX86Base<Machine>::translateO2() { |
Func->dump("After linear scan regalloc"); |
if (Ctx->getFlags().getPhiEdgeSplit()) { |
- // We need to pause constant blinding or pooling during advanced |
- // phi lowering, unless the lowering assignment has a physical |
- // register for the dest Variable. |
+ // We need to pause constant blinding or pooling during advanced phi |
+ // lowering, unless the lowering assignment has a physical register for the |
+ // dest Variable. |
{ |
BoolFlagSaver B(RandomizationPoolingPaused, true); |
Func->advancedPhiLowering(); |
@@ -416,11 +403,10 @@ template <class Machine> void TargetX86Base<Machine>::translateO2() { |
Func->contractEmptyNodes(); |
Func->reorderNodes(); |
- // Branch optimization. This needs to be done just before code |
- // emission. In particular, no transformations that insert or |
- // reorder CfgNodes should be done after branch optimization. We go |
- // ahead and do it before nop insertion to reduce the amount of work |
- // needed for searching for opportunities. |
+ // Branch optimization. This needs to be done just before code emission. In |
+ // particular, no transformations that insert or reorder CfgNodes should be |
+ // done after branch optimization. We go ahead and do it before nop insertion |
+ // to reduce the amount of work needed for searching for opportunities. |
Func->doBranchOpt(); |
Func->dump("After branch optimization"); |
@@ -468,8 +454,7 @@ template <class Machine> void TargetX86Base<Machine>::translateOm1() { |
bool canRMW(const InstArithmetic *Arith) { |
Type Ty = Arith->getDest()->getType(); |
- // X86 vector instructions write to a register and have no RMW |
- // option. |
+ // X86 vector instructions write to a register and have no RMW option. |
if (isVectorType(Ty)) |
return false; |
bool isI64 = Ty == IceType_i64; |
@@ -496,11 +481,14 @@ bool canRMW(const InstArithmetic *Arith) { |
} |
} |
+template <class Machine> |
bool isSameMemAddressOperand(const Operand *A, const Operand *B) { |
if (A == B) |
return true; |
- if (auto *MemA = llvm::dyn_cast<OperandX8632Mem>(A)) { |
- if (auto *MemB = llvm::dyn_cast<OperandX8632Mem>(B)) { |
+ if (auto *MemA = llvm::dyn_cast< |
+ typename TargetX86Base<Machine>::Traits::X86OperandMem>(A)) { |
+ if (auto *MemB = llvm::dyn_cast< |
+ typename TargetX86Base<Machine>::Traits::X86OperandMem>(B)) { |
return MemA->getBase() == MemB->getBase() && |
MemA->getOffset() == MemB->getOffset() && |
MemA->getIndex() == MemB->getIndex() && |
@@ -565,8 +553,8 @@ template <class Machine> void TargetX86Base<Machine>::findRMW() { |
// still trigger, resulting in two loads and one store, which is |
// worse than the original one load and one store. However, this is |
// probably rare, and caching probably keeps it just as fast. |
- if (!isSameMemAddressOperand(Load->getSourceAddress(), |
- Store->getAddr())) |
+ if (!isSameMemAddressOperand<Machine>(Load->getSourceAddress(), |
+ Store->getAddr())) |
continue; |
Operand *ArithSrcFromLoad = Arith->getSrc(0); |
Operand *ArithSrcOther = Arith->getSrc(1); |
@@ -593,7 +581,7 @@ template <class Machine> void TargetX86Base<Machine>::findRMW() { |
Store->setRmwBeacon(Beacon); |
InstFakeDef *BeaconDef = InstFakeDef::create(Func, Beacon); |
Node->getInsts().insert(I3, BeaconDef); |
- InstX8632FakeRMW *RMW = InstX8632FakeRMW::create( |
+ auto *RMW = Traits::Insts::FakeRMW::create( |
Func, ArithSrcOther, Store->getAddr(), Beacon, Arith->getOp()); |
Node->getInsts().insert(I3, RMW); |
} |
@@ -721,22 +709,13 @@ template <class Machine> void TargetX86Base<Machine>::doLoadOpt() { |
template <class Machine> |
bool TargetX86Base<Machine>::doBranchOpt(Inst *I, const CfgNode *NextNode) { |
- if (InstX8632Br *Br = llvm::dyn_cast<InstX8632Br>(I)) { |
+ if (auto *Br = llvm::dyn_cast<typename Traits::Insts::Br>(I)) { |
return Br->optimizeBranch(NextNode); |
} |
return false; |
} |
template <class Machine> |
-IceString TargetX86Base<Machine>::RegNames[] = { |
-#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
- frameptr, isI8, isInt, isFP) \ |
- name, |
- REGX8632_TABLE |
-#undef X |
-}; |
- |
-template <class Machine> |
Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { |
if (Ty == IceType_void) |
Ty = IceType_i32; |
@@ -760,30 +739,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { |
template <class Machine> |
IceString TargetX86Base<Machine>::getRegName(SizeT RegNum, Type Ty) const { |
- assert(RegNum < Traits::RegisterSet::Reg_NUM); |
- static IceString RegNames8[] = { |
-#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
- frameptr, isI8, isInt, isFP) \ |
- name8, |
- REGX8632_TABLE |
-#undef X |
- }; |
- static IceString RegNames16[] = { |
-#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
- frameptr, isI8, isInt, isFP) \ |
- name16, |
- REGX8632_TABLE |
-#undef X |
- }; |
- switch (Ty) { |
- case IceType_i1: |
- case IceType_i8: |
- return RegNames8[RegNum]; |
- case IceType_i16: |
- return RegNames16[RegNum]; |
- default: |
- return RegNames[RegNum]; |
- } |
+ return Traits::getRegName(RegNum, Ty); |
} |
template <class Machine> |
@@ -884,17 +840,16 @@ void TargetX86Base<Machine>::finishArgumentLowering(Variable *Arg, |
InArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
if (Arg->hasReg()) { |
assert(Ty != IceType_i64); |
- OperandX8632Mem *Mem = OperandX8632Mem::create( |
+ typename Traits::X86OperandMem *Mem = Traits::X86OperandMem::create( |
Func, Ty, FramePtr, Ctx->getConstantInt32(Arg->getStackOffset())); |
if (isVectorType(Arg->getType())) { |
_movp(Arg, Mem); |
} else { |
_mov(Arg, Mem); |
} |
- // This argument-copying instruction uses an explicit |
- // OperandX8632Mem operand instead of a Variable, so its |
- // fill-from-stack operation has to be tracked separately for |
- // statistics. |
+ // This argument-copying instruction uses an explicit Traits::X86OperandMem |
+ // operand instead of a Variable, so its fill-from-stack operation has to be |
+ // tracked separately for statistics. |
Ctx->statsUpdateFills(); |
} |
} |
@@ -965,7 +920,8 @@ template <class Machine> void TargetX86Base<Machine>::addProlog(CfgNode *Node) { |
// that stack slot. |
std::function<bool(Variable *)> TargetVarHook = |
[&VariablesLinkedToSpillSlots](Variable *Var) { |
- if (SpillVariable *SpillVar = llvm::dyn_cast<SpillVariable>(Var)) { |
+ if (auto *SpillVar = |
+ llvm::dyn_cast<typename Traits::SpillVariable>(Var)) { |
assert(Var->getWeight().isZero()); |
if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) { |
VariablesLinkedToSpillSlots.push_back(Var); |
@@ -1069,7 +1025,8 @@ template <class Machine> void TargetX86Base<Machine>::addProlog(CfgNode *Node) { |
// Assign stack offsets to variables that have been linked to spilled |
// variables. |
for (Variable *Var : VariablesLinkedToSpillSlots) { |
- Variable *Linked = (llvm::cast<SpillVariable>(Var))->getLinkedTo(); |
+ Variable *Linked = |
+ (llvm::cast<typename Traits::SpillVariable>(Var))->getLinkedTo(); |
Var->setStackOffset(Linked->getStackOffset()); |
} |
this->HasComputedFrame = true; |
@@ -1106,7 +1063,7 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) { |
InstList &Insts = Node->getInsts(); |
InstList::reverse_iterator RI, E; |
for (RI = Insts.rbegin(), E = Insts.rend(); RI != E; ++RI) { |
- if (llvm::isa<InstX8632Ret>(*RI)) |
+ if (llvm::isa<typename Traits::Insts::Ret>(*RI)) |
break; |
} |
if (RI == E) |
@@ -1216,8 +1173,8 @@ Operand *TargetX86Base<Machine>::loOperand(Operand *Operand) { |
Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); |
return legalize(ConstInt); |
} |
- if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
- OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
+ if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { |
+ auto *MemOperand = Traits::X86OperandMem::create( |
Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), |
Mem->getShift(), Mem->getSegmentRegister()); |
// Test if we should randomize or pool the offset, if so randomize it or |
@@ -1245,7 +1202,7 @@ Operand *TargetX86Base<Machine>::hiOperand(Operand *Operand) { |
// check if we need to blind/pool the constant |
return legalize(ConstInt); |
} |
- if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
+ if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { |
Constant *Offset = Mem->getOffset(); |
if (Offset == nullptr) { |
Offset = Ctx->getConstantInt32(4); |
@@ -1259,7 +1216,7 @@ Operand *TargetX86Base<Machine>::hiOperand(Operand *Operand) { |
Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), |
SymOffset->getSuppressMangling()); |
} |
- OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
+ auto *MemOperand = Traits::X86OperandMem::create( |
Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), |
Mem->getShift(), Mem->getSegmentRegister()); |
// Test if the Offset is an eligible i32 constants for randomization and |
@@ -1275,32 +1232,7 @@ template <class Machine> |
llvm::SmallBitVector |
TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, |
RegSetMask Exclude) const { |
- llvm::SmallBitVector Registers(Traits::RegisterSet::Reg_NUM); |
- |
-#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
- frameptr, isI8, isInt, isFP) \ |
- if (scratch && (Include & RegSet_CallerSave)) \ |
- Registers[Traits::RegisterSet::val] = true; \ |
- if (preserved && (Include & RegSet_CalleeSave)) \ |
- Registers[Traits::RegisterSet::val] = true; \ |
- if (stackptr && (Include & RegSet_StackPointer)) \ |
- Registers[Traits::RegisterSet::val] = true; \ |
- if (frameptr && (Include & RegSet_FramePointer)) \ |
- Registers[Traits::RegisterSet::val] = true; \ |
- if (scratch && (Exclude & RegSet_CallerSave)) \ |
- Registers[Traits::RegisterSet::val] = false; \ |
- if (preserved && (Exclude & RegSet_CalleeSave)) \ |
- Registers[Traits::RegisterSet::val] = false; \ |
- if (stackptr && (Exclude & RegSet_StackPointer)) \ |
- Registers[Traits::RegisterSet::val] = false; \ |
- if (frameptr && (Exclude & RegSet_FramePointer)) \ |
- Registers[Traits::RegisterSet::val] = false; |
- |
- REGX8632_TABLE |
- |
-#undef X |
- |
- return Registers; |
+ return Traits::getRegisterSet(Include, Exclude); |
} |
template <class Machine> |
@@ -1423,17 +1355,20 @@ bool TargetX86Base<Machine>::optimizeScalarMul(Variable *Dest, Operand *Src0, |
Constant *Zero = Ctx->getConstantZero(IceType_i32); |
for (uint32_t i = 0; i < Count9; ++i) { |
const uint16_t Shift = 3; // log2(9-1) |
- _lea(T, OperandX8632Mem::create(Func, IceType_void, T, Zero, T, Shift)); |
+ _lea(T, |
+ Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); |
_set_dest_nonkillable(); |
} |
for (uint32_t i = 0; i < Count5; ++i) { |
const uint16_t Shift = 2; // log2(5-1) |
- _lea(T, OperandX8632Mem::create(Func, IceType_void, T, Zero, T, Shift)); |
+ _lea(T, |
+ Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); |
_set_dest_nonkillable(); |
} |
for (uint32_t i = 0; i < Count3; ++i) { |
const uint16_t Shift = 1; // log2(3-1) |
- _lea(T, OperandX8632Mem::create(Func, IceType_void, T, Zero, T, Shift)); |
+ _lea(T, |
+ Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); |
_set_dest_nonkillable(); |
} |
if (Count2) { |
@@ -1601,7 +1536,8 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { |
Variable *T_1 = nullptr, *T_2 = nullptr, *T_3 = nullptr; |
Constant *BitTest = Ctx->getConstantInt32(0x20); |
Constant *Zero = Ctx->getConstantZero(IceType_i32); |
- InstX8632Label *Label = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *Label = |
+ Traits::Insts::Label::create(Func, this); |
_mov(T_1, Src1Lo, Traits::RegisterSet::Reg_ecx); |
_mov(T_2, Src0Lo); |
_mov(T_3, Src0Hi); |
@@ -1636,7 +1572,8 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { |
Variable *T_1 = nullptr, *T_2 = nullptr, *T_3 = nullptr; |
Constant *BitTest = Ctx->getConstantInt32(0x20); |
Constant *Zero = Ctx->getConstantZero(IceType_i32); |
- InstX8632Label *Label = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *Label = |
+ Traits::Insts::Label::create(Func, this); |
_mov(T_1, Src1Lo, Traits::RegisterSet::Reg_ecx); |
_mov(T_2, Src0Lo); |
_mov(T_3, Src0Hi); |
@@ -1671,7 +1608,8 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { |
Variable *T_1 = nullptr, *T_2 = nullptr, *T_3 = nullptr; |
Constant *BitTest = Ctx->getConstantInt32(0x20); |
Constant *SignExtend = Ctx->getConstantInt32(0x1f); |
- InstX8632Label *Label = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *Label = |
+ Traits::Insts::Label::create(Func, this); |
_mov(T_1, Src1Lo, Traits::RegisterSet::Reg_ecx); |
_mov(T_2, Src0Lo); |
_mov(T_3, Src0Hi); |
@@ -1709,7 +1647,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { |
if (isVectorType(Dest->getType())) { |
// TODO: Trap on integer divide and integer modulo by zero. |
// See: https://code.google.com/p/nativeclient/issues/detail?id=3899 |
- if (llvm::isa<OperandX8632Mem>(Src1)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src1)) |
Src1 = legalizeToVar(Src1); |
switch (Inst->getOp()) { |
case InstArithmetic::_num: |
@@ -2208,7 +2146,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) { |
Variable *esp = |
Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); |
- StackArgLocations.push_back(OperandX8632Mem::create(Func, Ty, esp, Loc)); |
+ StackArgLocations.push_back( |
+ Traits::X86OperandMem::create(Func, Ty, esp, Loc)); |
ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); |
} |
} |
@@ -2305,7 +2244,7 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) { |
CallTarget = CallTargetVar; |
} |
} |
- Inst *NewCall = InstX8632Call::create(Func, ReturnReg, CallTarget); |
+ Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); |
Context.insert(NewCall); |
if (NeedSandboxing) |
_bundle_unlock(); |
@@ -2532,7 +2471,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
// t1 = cvt Src0RM; Dest = t1 |
Variable *T = makeReg(Dest->getType()); |
- _cvt(T, Src0RM, InstX8632Cvt::Float2float); |
+ _cvt(T, Src0RM, Traits::Insts::Cvt::Float2float); |
_mov(Dest, T); |
break; |
} |
@@ -2541,10 +2480,10 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
assert(Dest->getType() == IceType_v4i32 && |
Inst->getSrc(0)->getType() == IceType_v4f32); |
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
- if (llvm::isa<OperandX8632Mem>(Src0RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src0RM)) |
Src0RM = legalizeToVar(Src0RM); |
Variable *T = makeReg(Dest->getType()); |
- _cvt(T, Src0RM, InstX8632Cvt::Tps2dq); |
+ _cvt(T, Src0RM, Traits::Insts::Cvt::Tps2dq); |
_movp(Dest, T); |
} else if (Dest->getType() == IceType_i64) { |
// Use a helper for converting floating-point values to 64-bit |
@@ -2567,7 +2506,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
// t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type |
Variable *T_1 = makeReg(IceType_i32); |
Variable *T_2 = makeReg(Dest->getType()); |
- _cvt(T_1, Src0RM, InstX8632Cvt::Tss2si); |
+ _cvt(T_1, Src0RM, Traits::Insts::Cvt::Tss2si); |
_mov(T_2, T_1); // T_1 and T_2 may have different integer types |
if (Dest->getType() == IceType_i1) |
_and(T_2, Ctx->getConstantInt1(1)); |
@@ -2606,7 +2545,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
// t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type |
Variable *T_1 = makeReg(IceType_i32); |
Variable *T_2 = makeReg(Dest->getType()); |
- _cvt(T_1, Src0RM, InstX8632Cvt::Tss2si); |
+ _cvt(T_1, Src0RM, Traits::Insts::Cvt::Tss2si); |
_mov(T_2, T_1); // T_1 and T_2 may have different integer types |
if (Dest->getType() == IceType_i1) |
_and(T_2, Ctx->getConstantInt1(1)); |
@@ -2618,10 +2557,10 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
assert(Dest->getType() == IceType_v4f32 && |
Inst->getSrc(0)->getType() == IceType_v4i32); |
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
- if (llvm::isa<OperandX8632Mem>(Src0RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src0RM)) |
Src0RM = legalizeToVar(Src0RM); |
Variable *T = makeReg(Dest->getType()); |
- _cvt(T, Src0RM, InstX8632Cvt::Dq2ps); |
+ _cvt(T, Src0RM, Traits::Insts::Cvt::Dq2ps); |
_movp(Dest, T); |
} else if (Inst->getSrc(0)->getType() == IceType_i64) { |
// Use a helper for x86-32. |
@@ -2645,7 +2584,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
_mov(T_1, Src0RM); |
else |
_movsx(T_1, Src0RM); |
- _cvt(T_2, T_1, InstX8632Cvt::Si2ss); |
+ _cvt(T_2, T_1, Traits::Insts::Cvt::Si2ss); |
_mov(Dest, T_2); |
} |
break; |
@@ -2686,7 +2625,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
_mov(T_1, Src0RM); |
else |
_movzx(T_1, Src0RM); |
- _cvt(T_2, T_1, InstX8632Cvt::Si2ss); |
+ _cvt(T_2, T_1, Traits::Insts::Cvt::Si2ss); |
_mov(Dest, T_2); |
} |
break; |
@@ -2728,8 +2667,8 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
Variable *T = nullptr; |
// TODO: Should be able to force a spill setup by calling legalize() with |
// Legal_Mem and not Legal_Reg or Legal_Imm. |
- SpillVariable *SpillVar = |
- Func->template makeVariable<SpillVariable>(SrcType); |
+ typename Traits::SpillVariable *SpillVar = |
+ Func->template makeVariable<typename Traits::SpillVariable>(SrcType); |
SpillVar->setLinkedTo(Dest); |
Variable *Spill = SpillVar; |
Spill->setWeight(RegWeight::Zero); |
@@ -2748,14 +2687,17 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
// a_hi.i32 = t_hi.i32 |
Operand *SpillLo, *SpillHi; |
if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0RM)) { |
- SpillVariable *SpillVar = |
- Func->template makeVariable<SpillVariable>(IceType_f64); |
+ typename Traits::SpillVariable *SpillVar = |
+ Func->template makeVariable<typename Traits::SpillVariable>( |
+ IceType_f64); |
SpillVar->setLinkedTo(Src0Var); |
Variable *Spill = SpillVar; |
Spill->setWeight(RegWeight::Zero); |
_movq(Spill, Src0RM); |
- SpillLo = VariableSplit::create(Func, Spill, VariableSplit::Low); |
- SpillHi = VariableSplit::create(Func, Spill, VariableSplit::High); |
+ SpillLo = Traits::VariableSplit::create(Func, Spill, |
+ Traits::VariableSplit::Low); |
+ SpillHi = Traits::VariableSplit::create(Func, Spill, |
+ Traits::VariableSplit::High); |
} else { |
SpillLo = loOperand(Src0RM); |
SpillHi = hiOperand(Src0RM); |
@@ -2774,7 +2716,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
case IceType_f64: { |
Src0 = legalize(Src0); |
assert(Src0->getType() == IceType_i64); |
- if (llvm::isa<OperandX8632Mem>(Src0)) { |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src0)) { |
Variable *T = Func->template makeVariable(Dest->getType()); |
_movq(T, Src0); |
_movq(Dest, T); |
@@ -2787,17 +2729,18 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { |
// t_hi.i32 = b_hi.i32 |
// hi(s.f64) = t_hi.i32 |
// a.f64 = s.f64 |
- SpillVariable *SpillVar = |
- Func->template makeVariable<SpillVariable>(IceType_f64); |
+ typename Traits::SpillVariable *SpillVar = |
+ Func->template makeVariable<typename Traits::SpillVariable>( |
+ IceType_f64); |
SpillVar->setLinkedTo(Dest); |
Variable *Spill = SpillVar; |
Spill->setWeight(RegWeight::Zero); |
Variable *T_Lo = nullptr, *T_Hi = nullptr; |
- VariableSplit *SpillLo = |
- VariableSplit::create(Func, Spill, VariableSplit::Low); |
- VariableSplit *SpillHi = |
- VariableSplit::create(Func, Spill, VariableSplit::High); |
+ typename Traits::VariableSplit *SpillLo = Traits::VariableSplit::create( |
+ Func, Spill, Traits::VariableSplit::Low); |
+ typename Traits::VariableSplit *SpillHi = Traits::VariableSplit::create( |
+ Func, Spill, Traits::VariableSplit::High); |
_mov(T_Lo, loOperand(Src0)); |
// Technically, the Spill is defined after the _store happens, but |
// SpillLo is considered a "use" of Spill so define Spill before it |
@@ -2897,7 +2840,7 @@ void TargetX86Base<Machine>::lowerExtractElement( |
// Compute the location of the element in memory. |
unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); |
- OperandX8632Mem *Loc = |
+ typename Traits::X86OperandMem *Loc = |
getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
_mov(ExtractedElementR, Loc); |
} |
@@ -2943,7 +2886,7 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) { |
} else { |
Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
Operand *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem); |
- if (llvm::isa<OperandX8632Mem>(Src1RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src1RM)) |
Src1RM = legalizeToVar(Src1RM); |
switch (Condition) { |
@@ -3018,7 +2961,8 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) { |
Constant *Default = Ctx->getConstantInt32(Traits::TableFcmp[Index].Default); |
_mov(Dest, Default); |
if (HasC1) { |
- InstX8632Label *Label = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *Label = |
+ Traits::Insts::Label::create(Func, this); |
_br(Traits::TableFcmp[Index].C1, Label); |
if (HasC2) { |
_br(Traits::TableFcmp[Index].C2, Label); |
@@ -3091,13 +3035,13 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { |
llvm_unreachable("unexpected condition"); |
break; |
case InstIcmp::Eq: { |
- if (llvm::isa<OperandX8632Mem>(Src1RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src1RM)) |
Src1RM = legalizeToVar(Src1RM); |
_movp(T, Src0RM); |
_pcmpeq(T, Src1RM); |
} break; |
case InstIcmp::Ne: { |
- if (llvm::isa<OperandX8632Mem>(Src1RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src1RM)) |
Src1RM = legalizeToVar(Src1RM); |
_movp(T, Src0RM); |
_pcmpeq(T, Src1RM); |
@@ -3106,7 +3050,7 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { |
} break; |
case InstIcmp::Ugt: |
case InstIcmp::Sgt: { |
- if (llvm::isa<OperandX8632Mem>(Src1RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src1RM)) |
Src1RM = legalizeToVar(Src1RM); |
_movp(T, Src0RM); |
_pcmpgt(T, Src1RM); |
@@ -3114,7 +3058,7 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { |
case InstIcmp::Uge: |
case InstIcmp::Sge: { |
// !(Src1RM > Src0RM) |
- if (llvm::isa<OperandX8632Mem>(Src0RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src0RM)) |
Src0RM = legalizeToVar(Src0RM); |
_movp(T, Src1RM); |
_pcmpgt(T, Src0RM); |
@@ -3123,7 +3067,7 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { |
} break; |
case InstIcmp::Ult: |
case InstIcmp::Slt: { |
- if (llvm::isa<OperandX8632Mem>(Src0RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src0RM)) |
Src0RM = legalizeToVar(Src0RM); |
_movp(T, Src1RM); |
_pcmpgt(T, Src0RM); |
@@ -3131,7 +3075,7 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { |
case InstIcmp::Ule: |
case InstIcmp::Sle: { |
// !(Src0RM > Src1RM) |
- if (llvm::isa<OperandX8632Mem>(Src1RM)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src1RM)) |
Src1RM = legalizeToVar(Src1RM); |
_movp(T, Src0RM); |
_pcmpgt(T, Src1RM); |
@@ -3156,8 +3100,10 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { |
Operand *Src1HiRI = legalize(hiOperand(Src1), Legal_Reg | Legal_Imm); |
Constant *Zero = Ctx->getConstantZero(IceType_i32); |
Constant *One = Ctx->getConstantInt32(1); |
- InstX8632Label *LabelFalse = InstX8632Label::create(Func, this); |
- InstX8632Label *LabelTrue = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *LabelFalse = |
+ Traits::Insts::Label::create(Func, this); |
+ typename Traits::Insts::Label *LabelTrue = |
+ Traits::Insts::Label::create(Func, this); |
_mov(Dest, One); |
_cmp(Src0HiRM, Src1HiRI); |
if (Traits::TableIcmp64[Index].C1 != Traits::Cond::Br_None) |
@@ -3293,7 +3239,7 @@ void TargetX86Base<Machine>::lowerInsertElement(const InstInsertElement *Inst) { |
// Compute the location of the position to insert in memory. |
unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); |
- OperandX8632Mem *Loc = |
+ typename Traits::X86OperandMem *Loc = |
getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
_store(legalizeToVar(ElementToInsertNotLegalized), Loc); |
@@ -3383,7 +3329,8 @@ void TargetX86Base<Machine>::lowerIntrinsicCall( |
// can't happen anyway, since this is x86-32 and integer arithmetic only |
// happens on 32-bit quantities. |
Variable *T = makeReg(IceType_f64); |
- OperandX8632Mem *Addr = formMemoryOperand(Instr->getArg(0), IceType_f64); |
+ typename Traits::X86OperandMem *Addr = |
+ formMemoryOperand(Instr->getArg(0), IceType_f64); |
_movq(T, Addr); |
// Then cast the bits back out of the XMM register to the i64 Dest. |
InstCast *Cast = InstCast::create(Func, InstCast::Bitcast, Dest, T); |
@@ -3433,7 +3380,8 @@ void TargetX86Base<Machine>::lowerIntrinsicCall( |
InstCast *Cast = InstCast::create(Func, InstCast::Bitcast, T, Value); |
lowerCast(Cast); |
// Then store XMM w/ a movq. |
- OperandX8632Mem *Addr = formMemoryOperand(Ptr, IceType_f64); |
+ typename Traits::X86OperandMem *Addr = |
+ formMemoryOperand(Ptr, IceType_f64); |
_storeq(T, Addr); |
_mfence(); |
return; |
@@ -3535,7 +3483,7 @@ void TargetX86Base<Machine>::lowerIntrinsicCall( |
// The pand instruction operates on an m128 memory operand, so if |
// Src is an f32 or f64, we need to make sure it's in a register. |
if (isVectorType(Ty)) { |
- if (llvm::isa<OperandX8632Mem>(Src)) |
+ if (llvm::isa<typename Traits::X86OperandMem>(Src)) |
Src = legalizeToVar(Src); |
} else { |
Src = legalizeToVar(Src); |
@@ -3590,9 +3538,9 @@ void TargetX86Base<Machine>::lowerIntrinsicCall( |
case Intrinsics::NaClReadTP: { |
if (Ctx->getFlags().getUseSandboxing()) { |
Constant *Zero = Ctx->getConstantZero(IceType_i32); |
- Operand *Src = |
- OperandX8632Mem::create(Func, IceType_i32, nullptr, Zero, nullptr, 0, |
- OperandX8632Mem::SegReg_GS); |
+ Operand *Src = Traits::X86OperandMem::create( |
+ Func, IceType_i32, nullptr, Zero, nullptr, 0, |
+ Traits::X86OperandMem::SegReg_GS); |
Variable *Dest = Instr->getDest(); |
Variable *T = nullptr; |
_mov(T, Src); |
@@ -3655,7 +3603,8 @@ void TargetX86Base<Machine>::lowerAtomicCmpxchg(Variable *DestPrev, |
_mov(T_edx, hiOperand(Expected)); |
_mov(T_ebx, loOperand(Desired)); |
_mov(T_ecx, hiOperand(Desired)); |
- OperandX8632Mem *Addr = formMemoryOperand(Ptr, Expected->getType()); |
+ typename Traits::X86OperandMem *Addr = |
+ formMemoryOperand(Ptr, Expected->getType()); |
const bool Locked = true; |
_cmpxchg8b(Addr, T_edx, T_eax, T_ecx, T_ebx, Locked); |
Variable *DestLo = llvm::cast<Variable>(loOperand(DestPrev)); |
@@ -3666,7 +3615,8 @@ void TargetX86Base<Machine>::lowerAtomicCmpxchg(Variable *DestPrev, |
} |
Variable *T_eax = makeReg(Expected->getType(), Traits::RegisterSet::Reg_eax); |
_mov(T_eax, Expected); |
- OperandX8632Mem *Addr = formMemoryOperand(Ptr, Expected->getType()); |
+ typename Traits::X86OperandMem *Addr = |
+ formMemoryOperand(Ptr, Expected->getType()); |
Variable *DesiredReg = legalizeToVar(Desired); |
const bool Locked = true; |
_cmpxchg(Addr, T_eax, DesiredReg, Locked); |
@@ -3768,7 +3718,8 @@ void TargetX86Base<Machine>::lowerAtomicRMW(Variable *Dest, uint32_t Operation, |
Op_Hi = &TargetX86Base<Machine>::_adc; |
break; |
} |
- OperandX8632Mem *Addr = formMemoryOperand(Ptr, Dest->getType()); |
+ typename Traits::X86OperandMem *Addr = |
+ formMemoryOperand(Ptr, Dest->getType()); |
const bool Locked = true; |
Variable *T = nullptr; |
_mov(T, Val); |
@@ -3783,7 +3734,8 @@ void TargetX86Base<Machine>::lowerAtomicRMW(Variable *Dest, uint32_t Operation, |
Op_Hi = &TargetX86Base<Machine>::_sbb; |
break; |
} |
- OperandX8632Mem *Addr = formMemoryOperand(Ptr, Dest->getType()); |
+ typename Traits::X86OperandMem *Addr = |
+ formMemoryOperand(Ptr, Dest->getType()); |
const bool Locked = true; |
Variable *T = nullptr; |
_mov(T, Val); |
@@ -3821,7 +3773,8 @@ void TargetX86Base<Machine>::lowerAtomicRMW(Variable *Dest, uint32_t Operation, |
Op_Hi = nullptr; |
break; |
} |
- OperandX8632Mem *Addr = formMemoryOperand(Ptr, Dest->getType()); |
+ typename Traits::X86OperandMem *Addr = |
+ formMemoryOperand(Ptr, Dest->getType()); |
Variable *T = nullptr; |
_mov(T, Val); |
_xchg(Addr, T); |
@@ -3869,12 +3822,13 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo, |
if (Ty == IceType_i64) { |
Variable *T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx); |
Variable *T_eax = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax); |
- OperandX8632Mem *Addr = formMemoryOperand(Ptr, Ty); |
+ typename Traits::X86OperandMem *Addr = formMemoryOperand(Ptr, Ty); |
_mov(T_eax, loOperand(Addr)); |
_mov(T_edx, hiOperand(Addr)); |
Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); |
Variable *T_ebx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ebx); |
- InstX8632Label *Label = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *Label = |
+ Traits::Insts::Label::create(Func, this); |
const bool IsXchg8b = Op_Lo == nullptr && Op_Hi == nullptr; |
if (!IsXchg8b) { |
Context.insert(Label); |
@@ -3916,10 +3870,11 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo, |
_mov(DestHi, T_edx); |
return; |
} |
- OperandX8632Mem *Addr = formMemoryOperand(Ptr, Ty); |
+ typename Traits::X86OperandMem *Addr = formMemoryOperand(Ptr, Ty); |
Variable *T_eax = makeReg(Ty, Traits::RegisterSet::Reg_eax); |
_mov(T_eax, Addr); |
- InstX8632Label *Label = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *Label = |
+ Traits::Insts::Label::create(Func, this); |
Context.insert(Label); |
// We want to pick a different register for T than Eax, so don't use |
// _mov(T == nullptr, T_eax). |
@@ -4260,11 +4215,11 @@ void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, |
template <class Machine> |
void TargetX86Base<Machine>::lowerLoad(const InstLoad *Load) { |
- // A Load instruction can be treated the same as an Assign |
- // instruction, after the source operand is transformed into an |
- // OperandX8632Mem operand. Note that the address mode |
- // optimization already creates an OperandX8632Mem operand, so it |
- // doesn't need another level of transformation. |
+ // A Load instruction can be treated the same as an Assign instruction, after |
+ // the source operand is transformed into an Traits::X86OperandMem operand. |
+ // Note that the address mode optimization already creates an |
+ // Traits::X86OperandMem operand, so it doesn't need another level of |
+ // transformation. |
Variable *DestLoad = Load->getDest(); |
Type Ty = DestLoad->getType(); |
Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); |
@@ -4279,19 +4234,19 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { |
Variable *Index = nullptr; |
uint16_t Shift = 0; |
int32_t Offset = 0; // TODO: make Constant |
- // Vanilla ICE load instructions should not use the segment registers, |
- // and computeAddressOpt only works at the level of Variables and Constants, |
- // not other OperandX8632Mem, so there should be no mention of segment |
+ // Vanilla ICE load instructions should not use the segment registers, and |
+ // computeAddressOpt only works at the level of Variables and Constants, not |
+ // other Traits::X86OperandMem, so there should be no mention of segment |
// registers there either. |
- const OperandX8632Mem::SegmentRegisters SegmentReg = |
- OperandX8632Mem::DefaultSegment; |
+ const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = |
+ Traits::X86OperandMem::DefaultSegment; |
Variable *Base = llvm::dyn_cast<Variable>(Addr); |
computeAddressOpt(Func, Inst, Base, Index, Shift, Offset); |
if (Base && Addr != Base) { |
Inst->setDeleted(); |
Constant *OffsetOp = Ctx->getConstantInt32(Offset); |
- Addr = OperandX8632Mem::create(Func, Dest->getType(), Base, OffsetOp, Index, |
- Shift, SegmentReg); |
+ Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, |
+ Index, Shift, SegmentReg); |
Context.insert(InstLoad::create(Func, Dest, Addr)); |
} |
} |
@@ -4438,7 +4393,8 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) { |
// The cmov instruction doesn't allow 8-bit or FP operands, so |
// we need explicit control flow. |
// d=cmp e,f; a=d?b:c ==> cmp e,f; a=b; jne L1; a=c; L1: |
- InstX8632Label *Label = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *Label = |
+ Traits::Insts::Label::create(Func, this); |
SrcT = legalize(SrcT, Legal_Reg | Legal_Imm); |
_mov(Dest, SrcT); |
_br(Cond, Label); |
@@ -4453,7 +4409,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) { |
// mov t, SrcT; cmov_!cond t, SrcF; mov dest, t |
if (llvm::isa<Constant>(SrcT) && !llvm::isa<Constant>(SrcF)) { |
std::swap(SrcT, SrcF); |
- Cond = InstX8632::getOppositeCondition(Cond); |
+ Cond = InstX86Base<Machine>::getOppositeCondition(Cond); |
} |
if (DestTy == IceType_i64) { |
// Set the low portion. |
@@ -4488,15 +4444,18 @@ template <class Machine> |
void TargetX86Base<Machine>::lowerStore(const InstStore *Inst) { |
Operand *Value = Inst->getData(); |
Operand *Addr = Inst->getAddr(); |
- OperandX8632Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); |
+ typename Traits::X86OperandMem *NewAddr = |
+ formMemoryOperand(Addr, Value->getType()); |
Type Ty = NewAddr->getType(); |
if (Ty == IceType_i64) { |
Value = legalize(Value); |
Operand *ValueHi = legalize(hiOperand(Value), Legal_Reg | Legal_Imm); |
Operand *ValueLo = legalize(loOperand(Value), Legal_Reg | Legal_Imm); |
- _store(ValueHi, llvm::cast<OperandX8632Mem>(hiOperand(NewAddr))); |
- _store(ValueLo, llvm::cast<OperandX8632Mem>(loOperand(NewAddr))); |
+ _store(ValueHi, |
+ llvm::cast<typename Traits::X86OperandMem>(hiOperand(NewAddr))); |
+ _store(ValueLo, |
+ llvm::cast<typename Traits::X86OperandMem>(loOperand(NewAddr))); |
} else if (isVectorType(Ty)) { |
_storep(legalizeToVar(Value), NewAddr); |
} else { |
@@ -4513,18 +4472,18 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptStore() { |
uint16_t Shift = 0; |
int32_t Offset = 0; // TODO: make Constant |
Variable *Base = llvm::dyn_cast<Variable>(Addr); |
- // Vanilla ICE store instructions should not use the segment registers, |
- // and computeAddressOpt only works at the level of Variables and Constants, |
- // not other OperandX8632Mem, so there should be no mention of segment |
+ // Vanilla ICE store instructions should not use the segment registers, and |
+ // computeAddressOpt only works at the level of Variables and Constants, not |
+ // other Traits::X86OperandMem, so there should be no mention of segment |
// registers there either. |
- const OperandX8632Mem::SegmentRegisters SegmentReg = |
- OperandX8632Mem::DefaultSegment; |
+ const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = |
+ Traits::X86OperandMem::DefaultSegment; |
computeAddressOpt(Func, Inst, Base, Index, Shift, Offset); |
if (Base && Addr != Base) { |
Inst->setDeleted(); |
Constant *OffsetOp = Ctx->getConstantInt32(Offset); |
- Addr = OperandX8632Mem::create(Func, Data->getType(), Base, OffsetOp, Index, |
- Shift, SegmentReg); |
+ Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, |
+ Index, Shift, SegmentReg); |
InstStore *NewStore = InstStore::create(Func, Data, Addr); |
if (Inst->getDest()) |
NewStore->setRmwBeacon(Inst->getRmwBeacon()); |
@@ -4552,7 +4511,8 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) { |
for (SizeT I = 0; I < NumCases; ++I) { |
Constant *ValueLo = Ctx->getConstantInt32(Inst->getValue(I)); |
Constant *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32); |
- InstX8632Label *Label = InstX8632Label::create(Func, this); |
+ typename Traits::Insts::Label *Label = |
+ Traits::Insts::Label::create(Func, this); |
_cmp(Src0Lo, ValueLo); |
_br(Traits::Cond::Br_ne, Label); |
_cmp(Src0Hi, ValueHi); |
@@ -4639,7 +4599,8 @@ void TargetX86Base<Machine>::lowerUnreachable( |
} |
template <class Machine> |
-void TargetX86Base<Machine>::lowerRMW(const InstX8632FakeRMW *RMW) { |
+void TargetX86Base<Machine>::lowerRMW( |
+ const typename Traits::Insts::FakeRMW *RMW) { |
// If the beacon variable's live range does not end in this |
// instruction, then it must end in the modified Store instruction |
// that follows. This means that the original Store instruction is |
@@ -4651,12 +4612,14 @@ void TargetX86Base<Machine>::lowerRMW(const InstX8632FakeRMW *RMW) { |
return; |
Operand *Src = RMW->getData(); |
Type Ty = Src->getType(); |
- OperandX8632Mem *Addr = formMemoryOperand(RMW->getAddr(), Ty); |
+ typename Traits::X86OperandMem *Addr = formMemoryOperand(RMW->getAddr(), Ty); |
if (Ty == IceType_i64) { |
Operand *SrcLo = legalize(loOperand(Src), Legal_Reg | Legal_Imm); |
Operand *SrcHi = legalize(hiOperand(Src), Legal_Reg | Legal_Imm); |
- OperandX8632Mem *AddrLo = llvm::cast<OperandX8632Mem>(loOperand(Addr)); |
- OperandX8632Mem *AddrHi = llvm::cast<OperandX8632Mem>(hiOperand(Addr)); |
+ typename Traits::X86OperandMem *AddrLo = |
+ llvm::cast<typename Traits::X86OperandMem>(loOperand(Addr)); |
+ typename Traits::X86OperandMem *AddrHi = |
+ llvm::cast<typename Traits::X86OperandMem>(hiOperand(Addr)); |
switch (RMW->getOp()) { |
default: |
// TODO(stichnot): Implement other arithmetic operators. |
@@ -4715,7 +4678,8 @@ void TargetX86Base<Machine>::lowerRMW(const InstX8632FakeRMW *RMW) { |
template <class Machine> |
void TargetX86Base<Machine>::lowerOther(const Inst *Instr) { |
- if (const auto *RMW = llvm::dyn_cast<InstX8632FakeRMW>(Instr)) { |
+ if (const auto *RMW = |
+ llvm::dyn_cast<typename Traits::Insts::FakeRMW>(Instr)) { |
lowerRMW(RMW); |
} else { |
TargetLowering::lowerOther(Instr); |
@@ -4991,7 +4955,7 @@ Variable *TargetX86Base<Machine>::makeVectorOfFabsMask(Type Ty, |
} |
template <class Machine> |
-OperandX8632Mem * |
+typename TargetX86Base<Machine>::Traits::X86OperandMem * |
TargetX86Base<Machine>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot, |
uint32_t Offset) { |
// Ensure that Loc is a stack slot. |
@@ -5005,7 +4969,7 @@ TargetX86Base<Machine>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot, |
Variable *Loc = makeReg(PointerType); |
_lea(Loc, Slot); |
Constant *ConstantOffset = Ctx->getConstantInt32(Offset); |
- return OperandX8632Mem::create(Func, Ty, Loc, ConstantOffset); |
+ return Traits::X86OperandMem::create(Func, Ty, Loc, ConstantOffset); |
} |
/// Helper for legalize() to emit the right code to lower an operand to a |
@@ -5037,7 +5001,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
// or in ecx.) |
assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); |
- if (auto Mem = llvm::dyn_cast<OperandX8632Mem>(From)) { |
+ if (auto Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(From)) { |
// Before doing anything with a Mem operand, we need to ensure |
// that the Base and Index components are in physical registers. |
Variable *Base = Mem->getBase(); |
@@ -5051,9 +5015,9 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
RegIndex = legalizeToVar(Index); |
} |
if (Base != RegBase || Index != RegIndex) { |
- Mem = |
- OperandX8632Mem::create(Func, Ty, RegBase, Mem->getOffset(), RegIndex, |
- Mem->getShift(), Mem->getSegmentRegister()); |
+ Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Mem->getOffset(), |
+ RegIndex, Mem->getShift(), |
+ Mem->getSegmentRegister()); |
} |
// For all Memory Operands, we do randomization/pooling here |
@@ -5103,7 +5067,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
llvm::cast<Constant>(From)->emitPoolLabel(StrBuf); |
llvm::cast<Constant>(From)->setShouldBePooled(true); |
Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
- From = OperandX8632Mem::create(Func, Ty, Base, Offset); |
+ From = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
} |
bool NeedsReg = false; |
if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) |
@@ -5162,13 +5126,13 @@ Operand *TargetX86Base<Machine>::legalizeSrc0ForCmp(Operand *Src0, |
} |
template <class Machine> |
-OperandX8632Mem *TargetX86Base<Machine>::formMemoryOperand(Operand *Opnd, |
- Type Ty, |
- bool DoLegalize) { |
- OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Opnd); |
- // It may be the case that address mode optimization already creates |
- // an OperandX8632Mem, so in that case it wouldn't need another level |
- // of transformation. |
+typename TargetX86Base<Machine>::Traits::X86OperandMem * |
+TargetX86Base<Machine>::formMemoryOperand(Operand *Opnd, Type Ty, |
+ bool DoLegalize) { |
+ auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Opnd); |
+ // It may be the case that address mode optimization already creates an |
+ // Traits::X86OperandMem, so in that case it wouldn't need another level of |
+ // transformation. |
if (!Mem) { |
Variable *Base = llvm::dyn_cast<Variable>(Opnd); |
Constant *Offset = llvm::dyn_cast<Constant>(Opnd); |
@@ -5188,11 +5152,11 @@ OperandX8632Mem *TargetX86Base<Machine>::formMemoryOperand(Operand *Opnd, |
assert(llvm::isa<ConstantInteger32>(Offset) || |
llvm::isa<ConstantRelocatable>(Offset)); |
} |
- Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); |
+ Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
} |
// Do legalization, which contains randomization/pooling |
// or do randomization/pooling. |
- return llvm::cast<OperandX8632Mem>( |
+ return llvm::cast<typename Traits::X86OperandMem>( |
DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); |
} |
@@ -5218,68 +5182,8 @@ template <class Machine> |
void TargetX86Base<Machine>::makeRandomRegisterPermutation( |
llvm::SmallVectorImpl<int32_t> &Permutation, |
const llvm::SmallBitVector &ExcludeRegisters) const { |
- // TODO(stichnot): Declaring Permutation this way loses type/size |
- // information. Fix this in conjunction with the caller-side TODO. |
- assert(Permutation.size() >= Traits::RegisterSet::Reg_NUM); |
- // Expected upper bound on the number of registers in a single |
- // equivalence class. For x86-32, this would comprise the 8 XMM |
- // registers. This is for performance, not correctness. |
- static const unsigned MaxEquivalenceClassSize = 8; |
- typedef llvm::SmallVector<int32_t, MaxEquivalenceClassSize> RegisterList; |
- typedef std::map<uint32_t, RegisterList> EquivalenceClassMap; |
- EquivalenceClassMap EquivalenceClasses; |
- SizeT NumShuffled = 0, NumPreserved = 0; |
- |
-// Build up the equivalence classes of registers by looking at the |
-// register properties as well as whether the registers should be |
-// explicitly excluded from shuffling. |
-#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
- frameptr, isI8, isInt, isFP) \ |
- if (ExcludeRegisters[Traits::RegisterSet::val]) { \ |
- /* val stays the same in the resulting permutation. */ \ |
- Permutation[Traits::RegisterSet::val] = Traits::RegisterSet::val; \ |
- ++NumPreserved; \ |
- } else { \ |
- const uint32_t Index = (scratch << 0) | (preserved << 1) | (isI8 << 2) | \ |
- (isInt << 3) | (isFP << 4); \ |
- /* val is assigned to an equivalence class based on its properties. */ \ |
- EquivalenceClasses[Index].push_back(Traits::RegisterSet::val); \ |
- } |
- REGX8632_TABLE |
-#undef X |
- |
- RandomNumberGeneratorWrapper RNG(Ctx->getRNG()); |
- |
- // Shuffle the resulting equivalence classes. |
- for (auto I : EquivalenceClasses) { |
- const RegisterList &List = I.second; |
- RegisterList Shuffled(List); |
- RandomShuffle(Shuffled.begin(), Shuffled.end(), RNG); |
- for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { |
- Permutation[List[SI]] = Shuffled[SI]; |
- ++NumShuffled; |
- } |
- } |
- |
- assert(NumShuffled + NumPreserved == Traits::RegisterSet::Reg_NUM); |
- |
- if (Func->isVerbose(IceV_Random)) { |
- OstreamLocker L(Func->getContext()); |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "Register equivalence classes:\n"; |
- for (auto I : EquivalenceClasses) { |
- Str << "{"; |
- const RegisterList &List = I.second; |
- bool First = true; |
- for (int32_t Register : List) { |
- if (!First) |
- Str << " "; |
- First = false; |
- Str << getRegName(Register, IceType_i32); |
- } |
- Str << "}\n"; |
- } |
- } |
+ Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, |
+ ExcludeRegisters); |
} |
template <class Machine> |
@@ -5350,8 +5254,8 @@ Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, |
uint32_t Cookie = Ctx->getRandomizationCookie(); |
_mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value)); |
Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie); |
- _lea(Reg, |
- OperandX8632Mem::create(Func, IceType_i32, Reg, Offset, nullptr, 0)); |
+ _lea(Reg, Traits::X86OperandMem::create(Func, IceType_i32, Reg, Offset, |
+ nullptr, 0)); |
// make sure liveness analysis won't kill this variable, otherwise a |
// liveness |
// assertion will be triggered. |
@@ -5384,8 +5288,9 @@ Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, |
const bool SuppressMangling = true; |
Constant *Symbol = |
Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); |
- OperandX8632Mem *MemOperand = |
- OperandX8632Mem::create(Func, Immediate->getType(), nullptr, Symbol); |
+ typename Traits::X86OperandMem *MemOperand = |
+ Traits::X86OperandMem::create(Func, Immediate->getType(), nullptr, |
+ Symbol); |
_mov(Reg, MemOperand); |
return Reg; |
} |
@@ -5396,9 +5301,9 @@ Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, |
} |
template <class Machine> |
-OperandX8632Mem * |
-TargetX86Base<Machine>::randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, |
- int32_t RegNum) { |
+typename TargetX86Base<Machine>::Traits::X86OperandMem * |
+TargetX86Base<Machine>::randomizeOrPoolImmediate( |
+ typename Traits::X86OperandMem *MemOperand, int32_t RegNum) { |
assert(MemOperand); |
if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || |
RandomizationPoolingPaused == true) { |
@@ -5432,8 +5337,9 @@ TargetX86Base<Machine>::randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, |
Constant *Mask2 = |
Ctx->getConstantInt(MemOperand->getOffset()->getType(), 0 - Cookie); |
- OperandX8632Mem *TempMemOperand = OperandX8632Mem::create( |
- Func, MemOperand->getType(), MemOperand->getBase(), Mask1); |
+ typename Traits::X86OperandMem *TempMemOperand = |
+ Traits::X86OperandMem::create(Func, MemOperand->getType(), |
+ MemOperand->getBase(), Mask1); |
// If we have already assigned a physical register, we must come from |
// advancedPhiLowering()=>lowerAssign(). In this case we should reuse |
// the assigned register as this assignment is that start of its use-def |
@@ -5447,9 +5353,11 @@ TargetX86Base<Machine>::randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, |
if (RegNum != Variable::NoRegister) |
_set_dest_nonkillable(); |
- OperandX8632Mem *NewMemOperand = OperandX8632Mem::create( |
- Func, MemOperand->getType(), RegTemp, Mask2, MemOperand->getIndex(), |
- MemOperand->getShift(), MemOperand->getSegmentRegister()); |
+ typename Traits::X86OperandMem *NewMemOperand = |
+ Traits::X86OperandMem::create(Func, MemOperand->getType(), RegTemp, |
+ Mask2, MemOperand->getIndex(), |
+ MemOperand->getShift(), |
+ MemOperand->getSegmentRegister()); |
// Label this memory operand as randomize, so we won't randomize it |
// again in case we call legalize() mutiple times on this memory |
@@ -5484,23 +5392,26 @@ TargetX86Base<Machine>::randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, |
bool SuppressMangling = true; |
Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), |
SuppressMangling); |
- OperandX8632Mem *SymbolOperand = OperandX8632Mem::create( |
- Func, MemOperand->getOffset()->getType(), nullptr, Symbol); |
+ typename Traits::X86OperandMem *SymbolOperand = |
+ Traits::X86OperandMem::create( |
+ Func, MemOperand->getOffset()->getType(), nullptr, Symbol); |
_mov(RegTemp, SymbolOperand); |
// If we have a base variable here, we should add the lea instruction |
// to add the value of the base variable to RegTemp. If there is no |
// base variable, we won't need this lea instruction. |
if (MemOperand->getBase()) { |
- OperandX8632Mem *CalculateOperand = OperandX8632Mem::create( |
- Func, MemOperand->getType(), MemOperand->getBase(), nullptr, |
- RegTemp, 0, MemOperand->getSegmentRegister()); |
+ typename Traits::X86OperandMem *CalculateOperand = |
+ Traits::X86OperandMem::create( |
+ Func, MemOperand->getType(), MemOperand->getBase(), nullptr, |
+ RegTemp, 0, MemOperand->getSegmentRegister()); |
_lea(RegTemp, CalculateOperand); |
_set_dest_nonkillable(); |
} |
- OperandX8632Mem *NewMemOperand = OperandX8632Mem::create( |
- Func, MemOperand->getType(), RegTemp, nullptr, |
- MemOperand->getIndex(), MemOperand->getShift(), |
- MemOperand->getSegmentRegister()); |
+ typename Traits::X86OperandMem *NewMemOperand = |
+ Traits::X86OperandMem::create(Func, MemOperand->getType(), RegTemp, |
+ nullptr, MemOperand->getIndex(), |
+ MemOperand->getShift(), |
+ MemOperand->getSegmentRegister()); |
return NewMemOperand; |
} |
assert("Unsupported -randomize-pool-immediates option" && false); |