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

Unified Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2313293002: [SubZero] Implement address optimization for MIPS (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 4 years, 3 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/IceTargetLoweringMIPS32.h ('k') | tests_lit/llvm2ice_tests/mips-address-mode-opt.ll » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceTargetLoweringMIPS32.cpp
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 7bdf723d3796b4da898c12e1f0a54380a7fbff89..60cf5a3877f39a027d7e51d2b53cbd8997ab528c 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -2310,7 +2310,237 @@ void TargetMIPS32::lowerLoad(const InstLoad *Instr) {
lowerAssign(Assign);
}
-void TargetMIPS32::doAddressOptLoad() { UnimplementedError(getFlags()); }
+namespace {
+void dumpAddressOpt(const Cfg *Func, const Variable *Base, int32_t Offset,
+ const Inst *Reason) {
+ if (!BuildDefs::dump())
+ return;
+ if (!Func->isVerbose(IceV_AddrOpt))
+ return;
+ OstreamLocker _(Func->getContext());
+ Ostream &Str = Func->getContext()->getStrDump();
+ Str << "Instruction: ";
+ Reason->dumpDecorated(Func);
+ Str << " results in Base=";
+ if (Base)
+ Base->dump(Func);
+ else
+ Str << "<null>";
+ Str << ", Offset=" << Offset << "\n";
+}
+
+bool matchAssign(const VariablesMetadata *VMetadata, const CfgNode *UseNode,
+ Variable **Var, int32_t *Offset, const Inst **Reason) {
+ // Var originates from Var=SrcVar ==> set Var:=SrcVar
+ if (*Var == nullptr)
+ return false;
+ const Inst *VarAssign = VMetadata->getSingleDefinition(*Var);
+ if (!VarAssign)
+ return false;
+ assert(!VMetadata->isMultiDef(*Var));
+ if (!llvm::isa<InstAssign>(VarAssign))
+ return false;
+
+ const CfgNode *DefNode = VMetadata->getSingleDefinitionNode(*Var);
+ const bool IsSingleBB = (DefNode->getIndex() == UseNode->getIndex());
Jim Stichnoth 2016/09/09 00:08:22 Why are you adding this single-block condition? I
jaydeep.patil 2016/09/13 06:42:25 Done.
+ Operand *SrcOp = VarAssign->getSrc(0);
+ bool Optimized = false;
+ if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
+ // Ensure SrcVar stays single-BB
+ if (!VMetadata->isMultiDef(SrcVar) || IsSingleBB == true) {
+ Optimized = true;
+ *Var = SrcVar;
+ } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
+ int32_t MoreOffset = Const->getValue();
+ int32_t NewOffset = MoreOffset + *Offset;
+ if (Utils::WouldOverflowAdd(*Offset, MoreOffset))
+ return false;
+ *Var = nullptr;
+ *Offset += NewOffset;
+ Optimized = true;
+ }
+ }
+
+ if (Optimized) {
+ *Reason = VarAssign;
+ }
+
+ return Optimized;
+}
+
+bool isAddOrSub(const Inst *Instr, InstArithmetic::OpKind *Kind) {
+ if (const auto *Arith = llvm::dyn_cast<InstArithmetic>(Instr)) {
+ switch (Arith->getOp()) {
+ default:
+ return false;
+ case InstArithmetic::Add:
+ case InstArithmetic::Sub:
+ *Kind = Arith->getOp();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable **Base,
+ int32_t *Offset, const Inst **Reason) {
+ // 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;
+ const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
+ if (BaseInst == nullptr) {
+ return false;
+ }
+ assert(!VMetadata->isMultiDef(*Base));
+
+ auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst);
+ if (ArithInst == nullptr)
+ return false;
+ InstArithmetic::OpKind Kind;
+ if (!isAddOrSub(ArithInst, &Kind))
+ return false;
+ bool IsAdd = Kind == InstArithmetic::Add;
+ Operand *Src0 = ArithInst->getSrc(0);
+ Operand *Src1 = ArithInst->getSrc(1);
+ auto *Var0 = llvm::dyn_cast<Variable>(Src0);
+ auto *Var1 = llvm::dyn_cast<Variable>(Src1);
+ auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0);
+ auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1);
+ Variable *NewBase = nullptr;
+ int32_t NewOffset = *Offset;
+
+ if (Var0 == nullptr && Const0 == nullptr) {
+ assert(llvm::isa<ConstantRelocatable>(Src0));
+ return false;
+ }
+
+ if (Var1 == nullptr && Const1 == nullptr) {
+ assert(llvm::isa<ConstantRelocatable>(Src1));
+ return false;
+ }
+
+ if (Var0 && Var1)
+ // TODO(jpp): merge base/index splitting into here.
+ return false;
+ if (!IsAdd && Var1)
+ return false;
+ if (Var0)
+ NewBase = Var0;
+ else if (Var1)
+ NewBase = Var1;
+ // Compute the updated constant offset.
+ if (Const0) {
+ int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue();
+ if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
+ return false;
+ NewOffset += MoreOffset;
+ }
+ if (Const1) {
+ int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue();
+ if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
+ return false;
+ NewOffset += MoreOffset;
+ }
+
+ // Update the computed address parameters once we are sure optimization
+ // is valid.
+ *Base = NewBase;
+ *Offset = NewOffset;
+ *Reason = BaseInst;
+ return true;
+}
+} // end of anonymous namespace
+
+OperandMIPS32Mem *TargetMIPS32::formAddressingMode(Type Ty, Cfg *Func,
+ const CfgNode *LdStNode,
+ const Inst *LdSt,
+ Operand *Base) {
+ assert(Base != nullptr);
+ int32_t OffsetImm = 0;
+
+ Func->resetCurrentNode();
+ if (Func->isVerbose(IceV_AddrOpt)) {
+ OstreamLocker _(Func->getContext());
+ Ostream &Str = Func->getContext()->getStrDump();
+ Str << "\nAddress mode formation:\t";
+ LdSt->dumpDecorated(Func);
+ }
+
+ if (isVectorType(Ty)) {
+ UnimplementedError(getFlags());
+ return nullptr;
+ }
+
+ auto *BaseVar = llvm::dyn_cast<Variable>(Base);
+ if (BaseVar == nullptr)
+ return nullptr;
+
+ const VariablesMetadata *VMetadata = Func->getVMetadata();
+ const Inst *Reason = nullptr;
+
+ do {
+ if (Reason != nullptr) {
+ dumpAddressOpt(Func, BaseVar, OffsetImm, Reason);
+ Reason = nullptr;
+ }
+
+ if (matchAssign(VMetadata, LdStNode, &BaseVar, &OffsetImm, &Reason)) {
+ continue;
+ }
+
+ if (matchOffsetBase(VMetadata, &BaseVar, &OffsetImm, &Reason)) {
+ continue;
+ }
+ } while (Reason);
+
+ if (BaseVar == nullptr) {
+ // We need base register rather than just OffsetImm. Move the OffsetImm to
+ // BaseVar and form 0(BaseVar) addressing.
+ const Type PointerType = getPointerType();
+ BaseVar = makeReg(PointerType);
+ Context.insert<InstAssign>(BaseVar, Ctx->getConstantInt32(OffsetImm));
+ OffsetImm = 0;
+ } else if (OffsetImm != 0) {
+ // If the OffsetImm is more than signed 16-bit value then add it in the
+ // BaseVar and form 0(BaseVar) addressing.
+ const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm;
+ const InstArithmetic::OpKind Op =
+ OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub;
+ constexpr bool ZeroExt = false;
+ if (!OperandMIPS32Mem::canHoldOffset(Ty, ZeroExt, OffsetImm)) {
+ const Type PointerType = getPointerType();
+ Variable *T = makeReg(PointerType);
+ Context.insert<InstArithmetic>(Op, T, BaseVar,
+ Ctx->getConstantInt32(PositiveOffset));
+ BaseVar = T;
+ OffsetImm = 0;
+ }
+ }
+
+ assert(BaseVar != nullptr);
+ assert(OffsetImm < 0 ? (-OffsetImm & 0x0000ffff) == -OffsetImm
+ : (OffsetImm & 0x0000ffff) == OffsetImm);
+
+ return OperandMIPS32Mem::create(
+ Func, Ty, BaseVar,
+ llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm)));
+}
+
+void TargetMIPS32::doAddressOptLoad() {
+ Inst *Instr = iteratorToInst(Context.getCur());
+ assert(llvm::isa<InstLoad>(Instr));
+ const CfgNode *LoadNode = Context.getNode();
+ Variable *Dest = Instr->getDest();
+ Operand *Addr = Instr->getSrc(0);
+ if (OperandMIPS32Mem *Mem =
+ formAddressingMode(Dest->getType(), Func, LoadNode, Instr, Addr)) {
+ Instr->setDeleted();
+ Context.insert<InstLoad>(Dest, Mem);
+ }
+}
void TargetMIPS32::randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) {
@@ -2380,7 +2610,18 @@ void TargetMIPS32::lowerStore(const InstStore *Instr) {
}
}
-void TargetMIPS32::doAddressOptStore() { UnimplementedError(getFlags()); }
+void TargetMIPS32::doAddressOptStore() {
+ Inst *Instr = iteratorToInst(Context.getCur());
+ assert(llvm::isa<InstStore>(Instr));
+ const CfgNode *StoreNode = Context.getNode();
+ Operand *Src = Instr->getSrc(0);
+ Operand *Addr = Instr->getSrc(1);
+ if (OperandMIPS32Mem *Mem =
+ formAddressingMode(Src->getType(), Func, StoreNode, Instr, Addr)) {
+ Instr->setDeleted();
+ Context.insert<InstStore>(Src, Mem);
+ }
+}
void TargetMIPS32::lowerSwitch(const InstSwitch *Instr) {
Operand *Src = Instr->getComparison();
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | tests_lit/llvm2ice_tests/mips-address-mode-opt.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698