diff --git a/src/mapleall/maple_me/BUILD.gn b/src/mapleall/maple_me/BUILD.gn index 270c5df53e06ebbd3428c8b06700373ce9c9fff8..7d6abffa878f8943f6bb01a7e5907e17c7e4df9c 100755 --- a/src/mapleall/maple_me/BUILD.gn +++ b/src/mapleall/maple_me/BUILD.gn @@ -106,7 +106,8 @@ src_libmplme = [ "src/simplifyCFG.cpp", "src/seqvec.cpp", "src/me_autovec.cpp", - "src/me_safety_warning.cpp" + "src/me_safety_warning.cpp", + "src/me_reassoc.cpp" ] src_libmplmewpo = [ diff --git a/src/mapleall/maple_me/include/me_ir.h b/src/mapleall/maple_me/include/me_ir.h index 3bda5eff223de96da0085e8acd2176b1c40266ce..eca543ac68a75bc83ed05d8add6dbb5e469082f5 100644 --- a/src/mapleall/maple_me/include/me_ir.h +++ b/src/mapleall/maple_me/include/me_ir.h @@ -489,7 +489,7 @@ class MePhiNode { return defBB; } - ScalarMeExpr *GetLHS() { + ScalarMeExpr *GetLHS() const { return lhs; } @@ -948,6 +948,7 @@ class OpMeExpr : public MeExpr { FieldID fieldID = 0; // this is also used to store puIdx public: bool hasAddressValue = false; // used only when op is ADD or SUB + bool canApplyReassoc = false; // hint to apply reassociation to this tree }; class IvarMeExpr : public MeExpr { diff --git a/src/mapleall/maple_me/include/me_phase_manager.h b/src/mapleall/maple_me/include/me_phase_manager.h index 98c3a6662b7d63d758978609f1cd8eb07e2862e7..c655da751ecc6b5763aa35233e3a63430c3027bf 100644 --- a/src/mapleall/maple_me/include/me_phase_manager.h +++ b/src/mapleall/maple_me/include/me_phase_manager.h @@ -84,6 +84,7 @@ #include "me_autovec.h" #include "me_safety_warning.h" #include "me_sink.h" +#include "me_reassoc.h" namespace maple { using meFuncOptTy = MapleFunctionPhase; diff --git a/src/mapleall/maple_me/include/me_reassoc.h b/src/mapleall/maple_me/include/me_reassoc.h new file mode 100644 index 0000000000000000000000000000000000000000..a039349b15403da4dbbb732ed267cfea8b1f3e48 --- /dev/null +++ b/src/mapleall/maple_me/include/me_reassoc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#ifndef MAPLE_ME_INCLUDE_ME_REASSOC_H +#define MAPLE_ME_INCLUDE_ME_REASSOC_H + +#include "me_function.h" +#include "me_irmap.h" +#include "me_cfg.h" +#include "me_loop_analysis.h" + +namespace maple { +// for representing the reults of ReassociateAddSub() +class ReassociatedParts { + public: + ReassociatedParts(MeExpr *ivpart, MeExpr *nonivpart) : ivPart(ivpart), nonIVPart(nonivpart) {} + public: + MeExpr *ivPart = nullptr; // the expr part likely to vary during exec + MeExpr *nonIVPart = nullptr; // the expr part not likely to change during exec + bool ivPartNegated = false; + bool nonIVPartNegated = false; +}; + +class MeReassoc { + public: + explicit MeReassoc(MeFunction *f, IRMap *map) : func(f), irMap(map), mirModule(&map->GetMIRModule()), cfg(f->GetCfg()) {} + virtual ~MeReassoc() = default; + + void FindSelfIncDecs(MeStmt *stmt, std::unordered_set *selfIncDefs); + MeExpr *FormReassociatedExpr(ReassociatedParts reassoc); + ReassociatedParts ReassociateAddSub(MeExpr *x, std::unordered_set *selfIncDefs); + void ProcessLoop(LoopDesc *aloop); + MeExpr *ApplyReassocExpr(MeExpr *x, std::unordered_set *selfIncDefs, bool *changed); + std::string PhaseName() const { + return "reassoc"; + } + public: + MeFunction *func; + IRMap *irMap; + MIRModule *mirModule; + MeCFG *cfg; +}; + +MAPLE_FUNC_PHASE_DECLARE(MEReassoc, MeFunction) +} // namespace maple +#endif // MAPLE_ME_INCLUDE_ME_REASSOC_H diff --git a/src/mapleall/maple_me/src/irmap.cpp b/src/mapleall/maple_me/src/irmap.cpp index 859c43f598d033b1e71ba510b1ed74d9141ddfda..e1bc160dc9fca99a0adfbaaa06e212badd238f33 100644 --- a/src/mapleall/maple_me/src/irmap.cpp +++ b/src/mapleall/maple_me/src/irmap.cpp @@ -445,21 +445,22 @@ MeExpr *IRMap::SimplifyIvarWithIaddrofBase(IvarMeExpr *ivar, bool lhsIvar) { } MeExpr *IRMap::SimplifyIvar(IvarMeExpr *ivar, bool lhsIvar) { - auto *simplifiedIvar = SimplifyIvarWithConstOffset(ivar, lhsIvar); - if (simplifiedIvar != nullptr) { - return simplifiedIvar; + MeExpr *simplifiedIvar = SimplifyIvarWithConstOffset(ivar, lhsIvar); + if (simplifiedIvar == nullptr) { + simplifiedIvar = SimplifyIvarWithAddrofBase(ivar); + if (simplifiedIvar == nullptr) { + simplifiedIvar = SimplifyIvarWithIaddrofBase(ivar, lhsIvar); + } } - - simplifiedIvar = SimplifyIvarWithAddrofBase(ivar); - if (simplifiedIvar != nullptr) { + if (simplifiedIvar != nullptr && simplifiedIvar->GetMeOp() != kMeOpIvar) { return simplifiedIvar; } - - simplifiedIvar = SimplifyIvarWithIaddrofBase(ivar, lhsIvar); - if (simplifiedIvar != nullptr) { - return simplifiedIvar; + // set canApplyReassoc + IvarMeExpr *retIvar = simplifiedIvar != nullptr ? static_cast(simplifiedIvar) : ivar ; + if (retIvar->GetBase()->GetOp() == OP_add || retIvar->GetBase()->GetOp() == OP_sub) { + static_cast(retIvar->GetBase())->canApplyReassoc = true; } - return nullptr; + return simplifiedIvar; } IvarMeExpr *IRMap::BuildLHSIvar(MeExpr &baseAddr, IassignMeStmt &iassignMeStmt, FieldID fieldID) { diff --git a/src/mapleall/maple_me/src/me_phase_manager.cpp b/src/mapleall/maple_me/src/me_phase_manager.cpp index fb5b32e76ea30322b02247508ef729be8ba74518..3d9b824874418d8fca7d05704e5f15539b36b4f5 100644 --- a/src/mapleall/maple_me/src/me_phase_manager.cpp +++ b/src/mapleall/maple_me/src/me_phase_manager.cpp @@ -197,6 +197,7 @@ MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(MEProfGen, profileGen) MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(MEPlacementRC, placementrc) MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(MEDse, dse) MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(MEABCOpt, abcopt) +MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(MEReassoc, reassoc) MAPLE_TRANSFORM_PHASE_REGISTER(MEEmit, meemit) MAPLE_TRANSFORM_PHASE_REGISTER(EmitForIPA, emitforipa) } // namespace maple diff --git a/src/mapleall/maple_me/src/me_reassoc.cpp b/src/mapleall/maple_me/src/me_reassoc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d8465d8af5c16b733236bbadd16c4d9d0609a7b --- /dev/null +++ b/src/mapleall/maple_me/src/me_reassoc.cpp @@ -0,0 +1,384 @@ +/* + * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "me_phase_manager.h" +#include "me_reassoc.h" + +// This reassoc phase performs reassociation mainly for address expressions +// under iread/iassign. In the reassociation, the add/sub terms less likely to +// vary are separated from the parts likely to vary. This is done on a per loop// basis, and is applied only to expressions in innermost loops. For now, only +// IVs in loops are regarded as likely to vary. The goal is to result in more +// loop-invariant expressions after the reassociation. + +namespace maple { + +void MeReassoc::FindSelfIncDecs(MeStmt *stmt, std::unordered_set *selfIncDefs) { + if (stmt->GetOp() != OP_dassign && stmt->GetOp() != OP_regassign) { + return; + } + ScalarMeExpr *lhs = static_cast(stmt)->GetLHS(); + OriginalSt *ost = lhs->GetOst(); + if (!IsPrimitiveInteger(ost->GetType()->GetPrimType())) { + return; + } + MeExpr *rhs = static_cast(stmt)->GetRHS(); + if (rhs->GetOp() != OP_add && rhs->GetOp() != OP_sub) { + return; + } + MeExpr *opnd0 = rhs->GetOpnd(0); + if (opnd0->GetOp() != OP_dread && opnd0->GetOp() != OP_regread) { + return; + } + if (static_cast(opnd0)->GetOst() != ost) { + return; + } + MeExpr *opnd1 = rhs->GetOpnd(1); + if (opnd1->GetMeOp() != kMeOpConst) { + return; + } + selfIncDefs->insert(ost->GetIndex()); +} + +// Given an address expression, group the terms into ivPart containing the +// terms likely to vary frequently during execution, and nonIVPart containing +// the rest of the terms. Return the 2 parts in ReassociatedParts. +ReassociatedParts MeReassoc::ReassociateAddSub(MeExpr *x, std::unordered_set *selfIncDefs) { + switch (x->GetMeOp()) { + case kMeOpVar: + case kMeOpReg: { + ScalarMeExpr *scalar = static_cast(x); + if (selfIncDefs->count(scalar->GetOst()->GetIndex()) > 0) { + return ReassociatedParts(x, nullptr); + } + return ReassociatedParts(nullptr, x); + } + case kMeOpOp: { + OpMeExpr *opX = static_cast(x); + if (!IsPrimitiveInteger(opX->GetPrimType())) { + return ReassociatedParts(nullptr, x); + } + switch (opX->GetOp()) { + case OP_cvt: { + if (!IsPrimitiveInteger(opX->GetOpndType())) { + return ReassociatedParts(nullptr, x); + } + ReassociatedParts opndReassoc = ReassociateAddSub(opX->GetOpnd(0), selfIncDefs); + if (opndReassoc.ivPart != nullptr) { + opndReassoc.ivPart = irMap->CreateMeExprTypeCvt(opX->GetPrimType(), opX->GetOpndType(), *opndReassoc.ivPart); + } + if (opndReassoc.nonIVPart != nullptr) { + opndReassoc.nonIVPart = irMap->CreateMeExprTypeCvt(opX->GetPrimType(), opX->GetOpndType(), *opndReassoc.nonIVPart); + } + return opndReassoc; + } + case OP_neg: { + ReassociatedParts opndReassoc = ReassociateAddSub(opX->GetOpnd(0), selfIncDefs); + if (opndReassoc.ivPart != nullptr) { + opndReassoc.ivPartNegated = !opndReassoc.ivPartNegated; + } + if (opndReassoc.nonIVPart != nullptr) { + opndReassoc.nonIVPartNegated = !opndReassoc.nonIVPartNegated; + } + return opndReassoc; + } + case OP_mul: { + ReassociatedParts reassoc0 = ReassociateAddSub(opX->GetOpnd(0), selfIncDefs); + ReassociatedParts reassoc1 = ReassociateAddSub(opX->GetOpnd(1), selfIncDefs); + if (reassoc0.ivPart != nullptr || reassoc1.ivPart != nullptr) { + return ReassociatedParts(x, nullptr); + } + return ReassociatedParts(nullptr, x); + } + case OP_add: { + ReassociatedParts reassoc0 = ReassociateAddSub(opX->GetOpnd(0), selfIncDefs); + ReassociatedParts reassoc1 = ReassociateAddSub(opX->GetOpnd(1), selfIncDefs); + ReassociatedParts answer(nullptr, nullptr); + // set answer.ivPart + if (reassoc0.ivPart == nullptr) { + answer.ivPart = reassoc1.ivPart; + answer.ivPartNegated = reassoc1.ivPartNegated; + } else if (reassoc1.ivPart == nullptr) { + answer.ivPart = reassoc0.ivPart; + answer.ivPartNegated = reassoc0.ivPartNegated; + } else { + if (reassoc0.ivPartNegated == reassoc1.ivPartNegated) { + answer.ivPart = irMap->CreateMeExprBinary(OP_add, x->GetPrimType(), *reassoc0.ivPart, *reassoc1.ivPart); + answer.ivPartNegated = reassoc0.ivPartNegated; + } else if (!reassoc0.ivPartNegated) { + answer.ivPart = irMap->CreateMeExprBinary(OP_sub, x->GetPrimType(), *reassoc0.ivPart, *reassoc1.ivPart); + } else { + answer.ivPart = irMap->CreateMeExprBinary(OP_sub, x->GetPrimType(), *reassoc1.ivPart, *reassoc0.ivPart); + } + } + // set answer.nonIVPart + if (reassoc0.nonIVPart == nullptr) { + answer.nonIVPart = reassoc1.nonIVPart; + answer.nonIVPartNegated = reassoc1.nonIVPartNegated; + } else if (reassoc1.nonIVPart == nullptr) { + answer.nonIVPart = reassoc0.nonIVPart; + answer.nonIVPartNegated = reassoc0.nonIVPartNegated; + } else { + if (reassoc0.nonIVPartNegated == reassoc1.nonIVPartNegated) { + answer.nonIVPart = irMap->CreateMeExprBinary(OP_add, x->GetPrimType(), *reassoc0.nonIVPart, *reassoc1.nonIVPart); + answer.nonIVPartNegated = reassoc0.nonIVPartNegated; + } else if (!reassoc0.nonIVPartNegated) { + answer.nonIVPart = irMap->CreateMeExprBinary(OP_sub, x->GetPrimType(), *reassoc0.nonIVPart, *reassoc1.nonIVPart); + } else { + answer.nonIVPart = irMap->CreateMeExprBinary(OP_sub, x->GetPrimType(), *reassoc1.nonIVPart, *reassoc0.nonIVPart); + } + } + return answer; + } + case OP_sub: { + ReassociatedParts reassoc0 = ReassociateAddSub(opX->GetOpnd(0), selfIncDefs); + ReassociatedParts reassoc1 = ReassociateAddSub(opX->GetOpnd(1), selfIncDefs); + ReassociatedParts answer(nullptr, nullptr); + // set answer.ivPart + if (reassoc0.ivPart == nullptr) { + answer.ivPart = reassoc1.ivPart; + if (answer.ivPart != nullptr) { + answer.ivPartNegated = !reassoc1.ivPartNegated; + } + } else if (reassoc1.ivPart == nullptr) { + answer.ivPart = reassoc0.ivPart; + answer.ivPartNegated = reassoc0.ivPartNegated; + } else { + if (reassoc0.ivPartNegated == reassoc1.ivPartNegated) { + answer.ivPart = irMap->CreateMeExprBinary(OP_sub, x->GetPrimType(), *reassoc0.ivPart, *reassoc1.ivPart); + answer.ivPartNegated = reassoc0.ivPartNegated; + } else if (!reassoc0.ivPartNegated) { // reassoc1 must ivPartNegated + answer.ivPart = irMap->CreateMeExprBinary(OP_add, x->GetPrimType(), *reassoc0.ivPart, *reassoc1.ivPart); + } else { // reassoc0.ivPartNegated and !reassoc1.ivPartNegated + answer.ivPart = irMap->CreateMeExprBinary(OP_add, x->GetPrimType(), *reassoc0.ivPart, *reassoc1.ivPart); + answer.ivPartNegated = true; + } + } + // set answer.nonIVPart + if (reassoc0.nonIVPart == nullptr) { + answer.nonIVPart = reassoc1.nonIVPart; + if (answer.nonIVPart != nullptr) { + answer.nonIVPartNegated = !reassoc1.nonIVPartNegated; + } + } else if (reassoc1.nonIVPart == nullptr) { + answer.nonIVPart = reassoc0.nonIVPart; + answer.nonIVPartNegated = reassoc0.nonIVPartNegated; + } else { + if (reassoc0.nonIVPartNegated == reassoc1.nonIVPartNegated) { + answer.nonIVPart = irMap->CreateMeExprBinary(OP_sub, x->GetPrimType(), *reassoc0.nonIVPart, *reassoc1.nonIVPart); + answer.nonIVPartNegated = reassoc0.nonIVPartNegated; + } else if (!reassoc0.nonIVPartNegated) { // reassoc1 must nonIVPartNegated + answer.nonIVPart = irMap->CreateMeExprBinary(OP_add, x->GetPrimType(), *reassoc0.nonIVPart, *reassoc1.nonIVPart); + } else { // reassoc0.nonIVPartNegated and !reassoc1.nonIVPartNegated + answer.nonIVPart = irMap->CreateMeExprBinary(OP_add, x->GetPrimType(), *reassoc0.nonIVPart, *reassoc1.nonIVPart); + answer.nonIVPartNegated = true; + } + } + return answer; + } + default: return ReassociatedParts(nullptr, x); + } + } + default: return ReassociatedParts(nullptr, x); + } +} + +// form and return the final reassociated expression +MeExpr *MeReassoc::FormReassociatedExpr(ReassociatedParts reassoc) { + if (reassoc.ivPart != nullptr ^ reassoc.nonIVPart != nullptr) { + CHECK_FATAL(!reassoc.ivPartNegated && !reassoc.nonIVPartNegated, + "SimplifyIvar: top level reassociated address expression must not be negated"); + // no re-association + if (reassoc.ivPart != nullptr) { + if (!reassoc.ivPartNegated) { + return reassoc.ivPart; + } + return irMap->CreateMeExprUnary(OP_neg, reassoc.ivPart->GetPrimType(), *reassoc.ivPart); + } + if (!reassoc.nonIVPartNegated) { + return reassoc.nonIVPart; + } + return irMap->CreateMeExprUnary(OP_neg, reassoc.nonIVPart->GetPrimType(), *reassoc.nonIVPart); + } + CHECK_FATAL(!(reassoc.ivPart->HasAddressValue() && reassoc.nonIVPart->HasAddressValue()), + "SimplifyIvar: Conflicting settings of HasAddressValue() in reassociated operands"); + if (reassoc.ivPart->HasAddressValue()) { + CHECK_FATAL(!reassoc.ivPartNegated, "SimplifyIvar: cannot negate an address value"); + Opcode opToUse = reassoc.nonIVPartNegated ? OP_sub : OP_add; + OpMeExpr opMeExpr(kInvalidExprID, opToUse, PTY_u64, 2); + opMeExpr.SetOpnd(0, reassoc.ivPart); + opMeExpr.SetOpnd(1, reassoc.nonIVPart); + MeExpr *finalMeExpr = irMap->HashMeExpr(opMeExpr); + static_cast(finalMeExpr)->hasAddressValue = true; + return finalMeExpr; + } else if (reassoc.nonIVPart->HasAddressValue()) { + CHECK_FATAL(!reassoc.nonIVPartNegated, "SimplifyIvar: cannot negate an address value"); + Opcode opToUse = reassoc.ivPartNegated ? OP_sub : OP_add; + OpMeExpr opMeExpr(kInvalidExprID, opToUse, PTY_u64, 2); + opMeExpr.SetOpnd(0, reassoc.nonIVPart); + opMeExpr.SetOpnd(1, reassoc.ivPart); + MeExpr *finalMeExpr = irMap->HashMeExpr(opMeExpr); + static_cast(finalMeExpr)->hasAddressValue = true; + return finalMeExpr; + } else { // not sure which part has address value + CHECK_FATAL(!(reassoc.ivPartNegated && reassoc.nonIVPartNegated), "SimplifyIvar: negative address expression cannot be negated"); + if (reassoc.nonIVPartNegated) { + OpMeExpr opMeExpr(kInvalidExprID, OP_sub, PTY_u64, 2); + opMeExpr.SetOpnd(0, reassoc.ivPart); + opMeExpr.SetOpnd(1, reassoc.nonIVPart); + return irMap->HashMeExpr(opMeExpr); + } else { + OpMeExpr opMeExpr(kInvalidExprID, reassoc.ivPartNegated ? OP_sub : OP_add, PTY_u64, 2); + opMeExpr.SetOpnd(0, reassoc.nonIVPart); + opMeExpr.SetOpnd(1, reassoc.ivPart); + return irMap->HashMeExpr(opMeExpr); + } + } +} + +// Descend the expression tree to find reassociation candidates. "changed" is +// for indicating back to caller whether expression has been changed. Any +// change can be due to reassociation or due to rehash on the way back up. +MeExpr *MeReassoc::ApplyReassocExpr(MeExpr *x, std::unordered_set *selfIncDefs, bool *changed) { + switch (x->GetMeOp()) { + case kMeOpOp: { + bool isChanged = false; + OpMeExpr *opX = static_cast(x); + OpMeExpr newX(*opX, kInvalidExprID); + for (uint32 i = 0; i < x->GetNumOpnds(); ++i) { + newX.SetOpnd(i, ApplyReassocExpr(x->GetOpnd(i), selfIncDefs, &isChanged)); + } + if (isChanged) { + *changed = true; + x = irMap->HashMeExpr(newX); + } + if (!static_cast(x)->canApplyReassoc) { + return x; + } + // perform reassociation for this reassociation candidate + if (DEBUGFUNC_NEWPM(*func)) { + mirModule->GetOut() << "Reassociating "; + x->Dump(irMap,0); + mirModule->GetOut() << std::endl; + } + ReassociatedParts reassoc = ReassociateAddSub(x, selfIncDefs); + if (reassoc.ivPart != nullptr ^ reassoc.nonIVPart != nullptr) { + CHECK_FATAL(!reassoc.ivPartNegated && !reassoc.nonIVPartNegated, + "ApplyReassocExpr: top level reassociated address expression must not be negated"); + if (DEBUGFUNC_NEWPM(*func)) { + mirModule->GetOut() << "Unchanged" << std::endl; + } + return x; // not reassociated + } + MeExpr *reassociatedX = FormReassociatedExpr(reassoc); + if (reassociatedX != x) { + *changed = true; + if (DEBUGFUNC_NEWPM(*func)) { + mirModule->GetOut() << "changing it to "; + reassociatedX->Dump(irMap,0); + mirModule->GetOut() << std::endl; + } + } else { + if (DEBUGFUNC_NEWPM(*func)) { + mirModule->GetOut() << "Unchanged" << std::endl; + } + } + return reassociatedX; + } + case kMeOpNary: { + bool isChanged = false; + NaryMeExpr *naryX = static_cast(x); + NaryMeExpr newNary(&irMap->GetIRMapAlloc(), kInvalidExprID, *naryX); + for (uint32 i = 0; i < x->GetNumOpnds(); ++i) { + newNary.SetOpnd(i, ApplyReassocExpr(x->GetOpnd(i), selfIncDefs, &isChanged)); + } + if (isChanged) { + *changed = true; + return irMap->HashMeExpr(newNary); + } + return x; + } + case kMeOpIvar: { + bool isChanged = false; + IvarMeExpr *ivarX = static_cast(x); + IvarMeExpr newIvar(kInvalidExprID, *ivarX); + newIvar.SetBase(ApplyReassocExpr(ivarX->GetBase(), selfIncDefs, &isChanged)); + if (isChanged) { + *changed = true; + return irMap->HashMeExpr(newIvar); + } + return x; + } + default: return x; + } +} + +// apply reassociation to all the expressions in this innermost loop +void MeReassoc::ProcessLoop(LoopDesc *aloop) { + std::unordered_set selfIncDefSyms; // symbols with self increment/decrement + // first pass over loop BBs to set selfIncDefSyms + for (BBId bbId : aloop->loopBBs) { + BB *bb = cfg->GetBBFromID(bbId); + for (MeStmt &stmt : bb->GetMeStmts()) { + FindSelfIncDecs(&stmt, &selfIncDefSyms); + } + } + // final pass: reassociate only expressions marked canApplyReassoc + for (BBId bbId : aloop->loopBBs) { + BB *bb = cfg->GetBBFromID(bbId); + for (MeStmt &stmt : bb->GetMeStmts()) { + for (uint32 i = 0; i < stmt.NumMeStmtOpnds(); i++) { + bool changed = false; + MeExpr *newOpnd = ApplyReassocExpr(stmt.GetOpnd(i), &selfIncDefSyms, &changed); + if (changed) { + stmt.SetOpnd(i, newOpnd); + } + } + } + } +} + +bool MEReassoc::PhaseRun(maple::MeFunction &f) { + IRMap *irMap = GET_ANALYSIS(MEIRMapBuild, f); + ASSERT(irMap != nullptr, "irMap phase has problem"); + IdentifyLoops *identLoops = GET_ANALYSIS(MELoopAnalysis, f); + CHECK_NULL_FATAL(identLoops); + MeReassoc reassoc(&f, irMap); + + // go thru all the loops to find innermost loops; do in reverse order so + // innermost loops are visited first + uint32 lastNestDepth = 0; + for (int32 i = identLoops->GetMeLoops().size()-1; i >= 0; i--) { + LoopDesc *aloop = identLoops->GetMeLoops()[i]; + if (aloop->nestDepth < lastNestDepth) { // not innermost + lastNestDepth = aloop->nestDepth; + continue; + } + reassoc.ProcessLoop(aloop); + lastNestDepth = aloop->nestDepth; + } + + if (DEBUGFUNC_NEWPM(f)) { + LogInfo::MapleLogger() << "\n============== after REASSOC =============" << '\n'; + f.Dump(false); + } + + return true; +} + +void MEReassoc::GetAnalysisDependence(AnalysisDep &aDep) const { + aDep.AddRequired(); + aDep.AddRequired(); + aDep.SetPreservedAll(); +} +} // namespace maple diff --git a/src/mapleall/maple_phase/include/phases.def b/src/mapleall/maple_phase/include/phases.def index 9735c3e36b2fc2cda9976d975496df04314d662f..071c9b7af9aec19a9a4ce304171e9975dd9df00b 100644 --- a/src/mapleall/maple_phase/include/phases.def +++ b/src/mapleall/maple_phase/include/phases.def @@ -56,6 +56,7 @@ ADDMAPLEMEPHASE("hprop", MeOption::optLevel >= 2) ADDMAPLEMEPHASE("hdse", MeOption::optLevel >= 2) ADDMAPLEMEPHASE("may2dassign", JAVALANG && MeOption::optLevel >= 2) ADDMAPLEMEPHASE("condbasednpc", JAVALANG && MeOption::optLevel >= 2) +ADDMAPLEMEPHASE("reassoc", MeOption::optLevel >= 2) ADDMAPLEMEPHASE("epre", MeOption::optLevel >= 2) ADDMAPLEMEPHASE("stmtpre", JAVALANG && MeOption::optLevel >= 2) ADDMAPLEMEPHASE("analyzerc", MeOption::optLevel != 0 && JAVALANG && !MeOption::noRC && !MeOption::gcOnly)