Index: src/IceTargetLoweringX86BaseImpl.h |
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h |
index 9ebeb621c52db35878674cfb7710489e868792cb..e66dc5704133f08545584afdcc8691ff15bc0c77 100644 |
--- a/src/IceTargetLoweringX86BaseImpl.h |
+++ b/src/IceTargetLoweringX86BaseImpl.h |
@@ -22,20 +22,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; |
@@ -84,8 +80,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 }; |
@@ -162,12 +157,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)) { |
@@ -225,10 +219,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(); |
} |
} |
@@ -282,24 +276,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; |
@@ -347,19 +335,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; |
@@ -375,19 +362,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); |
@@ -396,9 +383,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(); |
@@ -415,11 +402,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. |
jvoung (off chromium)
2015/07/07 00:00:18
extra space between "work" and "needed"
John
2015/07/07 15:12:18
Done.
|
Func->doBranchOpt(); |
Func->dump("After branch optimization"); |
@@ -467,8 +453,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; |
@@ -495,11 +480,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() && |
@@ -564,8 +552,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); |
@@ -592,8 +580,10 @@ 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( |
- Func, ArithSrcOther, Store->getAddr(), Beacon, Arith->getOp()); |
+ typename Traits::Insts::FakeRMW *RMW = |
+ Traits::Insts::FakeRMW::create(Func, ArithSrcOther, |
jvoung (off chromium)
2015/07/07 00:00:18
I wonder if we should allow "auto" for results of
John
2015/07/07 15:12:18
Done.
|
+ Store->getAddr(), Beacon, |
+ Arith->getOp()); |
Node->getInsts().insert(I3, RMW); |
} |
} |
@@ -720,22 +710,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; |
@@ -759,30 +740,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> |
@@ -883,7 +841,7 @@ 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); |
@@ -891,7 +849,7 @@ void TargetX86Base<Machine>::finishArgumentLowering(Variable *Arg, |
_mov(Arg, Mem); |
} |
// This argument-copying instruction uses an explicit |
- // OperandX8632Mem operand instead of a Variable, so its |
+ // typename Traits::X86OperandMem operand instead of a Variable, so its |
// fill-from-stack operation has to be tracked separately for |
// statistics. |
Ctx->statsUpdateFills(); |
@@ -964,7 +922,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); |
@@ -1068,7 +1027,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; |
@@ -1105,7 +1065,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) |
@@ -1215,8 +1175,9 @@ 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 (typename Traits::X86OperandMem *Mem = |
jvoung (off chromium)
2015/07/07 00:00:18
could declare as "auto *Mem" for this, since it's
John
2015/07/07 15:12:18
Done.
|
+ llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { |
+ typename Traits::X86OperandMem *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 |
@@ -1244,7 +1205,8 @@ 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 (typename Traits::X86OperandMem *Mem = |
jvoung (off chromium)
2015/07/07 00:00:18
auto
John
2015/07/07 15:12:18
Done.
|
+ llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { |
Constant *Offset = Mem->getOffset(); |
if (Offset == nullptr) { |
Offset = Ctx->getConstantInt32(4); |
@@ -1258,7 +1220,7 @@ Operand *TargetX86Base<Machine>::hiOperand(Operand *Operand) { |
Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), |
SymOffset->getSuppressMangling()); |
} |
- OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
+ typename Traits::X86OperandMem *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 |
@@ -1274,32 +1236,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> |
@@ -1422,17 +1359,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) { |
@@ -1600,7 +1540,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); |
@@ -1635,7 +1576,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); |
@@ -1670,7 +1612,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); |
@@ -1708,7 +1651,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: |
@@ -2207,7 +2150,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()); |
} |
} |
@@ -2304,7 +2248,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(); |
@@ -2531,7 +2475,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; |
} |
@@ -2540,10 +2484,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 |
@@ -2566,7 +2510,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)); |
@@ -2605,7 +2549,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)); |
@@ -2617,10 +2561,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. |
@@ -2644,7 +2588,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; |
@@ -2685,7 +2629,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; |
@@ -2727,8 +2671,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); |
@@ -2747,14 +2691,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); |
@@ -2773,7 +2720,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); |
@@ -2786,17 +2733,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 |
@@ -2896,7 +2844,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); |
} |
@@ -2942,7 +2890,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) { |
@@ -3017,7 +2965,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); |
@@ -3090,13 +3039,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); |
@@ -3105,7 +3054,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); |
@@ -3113,7 +3062,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); |
@@ -3122,7 +3071,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); |
@@ -3130,7 +3079,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); |
@@ -3155,8 +3104,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) |
@@ -3292,7 +3243,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); |
@@ -3382,7 +3333,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); |
@@ -3432,7 +3384,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; |
@@ -3534,7 +3487,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); |
@@ -3589,9 +3542,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); |
@@ -3654,7 +3607,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)); |
@@ -3665,7 +3619,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); |
@@ -3767,7 +3722,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); |
@@ -3782,7 +3738,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); |
@@ -3820,7 +3777,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); |
@@ -3868,12 +3826,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); |
@@ -3915,10 +3874,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). |
@@ -4259,11 +4219,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 typename Traits::X86OperandMem |
jvoung (off chromium)
2015/07/07 00:00:18
Could omit the "typename" within a comment? I supp
John
2015/07/07 15:12:18
Yes, it makes sense. It did not occur to me to
/\
|
+ // operand. Note that the address mode optimization already creates an |
+ // typename 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); |
@@ -4278,19 +4238,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 |
- // registers there either. |
- const OperandX8632Mem::SegmentRegisters SegmentReg = |
- OperandX8632Mem::DefaultSegment; |
+ // Vanilla ICE load instructions should not use the segment registers, and |
+ // computeAddressOpt only works at the level of Variables and Constants, not |
+ // other typename Traits::X86OperandMem, so there should be no mention of |
jvoung (off chromium)
2015/07/07 00:00:18
similar, in a few places other than this, if you a
John
2015/07/07 15:12:18
Done.
John
2015/07/07 15:12:18
Done.
|
+ // segment registers there either. |
+ 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)); |
} |
} |
@@ -4437,7 +4397,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); |
@@ -4452,7 +4413,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. |
@@ -4487,15 +4448,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 { |
@@ -4514,16 +4478,17 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptStore() { |
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 |
+ // not other typename Traits::X86OperandMem, so there should be no mention of |
+ // segment |
jvoung (off chromium)
2015/07/07 00:00:18
could fit rest of comment on this line too
John
2015/07/07 15:12:18
Done.
|
// 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()); |
@@ -4551,7 +4516,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); |
@@ -4638,7 +4604,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 |
@@ -4650,12 +4617,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. |
@@ -4714,7 +4683,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); |
@@ -4990,7 +4960,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. |
@@ -5004,7 +4974,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 |
@@ -5036,7 +5006,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(); |
@@ -5050,9 +5020,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 |
@@ -5102,7 +5072,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)) |
@@ -5161,12 +5131,14 @@ 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); |
+typename TargetX86Base<Machine>::Traits::X86OperandMem * |
+TargetX86Base<Machine>::formMemoryOperand(Operand *Opnd, Type Ty, |
+ bool DoLegalize) { |
+ typename Traits::X86OperandMem *Mem = |
jvoung (off chromium)
2015/07/07 00:00:18
auto for dyn_cast ?
|
+ llvm::dyn_cast<typename Traits::X86OperandMem>(Opnd); |
// It may be the case that address mode optimization already creates |
- // an OperandX8632Mem, so in that case it wouldn't need another level |
+ // an typename Traits::X86OperandMem, so in that case it wouldn't need another |
+ // level |
jvoung (off chromium)
2015/07/07 00:00:18
could fit rest of comment here
John
2015/07/07 15:12:18
Done.
|
// of transformation. |
if (!Mem) { |
Variable *Base = llvm::dyn_cast<Variable>(Opnd); |
@@ -5187,11 +5159,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)); |
} |
@@ -5217,68 +5189,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> |
@@ -5349,8 +5261,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. |
@@ -5383,8 +5295,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; |
} |
@@ -5395,9 +5308,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) { |
@@ -5431,8 +5344,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 |
@@ -5446,9 +5360,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 |
@@ -5483,23 +5399,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); |