Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Unified Diff: src/IceTargetLoweringX86BaseImpl.h

Issue 1605103002: Subzero. X86. Refactors Address Mode formation. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: make format Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceTargetLoweringX86Base.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceTargetLoweringX86BaseImpl.h
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index e70c757f9bb72abafb67984a4675f918f5b3c731..1d2ef6193a89877745ee1802f7f31d6cbad4f15c 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -308,7 +308,7 @@ void TargetX86Base<TraitsType>::initNodeForLowering(CfgNode *Node) {
template <typename TraitsType>
TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func)
- : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()) {
+ : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl) {
static_assert(
(Traits::InstructionSet::End - Traits::InstructionSet::Begin) ==
(TargetInstructionSet::X86InstructionSet_End -
@@ -338,12 +338,8 @@ void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) {
template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() {
TimerMarker T(TimerStack::TT_O2, Func);
- if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) {
- GotVar = Func->makeVariable(IceType_i32);
- }
-
- if (NeedSandboxing) {
- initSandbox();
+ if (SandboxingType != ST_None) {
+ initRebasePtr();
}
genTargetHelperCalls();
@@ -414,7 +410,9 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() {
Func->genCode();
if (Func->hasError())
return;
- initGotVarIfNeeded();
+ if (SandboxingType != ST_None) {
+ initSandbox();
+ }
Func->dump("After x86 codegen");
// Register allocation. This requires instruction renumbering and full
@@ -474,12 +472,8 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() {
template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() {
TimerMarker T(TimerStack::TT_Om1, Func);
- if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) {
- GotVar = Func->makeVariable(IceType_i32);
- }
-
- if (NeedSandboxing) {
- initSandbox();
+ if (SandboxingType != ST_None) {
+ initRebasePtr();
}
genTargetHelperCalls();
@@ -504,7 +498,9 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() {
Func->genCode();
if (Func->hasError())
return;
- initGotVarIfNeeded();
+ if (SandboxingType != ST_None) {
+ initSandbox();
+ }
Func->dump("After initial x8632 codegen");
regAlloc(RAK_InfOnly);
@@ -1329,23 +1325,6 @@ TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include,
}
template <typename TraitsType>
-void TargetX86Base<TraitsType>::initGotVarIfNeeded() {
- if (!Func->getContext()->getFlags().getUseNonsfi())
- return;
- if (Traits::Is64Bit) {
- // Probably no implementation is needed, but error to be safe for now.
- llvm::report_fatal_error(
- "Need to implement initGotVarIfNeeded() for 64-bit.");
- }
- // Insert the GotVar assignment as the very first lowered instruction. Later,
- // it will be moved into the right place - after the stack frame is set up but
- // before in-args are copied into registers.
- Context.init(Func->getEntryNode());
- Context.setInsertPoint(Context.getCur());
- Context.insert<typename Traits::Insts::GetIP>(GotVar);
-}
-
-template <typename TraitsType>
void TargetX86Base<TraitsType>::lowerAlloca(const InstAlloca *Inst) {
// Conservatively require the stack to be aligned. Some stack adjustment
// operations implemented below assume that the stack is aligned before the
@@ -4916,18 +4895,49 @@ void TargetX86Base<TraitsType>::lowerMemset(Operand *Dest, Operand *Val,
lowerCall(Call);
}
-inline bool isAdd(const Inst *Inst) {
- if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
- return (Arith->getOp() == InstArithmetic::Add);
+class AddressOptimizer {
+ AddressOptimizer() = delete;
+ AddressOptimizer(const AddressOptimizer &) = delete;
+ AddressOptimizer &operator=(const AddressOptimizer &) = delete;
+
+public:
+ explicit AddressOptimizer(const Cfg *Func)
+ : Func(Func), VMetadata(Func->getVMetadata()) {}
+
+ inline void dumpAddressOpt(const ConstantRelocatable *const Relocatable,
+ int32_t Offset, const Variable *Base,
+ const Variable *Index, uint16_t Shift,
+ const Inst *Reason) const;
+
+ inline const Inst *matchAssign(Variable **Var,
+ ConstantRelocatable **Relocatable,
+ int32_t *Offset);
+
+ inline const Inst *matchCombinedBaseIndex(Variable **Base, Variable **Index,
+ uint16_t *Shift);
+
+ inline const Inst *matchShiftedIndex(Variable **Index, uint16_t *Shift);
+
+ inline const Inst *matchOffsetBase(Variable **Base,
+ ConstantRelocatable **Relocatable,
+ int32_t *Offset);
+
+private:
+ const Cfg *const Func;
+ const VariablesMetadata *const VMetadata;
+
+ static bool isAdd(const Inst *Inst) {
+ if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
+ return (Arith->getOp() == InstArithmetic::Add);
+ }
+ return false;
}
- return false;
-}
+};
-inline void dumpAddressOpt(const Cfg *Func,
- const ConstantRelocatable *Relocatable,
- int32_t Offset, const Variable *Base,
- const Variable *Index, uint16_t Shift,
- const Inst *Reason) {
+void AddressOptimizer::dumpAddressOpt(
+ const ConstantRelocatable *const Relocatable, int32_t Offset,
+ const Variable *Base, const Variable *Index, uint16_t Shift,
+ const Inst *Reason) const {
if (!BuildDefs::dump())
return;
if (!Func->isVerbose(IceV_AddrOpt))
@@ -4950,14 +4960,14 @@ inline void dumpAddressOpt(const Cfg *Func,
<< ", Relocatable=" << Relocatable << "\n";
}
-inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *GotVar,
- Variable *&Var, ConstantRelocatable *&Relocatable,
- int32_t &Offset, const Inst *&Reason) {
+const Inst *AddressOptimizer::matchAssign(Variable **Var,
+ ConstantRelocatable **Relocatable,
+ int32_t *Offset) {
// Var originates from Var=SrcVar ==> set Var:=SrcVar
- if (Var == nullptr)
- return false;
- if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) {
- assert(!VMetadata->isMultiDef(Var));
+ if (*Var == nullptr)
+ return nullptr;
+ if (const Inst *VarAssign = VMetadata->getSingleDefinition(*Var)) {
+ assert(!VMetadata->isMultiDef(*Var));
if (llvm::isa<InstAssign>(VarAssign)) {
Operand *SrcOp = VarAssign->getSrc(0);
assert(SrcOp);
@@ -4965,88 +4975,86 @@ inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *GotVar,
if (!VMetadata->isMultiDef(SrcVar) &&
// TODO: ensure SrcVar stays single-BB
true) {
- Var = SrcVar;
- Reason = VarAssign;
- return true;
+ *Var = SrcVar;
+ return VarAssign;
}
} else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
int32_t MoreOffset = Const->getValue();
- if (Utils::WouldOverflowAdd(Offset, MoreOffset))
- return false;
- Var = nullptr;
+ if (Utils::WouldOverflowAdd(*Offset, MoreOffset))
+ return nullptr;
+ *Var = nullptr;
Offset += MoreOffset;
- Reason = VarAssign;
- return true;
+ return VarAssign;
} else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) {
- if (Relocatable == nullptr) {
- Var = GotVar;
- Relocatable = AddReloc;
- Reason = VarAssign;
- return true;
+ if (*Relocatable == nullptr) {
+ // It is always safe to fold a relocatable through assignment -- the
+ // assignment frees a slot in the address operand that can be used to
+ // hold the Sandbox Pointer -- if any.
+ *Var = nullptr;
+ *Relocatable = AddReloc;
+ return VarAssign;
}
}
}
}
- return false;
+ return nullptr;
}
-inline bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata,
- Variable *&Base, Variable *&Index,
- uint16_t &Shift, const Inst *&Reason) {
+const Inst *AddressOptimizer::matchCombinedBaseIndex(Variable **Base,
+ Variable **Index,
+ uint16_t *Shift) {
// Index==nullptr && Base is Base=Var1+Var2 ==>
// set Base=Var1, Index=Var2, Shift=0
- if (Base == nullptr)
- return false;
- if (Index != nullptr)
- return false;
- auto *BaseInst = VMetadata->getSingleDefinition(Base);
+ if (*Base == nullptr)
+ return nullptr;
+ if (*Index != nullptr)
+ return nullptr;
+ auto *BaseInst = VMetadata->getSingleDefinition(*Base);
if (BaseInst == nullptr)
- return false;
- assert(!VMetadata->isMultiDef(Base));
+ return nullptr;
+ assert(!VMetadata->isMultiDef(*Base));
if (BaseInst->getSrcSize() < 2)
- return false;
+ return nullptr;
if (auto *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) {
if (VMetadata->isMultiDef(Var1))
- return false;
+ return nullptr;
if (auto *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) {
if (VMetadata->isMultiDef(Var2))
- return false;
+ return nullptr;
if (isAdd(BaseInst) &&
// TODO: ensure Var1 and Var2 stay single-BB
true) {
- Base = Var1;
- Index = Var2;
- Shift = 0; // should already have been 0
- Reason = BaseInst;
- return true;
+ *Base = Var1;
+ *Index = Var2;
+ *Shift = 0; // should already have been 0
+ return BaseInst;
}
}
}
- return false;
+ return nullptr;
}
-inline bool matchShiftedIndex(const VariablesMetadata *VMetadata,
- Variable *&Index, uint16_t &Shift,
- const Inst *&Reason) {
+const Inst *AddressOptimizer::matchShiftedIndex(Variable **Index,
+ uint16_t *Shift) {
// Index is Index=Var*Const && log2(Const)+Shift<=3 ==>
// Index=Var, Shift+=log2(Const)
- if (Index == nullptr)
- return false;
- auto *IndexInst = VMetadata->getSingleDefinition(Index);
+ if (*Index == nullptr)
+ return nullptr;
+ auto *IndexInst = VMetadata->getSingleDefinition(*Index);
if (IndexInst == nullptr)
- return false;
- assert(!VMetadata->isMultiDef(Index));
+ return nullptr;
+ assert(!VMetadata->isMultiDef(*Index));
if (IndexInst->getSrcSize() < 2)
- return false;
+ return nullptr;
if (auto *ArithInst = llvm::dyn_cast<InstArithmetic>(IndexInst)) {
if (auto *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) {
if (auto *Const =
llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) {
if (VMetadata->isMultiDef(Var) || Const->getType() != IceType_i32)
- return false;
+ return nullptr;
switch (ArithInst->getOp()) {
default:
- return false;
+ return nullptr;
case InstArithmetic::Mul: {
uint32_t Mult = Const->getValue();
uint32_t LogMult;
@@ -5064,13 +5072,12 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata,
LogMult = 3;
break;
default:
- return false;
+ return nullptr;
}
- if (Shift + LogMult <= 3) {
- Index = Var;
- Shift += LogMult;
- Reason = IndexInst;
- return true;
+ if (*Shift + LogMult <= 3) {
+ *Index = Var;
+ *Shift += LogMult;
+ return IndexInst;
}
}
case InstArithmetic::Shl: {
@@ -5082,43 +5089,40 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata,
case 3:
break;
default:
- return false;
+ return nullptr;
}
- if (Shift + ShiftAmount <= 3) {
- Index = Var;
- Shift += ShiftAmount;
- Reason = IndexInst;
- return true;
+ if (*Shift + ShiftAmount <= 3) {
+ *Index = Var;
+ *Shift += ShiftAmount;
+ return IndexInst;
}
}
}
}
}
}
- return false;
+ return nullptr;
}
-inline bool matchOffsetBase(const VariablesMetadata *VMetadata,
- Variable *GotVar, Variable *&Base,
- Variable *&BaseOther,
- ConstantRelocatable *&Relocatable, int32_t &Offset,
- const Inst *&Reason) {
+const Inst *AddressOptimizer::matchOffsetBase(Variable **Base,
+ ConstantRelocatable **Relocatable,
+ int32_t *Offset) {
// Base is Base=Var+Const || Base is Base=Const+Var ==>
// set Base=Var, Offset+=Const
// Base is Base=Var-Const ==>
// set Base=Var, Offset-=Const
- if (Base == nullptr) {
- return false;
+ if (*Base == nullptr) {
+ return nullptr;
}
- const Inst *BaseInst = VMetadata->getSingleDefinition(Base);
+ const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
if (BaseInst == nullptr) {
- return false;
+ return nullptr;
}
- assert(!VMetadata->isMultiDef(Base));
+ assert(!VMetadata->isMultiDef(*Base));
if (auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst)) {
if (ArithInst->getOp() != InstArithmetic::Add &&
ArithInst->getOp() != InstArithmetic::Sub)
- return false;
+ return nullptr;
bool IsAdd = ArithInst->getOp() == InstArithmetic::Add;
Operand *Src0 = ArithInst->getSrc(0);
Operand *Src1 = ArithInst->getSrc(1);
@@ -5129,74 +5133,55 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata,
auto *Reloc0 = llvm::dyn_cast<ConstantRelocatable>(Src0);
auto *Reloc1 = llvm::dyn_cast<ConstantRelocatable>(Src1);
Variable *NewBase = nullptr;
- int32_t NewOffset = Offset;
- ConstantRelocatable *NewRelocatable = Relocatable;
+ int32_t NewOffset = *Offset;
+ ConstantRelocatable *NewRelocatable = *Relocatable;
if (Var0 && Var1)
// TODO(sehr): merge base/index splitting into here.
- return false;
+ return nullptr;
if (!IsAdd && Var1)
- return false;
+ return nullptr;
if (Var0)
NewBase = Var0;
else if (Var1)
NewBase = Var1;
// Don't know how to add/subtract two relocatables.
- if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1))
- return false;
+ if ((*Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1))
+ return nullptr;
// Don't know how to subtract a relocatable.
if (!IsAdd && Reloc1)
- return false;
+ return nullptr;
// Incorporate ConstantRelocatables.
if (Reloc0)
NewRelocatable = Reloc0;
else if (Reloc1)
NewRelocatable = Reloc1;
- if ((Reloc0 || Reloc1) && BaseOther && GotVar)
- return false;
// Compute the updated constant offset.
if (Const0) {
const int32_t MoreOffset =
IsAdd ? Const0->getValue() : -Const0->getValue();
if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
- return false;
+ return nullptr;
NewOffset += MoreOffset;
}
if (Const1) {
const int32_t MoreOffset =
IsAdd ? Const1->getValue() : -Const1->getValue();
if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
- return false;
+ return nullptr;
NewOffset += MoreOffset;
}
- // Update the computed address parameters once we are sure optimization
- // is valid.
- if ((Reloc0 || Reloc1) && GotVar) {
- assert(BaseOther == nullptr);
- BaseOther = GotVar;
- }
- Base = NewBase;
- Offset = NewOffset;
- Relocatable = NewRelocatable;
- Reason = BaseInst;
- return true;
+ *Base = NewBase;
+ *Offset = NewOffset;
+ *Relocatable = NewRelocatable;
+ return BaseInst;
}
- return false;
+ return nullptr;
}
-// Builds information for a canonical address expresion:
-// <Relocatable + Offset>(Base, Index, Shift)
-// On entry:
-// Relocatable == null,
-// Offset == 0,
-// Base is a Variable,
-// Index == nullptr,
-// Shift == 0
-inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar,
- bool ReserveSlot,
- ConstantRelocatable *&Relocatable,
- int32_t &Offset, Variable *&Base,
- Variable *&Index, uint16_t &Shift) {
- bool AddressWasOptimized = false;
+template <typename TypeTraits>
+typename TargetX86Base<TypeTraits>::X86OperandMem *
+TargetX86Base<TypeTraits>::computeAddressOpt(const Inst *Instr, Type MemType,
+ Operand *Addr) {
Func->resetCurrentNode();
if (Func->isVerbose(IceV_AddrOpt)) {
OstreamLocker L(Func->getContext());
@@ -5204,70 +5189,138 @@ inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar,
Str << "\nStarting computeAddressOpt for instruction:\n ";
Instr->dumpDecorated(Func);
}
- if (Base == nullptr)
- return AddressWasOptimized;
+
+ OptAddr NewAddr;
+ NewAddr.Base = llvm::dyn_cast<Variable>(Addr);
+ if (NewAddr.Base == nullptr)
+ return nullptr;
+
// If the Base has more than one use or is live across multiple blocks, then
// don't go further. Alternatively (?), never consider a transformation that
// would change a variable that is currently *not* live across basic block
// boundaries into one that *is*.
- if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/)
- return AddressWasOptimized;
+ if (Func->getVMetadata()->isMultiBlock(
+ NewAddr.Base) /* || Base->getUseCount() > 1*/)
+ return nullptr;
+ AddressOptimizer AddrOpt(Func);
const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck();
- const VariablesMetadata *VMetadata = Func->getVMetadata();
const Inst *Reason = nullptr;
+ bool AddressWasOptimized = false;
+ // The following unnamed struct identifies the address mode formation steps
+ // that could potentially create an invalid memory operand (i.e., no free
+ // slots for RebasePtr.) We add all those variables to this struct so that we
+ // can use memset() to reset all members to false.
+ struct {
+ bool AssignBase = false;
+ bool AssignIndex = false;
+ bool OffsetFromBase = false;
+ bool OffsetFromIndex = false;
+ bool CombinedBaseIndex = false;
+ } Skip;
+ // This points to the boolean in Skip that represents the last folding
+ // performed. This is used to disable a pattern match that generated an
+ // invalid address. Without this, the algorithm would never finish.
+ bool *SkipLastFolding = nullptr;
+ // NewAddrCheckpoint is used to rollback the address being formed in case an
+ // invalid address is formed.
+ OptAddr NewAddrCheckpoint;
+ Reason = Instr;
do {
- assert(!ReserveSlot || Base == nullptr || Index == nullptr);
+ if (SandboxingType != ST_None) {
+ // When sandboxing, we defer the sandboxing of NewAddr to the Concrete
+ // Target. If our optimization was overly aggressive, then we simply undo
+ // what the previous iteration did, and set the previous pattern's skip
+ // bit to true.
+ if (!legalizeOptAddrForSandbox(&NewAddr)) {
+ *SkipLastFolding = true;
+ SkipLastFolding = nullptr;
+ NewAddr = NewAddrCheckpoint;
+ Reason = nullptr;
+ }
+ }
+
if (Reason) {
- dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason);
+ AddrOpt.dumpAddressOpt(NewAddr.Relocatable, NewAddr.Offset, NewAddr.Base,
+ NewAddr.Index, NewAddr.Shift, Reason);
AddressWasOptimized = true;
Reason = nullptr;
+ SkipLastFolding = nullptr;
+ memset(&Skip, 0, sizeof(Skip));
}
+
+ NewAddrCheckpoint = NewAddr;
+
// Update Base and Index to follow through assignments to definitions.
- if (matchAssign(VMetadata, GotVar, Base, Relocatable, Offset, Reason)) {
+ if (!Skip.AssignBase &&
+ (Reason = AddrOpt.matchAssign(&NewAddr.Base, &NewAddr.Relocatable,
+ &NewAddr.Offset))) {
+ SkipLastFolding = &Skip.AssignBase;
// Assignments of Base from a Relocatable or ConstantInt32 can result
// in Base becoming nullptr. To avoid code duplication in this loop we
// prefer that Base be non-nullptr if possible.
- if ((Base == nullptr) && (Index != nullptr) && Shift == 0)
- std::swap(Base, Index);
+ if ((NewAddr.Base == nullptr) && (NewAddr.Index != nullptr) &&
+ NewAddr.Shift == 0) {
+ std::swap(NewAddr.Base, NewAddr.Index);
+ }
continue;
}
- if (matchAssign(VMetadata, GotVar, Index, Relocatable, Offset, Reason))
+ if (!Skip.AssignBase &&
+ (Reason = AddrOpt.matchAssign(&NewAddr.Index, &NewAddr.Relocatable,
+ &NewAddr.Offset))) {
+ SkipLastFolding = &Skip.AssignIndex;
continue;
+ }
if (!MockBounds) {
// Transition from:
// <Relocatable + Offset>(Base) to
// <Relocatable + Offset>(Base, Index)
- if (!ReserveSlot &&
- matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason))
+ if (!Skip.CombinedBaseIndex &&
+ (Reason = AddrOpt.matchCombinedBaseIndex(
+ &NewAddr.Base, &NewAddr.Index, &NewAddr.Shift))) {
+ SkipLastFolding = &Skip.CombinedBaseIndex;
continue;
+ }
+
// Recognize multiply/shift and update Shift amount.
// Index becomes Index=Var<<Const && Const+Shift<=3 ==>
// Index=Var, Shift+=Const
// Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==>
// Index=Var, Shift+=log2(Const)
- if (matchShiftedIndex(VMetadata, Index, Shift, Reason))
+ if ((Reason =
+ AddrOpt.matchShiftedIndex(&NewAddr.Index, &NewAddr.Shift))) {
continue;
+ }
+
// If Shift is zero, the choice of Base and Index was purely arbitrary.
// Recognize multiply/shift and set Shift amount.
// Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==>
// swap(Index,Base)
// Similar for Base=Const*Var and Base=Var<<Const
- if (Shift == 0 && matchShiftedIndex(VMetadata, Base, Shift, Reason)) {
- std::swap(Base, Index);
+ if (NewAddr.Shift == 0 &&
+ (Reason = AddrOpt.matchShiftedIndex(&NewAddr.Base, &NewAddr.Shift))) {
+ std::swap(NewAddr.Base, NewAddr.Index);
continue;
}
}
+
// Update Offset to reflect additions/subtractions with constants and
// relocatables.
// TODO: consider overflow issues with respect to Offset.
- if (matchOffsetBase(VMetadata, GotVar, Base, Index, Relocatable, Offset,
- Reason))
+ if (!Skip.OffsetFromBase &&
+ (Reason = AddrOpt.matchOffsetBase(&NewAddr.Base, &NewAddr.Relocatable,
+ &NewAddr.Offset))) {
+ SkipLastFolding = &Skip.OffsetFromBase;
continue;
- if (Shift == 0 && matchOffsetBase(VMetadata, GotVar, Index, Base,
- Relocatable, Offset, Reason))
+ }
+ if (NewAddr.Shift == 0 && !Skip.OffsetFromIndex &&
+ (Reason = AddrOpt.matchOffsetBase(&NewAddr.Index, &NewAddr.Relocatable,
+ &NewAddr.Offset))) {
+ SkipLastFolding = &Skip.OffsetFromIndex;
continue;
+ }
+
// TODO(sehr, stichnot): Handle updates of Index with Shift != 0.
// Index is Index=Var+Const ==>
// set Index=Var, Offset+=(Const<<Shift)
@@ -5277,13 +5330,40 @@ inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar,
// set Index=Var, Offset-=(Const<<Shift)
break;
} while (Reason);
- // Undo any addition of GotVar. It will be added back when the mem operand is
- // legalized.
- if (Base == GotVar)
- Base = nullptr;
- if (Index == GotVar)
- Index = nullptr;
- return AddressWasOptimized;
+
+ if (!AddressWasOptimized) {
+ return nullptr;
+ }
+
+ // Undo any addition of RebasePtr. It will be added back when the mem
+ // operand is sandboxed.
+ if (NewAddr.Base == RebasePtr) {
+ NewAddr.Base = nullptr;
+ }
+
+ if (NewAddr.Index == RebasePtr) {
+ NewAddr.Index = nullptr;
+ NewAddr.Shift = 0;
+ }
+
+ Constant *OffsetOp = nullptr;
+ if (NewAddr.Relocatable == nullptr) {
+ OffsetOp = Ctx->getConstantInt32(NewAddr.Offset);
+ } else {
+ OffsetOp =
+ Ctx->getConstantSym(NewAddr.Relocatable->getOffset() + NewAddr.Offset,
+ NewAddr.Relocatable->getName(),
+ NewAddr.Relocatable->getSuppressMangling());
+ }
+ // Vanilla ICE load instructions should not use the segment registers, and
+ // computeAddressOpt only works at the level of Variables and Constants, not
+ // other X86OperandMem, so there should be no mention of segment
+ // registers there either.
+ static constexpr auto SegmentReg =
+ X86OperandMem::SegmentRegisters::DefaultSegment;
+
+ return X86OperandMem::create(Func, MemType, NewAddr.Base, OffsetOp,
+ NewAddr.Index, NewAddr.Shift, SegmentReg);
}
/// Add a mock bounds check on the memory address before using it as a load or
@@ -5361,35 +5441,11 @@ void TargetX86Base<TraitsType>::lowerLoad(const InstLoad *Load) {
template <typename TraitsType>
void TargetX86Base<TraitsType>::doAddressOptLoad() {
Inst *Inst = Context.getCur();
- Variable *Dest = Inst->getDest();
Operand *Addr = Inst->getSrc(0);
- Variable *Index = nullptr;
- ConstantRelocatable *Relocatable = nullptr;
- uint16_t Shift = 0;
- int32_t Offset = 0;
- // Vanilla ICE load instructions should not use the segment registers, and
- // computeAddressOpt only works at the level of Variables and Constants, not
- // other X86OperandMem, so there should be no mention of segment
- // registers there either.
- constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment;
- auto *Base = llvm::dyn_cast<Variable>(Addr);
- const bool ReserveSlot = Traits::Is64Bit && NeedSandboxing;
- if (computeAddressOpt(Func, Inst, GotVar, ReserveSlot, Relocatable, Offset,
- Base, Index, Shift)) {
+ Variable *Dest = Inst->getDest();
+ if (auto *OptAddr = computeAddressOpt(Inst, Dest->getType(), Addr)) {
Inst->setDeleted();
- Constant *OffsetOp = nullptr;
- if (Relocatable == nullptr) {
- OffsetOp = Ctx->getConstantInt32(Offset);
- } else {
- OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
- Relocatable->getName(),
- Relocatable->getSuppressMangling());
- }
- // The new mem operand is created without IsRebased being set, because
- // computeAddressOpt() doesn't include GotVar in its final result.
- Addr = X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, Index,
- Shift, SegmentReg);
- Context.insert<InstLoad>(Dest, Addr);
+ Context.insert<InstLoad>(Dest, OptAddr);
}
}
@@ -5686,35 +5742,11 @@ void TargetX86Base<TraitsType>::lowerStore(const InstStore *Inst) {
template <typename TraitsType>
void TargetX86Base<TraitsType>::doAddressOptStore() {
auto *Inst = llvm::cast<InstStore>(Context.getCur());
- Operand *Data = Inst->getData();
Operand *Addr = Inst->getAddr();
- Variable *Index = nullptr;
- ConstantRelocatable *Relocatable = nullptr;
- uint16_t Shift = 0;
- int32_t Offset = 0;
- auto *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 X86OperandMem, so there should be no mention of segment
- // registers there either.
- constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment;
- const bool ReserveSlot = Traits::Is64Bit && NeedSandboxing;
- if (computeAddressOpt(Func, Inst, GotVar, ReserveSlot, Relocatable, Offset,
- Base, Index, Shift)) {
+ Operand *Data = Inst->getData();
+ if (auto *OptAddr = computeAddressOpt(Inst, Data->getType(), Addr)) {
Inst->setDeleted();
- Constant *OffsetOp = nullptr;
- if (Relocatable == nullptr) {
- OffsetOp = Ctx->getConstantInt32(Offset);
- } else {
- OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
- Relocatable->getName(),
- Relocatable->getSuppressMangling());
- }
- // The new mem operand is created without IsRebased being set, because
- // computeAddressOpt() doesn't include GotVar in its final result.
- Addr = X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, Index,
- Shift, SegmentReg);
- auto *NewStore = Context.insert<InstStore>(Data, Addr);
+ auto *NewStore = Context.insert<InstStore>(Data, OptAddr);
if (Inst->getDest())
NewStore->setRmwBeacon(Inst->getRmwBeacon());
}
@@ -5774,9 +5806,8 @@ void TargetX86Base<TraitsType>::lowerCaseCluster(const CaseCluster &Case,
constexpr RelocOffsetT RelocOffset = 0;
constexpr bool SuppressMangling = true;
- const bool IsRebased = Ctx->getFlags().getUseNonsfi();
IceString MangledName = Ctx->mangleName(Func->getFunctionName());
- Variable *Base = IsRebased ? legalizeToReg(GotVar) : nullptr;
+ constexpr Variable *NoBase = nullptr;
Constant *Offset = Ctx->getConstantSym(
RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()),
SuppressMangling);
@@ -5785,11 +5816,10 @@ void TargetX86Base<TraitsType>::lowerCaseCluster(const CaseCluster &Case,
Variable *Target = nullptr;
if (Traits::Is64Bit && NeedSandboxing) {
- assert(Base == nullptr);
assert(Index != nullptr && Index->getType() == IceType_i32);
}
- auto *TargetInMemory = X86OperandMem::create(
- Func, PointerType, Base, Offset, Index, Shift, Segment, IsRebased);
+ auto *TargetInMemory = X86OperandMem::create(Func, PointerType, NoBase,
+ Offset, Index, Shift, Segment);
_mov(Target, TargetInMemory);
lowerIndirectJump(Target);
@@ -6116,12 +6146,12 @@ void TargetX86Base<TraitsType>::lowerOther(const Inst *Instr) {
/// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve
/// integrity of liveness analysis. Undef values are also turned into zeroes,
/// since loOperand() and hiOperand() don't expect Undef input. Also, in
-/// Non-SFI mode, add a FakeUse(GotVar) for every pooled constant operand.
+/// Non-SFI mode, add a FakeUse(RebasePtr) for every pooled constant operand.
template <typename TraitsType> void TargetX86Base<TraitsType>::prelowerPhis() {
if (Ctx->getFlags().getUseNonsfi()) {
- assert(GotVar);
+ assert(RebasePtr);
CfgNode *Node = Context.getNode();
- uint32_t GotVarUseCount = 0;
+ uint32_t RebasePtrUseCount = 0;
for (Inst &I : Node->getPhis()) {
auto *Phi = llvm::dyn_cast<InstPhi>(&I);
if (Phi->isDeleted())
@@ -6132,12 +6162,12 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::prelowerPhis() {
// kinds of pooling.
if (llvm::isa<ConstantRelocatable>(Src) ||
llvm::isa<ConstantFloat>(Src) || llvm::isa<ConstantDouble>(Src)) {
- ++GotVarUseCount;
+ ++RebasePtrUseCount;
}
}
}
- if (GotVarUseCount) {
- Node->getInsts().push_front(InstFakeUse::create(Func, GotVar));
+ if (RebasePtrUseCount) {
+ Node->getInsts().push_front(InstFakeUse::create(Func, RebasePtr));
}
}
if (Traits::Is64Bit) {
@@ -6685,29 +6715,13 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
RegIndex = llvm::cast<Variable>(
legalize(Index, Legal_Reg | Legal_Rematerializable));
}
- // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we
- // replace either Base or Index with a legalized GotVar. At emission time,
- // the ConstantRelocatable will be emitted with the @GOTOFF relocation.
- bool IsRebased = false;
- if (UseNonsfi && !Mem->getIsRebased() && Offset &&
- llvm::isa<ConstantRelocatable>(Offset)) {
- assert(!(Allowed & Legal_AddrAbs));
- IsRebased = true;
- if (RegBase == nullptr) {
- RegBase = legalizeToReg(GotVar);
- } else if (RegIndex == nullptr) {
- RegIndex = legalizeToReg(GotVar);
- } else {
- llvm::report_fatal_error(
- "Either Base or Index must be unused in Non-SFI mode");
- }
- }
+
if (Base != RegBase || Index != RegIndex) {
Mem = X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, Shift,
- Mem->getSegmentRegister(), IsRebased);
+ Mem->getSegmentRegister());
}
- // For all Memory Operands, we do randomization/pooling here
+ // For all Memory Operands, we do randomization/pooling here.
From = randomizeOrPoolImmediate(Mem);
if (!(Allowed & Legal_Mem)) {
@@ -6746,24 +6760,21 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
}
}
- // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not
- // specified, and UseNonsfi is indicated, we need to add GotVar.
if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) {
+ // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not
+ // specified, and UseNonsfi is indicated, we need to add RebasePtr.
if (UseNonsfi && !(Allowed & Legal_AddrAbs)) {
assert(Ty == IceType_i32);
- Variable *RegBase = legalizeToReg(GotVar);
Variable *NewVar = makeReg(Ty, RegNum);
- static constexpr bool IsRebased = true;
- auto *Mem =
- Traits::X86OperandMem::create(Func, Ty, RegBase, CR, IsRebased);
- _lea(NewVar, Mem);
+ auto *Mem = Traits::X86OperandMem::create(Func, Ty, nullptr, CR);
+ // LEAs are not automatically sandboxed, thus we explicitly invoke
+ // _sandbox_mem_reference.
+ _lea(NewVar, _sandbox_mem_reference(Mem));
From = NewVar;
}
- }
-
- // Convert a scalar floating point constant into an explicit memory
- // operand.
- if (isScalarFloatingType(Ty)) {
+ } else if (isScalarFloatingType(Ty)) {
+ // Convert a scalar floating point constant into an explicit memory
+ // operand.
if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) {
if (Utils::isPositiveZero(ConstFloat->getValue()))
return makeZeroedRegister(Ty, RegNum);
@@ -6771,19 +6782,19 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
if (Utils::isPositiveZero(ConstDouble->getValue()))
return makeZeroedRegister(Ty, RegNum);
}
- Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
+
std::string Buffer;
llvm::raw_string_ostream StrBuf(Buffer);
llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx);
llvm::cast<Constant>(From)->setShouldBePooled(true);
Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
- const bool IsRebased = Base != nullptr;
- auto *Mem = X86OperandMem::create(Func, Ty, Base, Offset, IsRebased);
+ auto *Mem = X86OperandMem::create(Func, Ty, nullptr, Offset);
From = Mem;
}
+
bool NeedsReg = false;
if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty))
- // Immediate specifically not allowed
+ // Immediate specifically not allowed.
NeedsReg = true;
if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty))
// On x86, FP constants are lowered to mem operands.
@@ -6816,8 +6827,7 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
_lea(NewVar, Mem);
From = NewVar;
} else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
- (RegNum != Variable::NoRegister && RegNum != Var->getRegNum()) ||
- MustRematerialize) {
+ (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
From = copyToReg(From, RegNum);
}
return From;
@@ -7097,11 +7107,9 @@ TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate,
constexpr bool SuppressMangling = true;
Constant *Symbol =
Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling);
- const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
- Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
- const bool IsRebased = Base != nullptr;
- X86OperandMem *MemOperand = X86OperandMem::create(
- Func, Immediate->getType(), Base, Symbol, IsRebased);
+ constexpr Variable *NoBase = nullptr;
+ X86OperandMem *MemOperand =
+ X86OperandMem::create(Func, Immediate->getType(), NoBase, Symbol);
_mov(Reg, MemOperand);
return Reg;
}
@@ -7207,11 +7215,9 @@ TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand,
constexpr bool SuppressMangling = true;
Constant *Symbol =
Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling);
- const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
- Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
- const bool IsRebased = Base != nullptr;
+ constexpr Variable *NoBase = nullptr;
X86OperandMem *SymbolOperand = X86OperandMem::create(
- Func, MemOperand->getOffset()->getType(), Base, Symbol, IsRebased);
+ Func, MemOperand->getOffset()->getType(), NoBase, 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
« no previous file with comments | « src/IceTargetLoweringX86Base.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698