From 6f43c72c88c8a53089c214281e1ed51fa9660288 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Thu, 10 Jun 2021 00:00:14 -0700 Subject: [PATCH 1/5] Implement Linear Function Test Replacement (still off by default) When strength reduction is on, turn on via --lftr --- src/mapleall/maple_me/BUILD.gn | 1 + src/mapleall/maple_me/include/me_option.h | 1 + src/mapleall/maple_me/include/occur.h | 4 +- src/mapleall/maple_me/include/ssa_epre.h | 3 + src/mapleall/maple_me/include/ssa_pre.h | 4 +- src/mapleall/maple_me/src/irmap_build.cpp | 10 ++ src/mapleall/maple_me/src/me_option.cpp | 19 ++- src/mapleall/maple_me/src/me_ssa_epre.cpp | 3 + src/mapleall/maple_me/src/occur.cpp | 5 + src/mapleall/maple_me/src/ssa_epre.cpp | 6 +- .../maple_me/src/ssa_epre_for_lftr.cpp | 136 ++++++++++++++++++ src/mapleall/maple_me/src/ssa_epre_for_sr.cpp | 2 +- src/mapleall/maple_me/src/ssa_pre.cpp | 82 ++++++++++- 13 files changed, 268 insertions(+), 8 deletions(-) create mode 100644 src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp diff --git a/src/mapleall/maple_me/BUILD.gn b/src/mapleall/maple_me/BUILD.gn index 3593617942..635041c636 100755 --- a/src/mapleall/maple_me/BUILD.gn +++ b/src/mapleall/maple_me/BUILD.gn @@ -73,6 +73,7 @@ src_libmplme = [ "src/ssa_epre.cpp", "src/ssa_pre.cpp", "src/ssa_epre_for_sr.cpp", + "src/ssa_epre_for_lftr.cpp", "src/occur.cpp", "src/me_inequality_graph.cpp", "src/me_abco.cpp", diff --git a/src/mapleall/maple_me/include/me_option.h b/src/mapleall/maple_me/include/me_option.h index 61f8eaf7d0..5d06d3a0db 100644 --- a/src/mapleall/maple_me/include/me_option.h +++ b/src/mapleall/maple_me/include/me_option.h @@ -123,6 +123,7 @@ class MeOption : public MapleDriverOptionBase { static bool subsumRC; static bool performFSAA; static bool strengthReduction; + static bool doLFTR; static std::string inlineFuncList; static bool meVerify; #if MIR_JAVA diff --git a/src/mapleall/maple_me/include/occur.h b/src/mapleall/maple_me/include/occur.h index c4da174ec6..d8ce0e3c22 100644 --- a/src/mapleall/maple_me/include/occur.h +++ b/src/mapleall/maple_me/include/occur.h @@ -30,9 +30,11 @@ enum OccType { kOccGcmalloc, kOccUse, // for use appearances when candidate is dassign kOccMembar, // for representing occurrence of memory barriers (use MeRealOcc) + kOccCompare, // for linear function test replacement (uses MeRealOcc) }; class MePhiOcc; + class MeOccur { public: MeOccur(OccType ty, int cId, MeOccur *df) : occTy(ty), classID(cId), mirBB(nullptr), def(df) {} @@ -203,7 +205,7 @@ class MeRealOcc : public MeOccur { MeExpr *meExpr; // the expr it's corresponding to MeExpr *savedExpr; // the reall occ saved to, must be a VarMeExpr/RegMeExpr int seq; // meStmt sequence number in the bb - size_t position; // the position in the workCand->GetRealOccs() vector + size_t position; // the position in the workCand->realOccs vector bool isReload; bool isSave; bool isLHS; diff --git a/src/mapleall/maple_me/include/ssa_epre.h b/src/mapleall/maple_me/include/ssa_epre.h index 5db9da0a2a..191877614d 100644 --- a/src/mapleall/maple_me/include/ssa_epre.h +++ b/src/mapleall/maple_me/include/ssa_epre.h @@ -72,6 +72,9 @@ class SSAEPre : public SSAPre { bool epreIncludeRef; bool enableLHSIvar; + // here starts mtehods related to linear function test replacement + OpMeExpr *FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) override; + void CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *comapre, bool isRebuilt) override; }; } // namespace maple #endif // MAPLE_ME_INCLUDE_SSAEPRE_H diff --git a/src/mapleall/maple_me/include/ssa_pre.h b/src/mapleall/maple_me/include/ssa_pre.h index 2d6b0dd90b..4d75aa2b3e 100644 --- a/src/mapleall/maple_me/include/ssa_pre.h +++ b/src/mapleall/maple_me/include/ssa_pre.h @@ -140,6 +140,7 @@ class SSAPre { void GenerateSaveInsertedOcc(MeInsertedOcc &insertedOcc); void GenerateSavePhiOcc(MePhiOcc &phiOcc); void UpdateInsertedPhiOccOpnd(); + virtual OpMeExpr *FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { return nullptr; } virtual void CodeMotion(); // step 5 Finalize methods virtual void Finalize1(); @@ -187,6 +188,7 @@ class SSAPre { MeOccur *exitOcc = ssaPreMemPool->New(kOccExit, 0, bb, nullptr); exitOccs.push_back(exitOcc); } + virtual void CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *comapre, bool isRebuilt) {} bool CheckIfAnyLocalOpnd(const MeExpr &meExpr) const; MeRealOcc *CreateRealOcc(MeStmt &meStmt, int32 seqStmt, MeExpr &meExpr, bool isRebuilt, bool isLHS = false); @@ -200,7 +202,6 @@ class SSAPre { virtual bool IsLoopHeadBB(BBId) const { return false; } - virtual VarMeExpr *ResolveAllInjuringDefs(VarMeExpr *varx) const { return varx; } virtual RegMeExpr *ResolveAllInjuringDefs(RegMeExpr *regx) const { return regx; } virtual MeExpr *ResolveAllInjuringDefs(MeExpr *x) const { return x; } virtual void SubstituteOpnd(MeExpr *x, MeExpr *oldopnd, MeExpr *newopnd) { @@ -271,6 +272,7 @@ class SSAPre { bool addedNewLocalRefVars = false; public: bool strengthReduction = false; + bool doLFTR = false; }; } // namespace maple #endif // MAPLE_ME_INCLUDE_SSAPRE_H diff --git a/src/mapleall/maple_me/src/irmap_build.cpp b/src/mapleall/maple_me/src/irmap_build.cpp index 15cb82e7fd..63691fbe47 100644 --- a/src/mapleall/maple_me/src/irmap_build.cpp +++ b/src/mapleall/maple_me/src/irmap_build.cpp @@ -408,6 +408,16 @@ MeExpr *IRMapBuild::BuildExpr(BaseNode &mirNode, bool atParm, bool noProp) { } } + if (op == OP_mul) { + OpMeExpr *opMeExpr = static_cast(meExpr); + if (opMeExpr->GetOpnd(0)->GetMeOp() == kMeOpConst) { + // canonicalize constant operand to be operand 1 + MeExpr *savedOpnd = opMeExpr->GetOpnd(0); + opMeExpr->SetOpnd(0, opMeExpr->GetOpnd(1)); + opMeExpr->SetOpnd(1, savedOpnd); + } + } + MeExpr *retMeExpr = irMap->HashMeExpr(*meExpr); delete meExpr; diff --git a/src/mapleall/maple_me/src/me_option.cpp b/src/mapleall/maple_me/src/me_option.cpp index 01e8cd4030..4de8364b55 100644 --- a/src/mapleall/maple_me/src/me_option.cpp +++ b/src/mapleall/maple_me/src/me_option.cpp @@ -97,6 +97,7 @@ bool MeOption::placementRC = false; bool MeOption::subsumRC = false; bool MeOption::performFSAA = true; bool MeOption::strengthReduction = false; +bool MeOption::doLFTR = false; std::string MeOption::inlineFuncList = ""; bool MeOption::meVerify = false; #if MIR_JAVA @@ -186,6 +187,7 @@ enum OptionIndex { kSubsumRC, kPerformFSAA, kStrengthReduction, + kLFTR, kRegReadAtReturn, kProPatphi, kNoProPatphi, @@ -778,8 +780,18 @@ const Descriptor kUsage[] = { "strengthreduction", kBuildTypeExperimental, kArgCheckPolicyBool, - " --strengthreduction \tPerform flow sensitive alias analysis\n" - " --no-strengthreduction \tDisable flow sensitive alias analysis\n", + " --strengthreduction \tPerform strength reduction\n" + " --no-strengthreduction \tDisable strength reduction\n", + "me", + {} }, + { kLFTR, + kEnable, + "", + "lftr", + kBuildTypeExperimental, + kArgCheckPolicyBool, + " --lftr \tPerform linear function test replacement\n" + " --no-lftr \tDisable linear function test replacement\n", "me", {} }, { kCheckCastOpt, @@ -1378,6 +1390,9 @@ bool MeOption::SolveOptions(const std::vector &opts, bool i case kStrengthReduction: strengthReduction = (opt.Type() == kEnable); break; + case kLFTR: + doLFTR = (opt.Type() == kEnable); + break; case kMeInlineHint: inlineFuncList = opt.Args(); break; diff --git a/src/mapleall/maple_me/src/me_ssa_epre.cpp b/src/mapleall/maple_me/src/me_ssa_epre.cpp index 0335d5a007..1961754754 100644 --- a/src/mapleall/maple_me/src/me_ssa_epre.cpp +++ b/src/mapleall/maple_me/src/me_ssa_epre.cpp @@ -92,6 +92,9 @@ AnalysisResult *MeDoSSAEPre::Run(MeFunction *func, MeFuncResultMgr *m, ModuleRes ssaPre.SetSpillAtCatch(MeOption::spillAtCatch); if (MeOption::strengthReduction && !func->GetMIRModule().IsJavaModule()) { ssaPre.strengthReduction = true; + if (MeOption::doLFTR) { + ssaPre.doLFTR = true; + } } if (func->GetHints() & kPlacementRCed) { ssaPre.SetPlacementRC(true); diff --git a/src/mapleall/maple_me/src/occur.cpp b/src/mapleall/maple_me/src/occur.cpp index 2671631946..7ec6eb3e2b 100644 --- a/src/mapleall/maple_me/src/occur.cpp +++ b/src/mapleall/maple_me/src/occur.cpp @@ -49,6 +49,7 @@ bool MeOccur::IsDominate(Dominance &dom, MeOccur &occ) { switch (occTy) { case kOccReal: { switch (occ.GetOccType()) { + case kOccCompare: case kOccReal: { if (mirBB == occ.GetBB()) { auto *thisRealOcc = static_cast(this); @@ -162,6 +163,10 @@ void MeRealOcc::Dump(const IRMap &irMap) const { } else { mod->GetOut() << " classID " << GetClassID(); } + } else if (GetOccType() == kOccCompare) { + mod->GetOut() << "CompOcc "; + meExpr->Dump(&irMap); + mod->GetOut() << " at bb" << GetBB()->GetBBId() << " seq " << seq << " classID " << GetClassID(); } else { mod->GetOut() << "MembarOcc "; mod->GetOut() << " at bb" << GetBB()->GetBBId() << " seq " << seq; diff --git a/src/mapleall/maple_me/src/ssa_epre.cpp b/src/mapleall/maple_me/src/ssa_epre.cpp index 401745161a..351acd82c5 100644 --- a/src/mapleall/maple_me/src/ssa_epre.cpp +++ b/src/mapleall/maple_me/src/ssa_epre.cpp @@ -296,6 +296,9 @@ void SSAEPre::ComputeVarAndDfPhis() { CHECK_FATAL(!dom->IsBBVecEmpty(), "size to be allocated is 0"); for (auto it = realOccList.begin(); it != realOccList.end(); ++it) { MeRealOcc *realOcc = *it; + if (realOcc->GetOccType() == kOccCompare) { + continue; + } BB *defBB = realOcc->GetBB(); GetIterDomFrontier(defBB, &dfPhiDfns); MeExpr *meExpr = realOcc->GetMeExpr(); @@ -337,7 +340,8 @@ void SSAEPre::BuildWorkListExpr(MeStmt &meStmt, int32 seqStmt, MeExpr &meExpr, b if (meExpr.GetPrimType() == PTY_agg) { break; } - if (isRootExpr && kOpcodeInfo.IsCompare(meOpExpr->GetOp())) { + if (isRootExpr && kOpcodeInfo.IsCompare(meOpExpr->GetOp()) && doLFTR) { + CreateCompOcc(&meStmt, seqStmt, meOpExpr, isRebuild); break; } if (!epreIncludeRef && meOpExpr->GetPrimType() == PTY_ref) { diff --git a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp new file mode 100644 index 0000000000..7f42ac9d58 --- /dev/null +++ b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) [2021] Huawei Technologies Co., Ltd. All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. + * You can use this software according to the terms and conditions of the MulanPSL - 2.0. + * You may obtain a copy of MulanPSL - 2.0 at: + * + * https://opensource.org/licenses/MulanPSL-2.0 + * + * 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 MulanPSL - 2.0 for more details. + */ + +#include "ssa_epre.h" + +namespace maple { + +// one side of compare is an operand x in workCand->GetTheMeExpr() with current +// occurrence occExpr; replace that side of the compare by regorvar; replace the +// other side of compare by the expression formed by substituting x in occExpr +// by that side of the compare; if the new compare side cannot be folded to a +// leaf, enter into EPRE work list +// EXAMPLE 1: INPUT: workCand is (i + 4), compare is (i < n) +// RETURN: regorvar < (n + 4) +// (n + 4) added to EPRE work list +// EXAMPLE 2: INPUT: workCand is (i * 3), compare is (n == i) +// RETURN: n * 3 == regorvar +// (n * 3) added to EPRE work list +// EXAMPLE 3: INPUT: workCand is (i + &A), compare is (i < 100) +// RETURN: regorvar < 100 + &A +// 100 + &A is folded to an OP_addrof node +OpMeExpr *SSAEPre::FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { + MeExpr *compare = compOcc->GetMeExpr(); + // determine the ith operand of workCand that is the jth operand of compare + OpMeExpr *x = static_cast(workCand->GetTheMeExpr()); + size_t i; + size_t j = 0; + for (i = 0; i < x->GetNumOpnds(); i++) { + ScalarMeExpr *iv = dynamic_cast(x->GetOpnd(i)); + if (iv == nullptr) { + continue; + } + ScalarMeExpr *compareOpnd = dynamic_cast(compare->GetOpnd(0)); + if (compareOpnd != nullptr && iv->GetOst() == compareOpnd->GetOst()) { + j = 0; + break; + } + compareOpnd = dynamic_cast(compare->GetOpnd(1)); + if (compareOpnd != nullptr && iv->GetOst() == compareOpnd->GetOst()) { + j = 1; + break; + } + } + ASSERT(j == 0 || j == 1, "FormLFTRCompare: cannot correspond comp occ to workcand"); + // handle the ops corresponding to OpMeExpr::StrengthReducible() + OpMeExpr newSide(-1, x->GetOp(), x->GetPrimType(), x->GetNumOpnds()); + newSide.SetOpnd(i, compare->GetOpnd(1-j)); + switch (x->GetOp()) { + case OP_cvt: { + newSide.SetOpndType(x->GetOpndType()); + break; + } + case OP_mul: + case OP_add: { + newSide.SetOpnd(1-i, x->GetOpnd(1-i)); + break; + } + default: { + ASSERT(false, "FormLFTRCompare: unrecognized strength reduction operation"); + return nullptr; + } + } + // check if newSide can be folded + MeExpr *simplifyExpr = irMap->SimplifyOpMeExpr(&newSide); + MeExpr *hashedSide = nullptr; + if (simplifyExpr != nullptr) { + hashedSide = simplifyExpr; + } else { + hashedSide = irMap->HashMeExpr(newSide); + BuildWorkListExpr(*compOcc->GetMeStmt(), compOcc->GetSequence(), *hashedSide, false, nullptr, true); + } + OpMeExpr newcompare(-1, compare->GetOp(), compare->GetPrimType(), 2); + newcompare.SetOpndType(static_cast(compare)->GetOpndType()); + newcompare.SetOpnd(j, regorvar); + newcompare.SetOpnd(1-j, hashedSide); + return static_cast(irMap->HashMeExpr(newcompare)); +} + +void SSAEPre::CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *compare, bool isRebuilt) { + if (compare->GetOpnd(0)->GetNumOpnds() > 0 || + compare->GetOpnd(1)->GetNumOpnds() > 0) { + // both sides of compare must be leaf + return; + } + ScalarMeExpr *compareLHS = dynamic_cast(compare->GetOpnd(0)); + ScalarMeExpr *compareRHS = dynamic_cast(compare->GetOpnd(1)); + if (compareLHS == nullptr && compareRHS == nullptr) { + return; + } + // search for worklist candidates set isSRCand such that one of its operands + // is either compareLHS or compareRHS, and create MeRealOcc for each of them + for (PreWorkCand *wkCand : workList) { + if (!wkCand->isSRCand) { + continue; + } + MeExpr *x = wkCand->GetTheMeExpr(); + bool isRelevant = false; + for (size_t i = 0; i < x->GetNumOpnds(); i++) { + ScalarMeExpr *iv = dynamic_cast(x->GetOpnd(i)); + if (iv == nullptr) { + continue; + } + if ((compareLHS && iv->GetOst() == compareLHS->GetOst()) || + (compareRHS && iv->GetOst() == compareRHS->GetOst())) { + isRelevant = true; + } else { // disqualify as compocc if x has a scalar which is not an iv + isRelevant = false; + break; + } + } + if (isRelevant) { + MeRealOcc *compOcc = ssaPreMemPool->New(meStmt, seqStmt, compare); + compOcc->SetOccType(kOccCompare); + if (isRebuilt) { + // insert to realOccs in dt_preorder of the BBs and seq in each BB + wkCand->AddRealOccSorted(*dom, *compOcc, GetPUIdx()); + } else { + wkCand->AddRealOccAsLast(*compOcc, GetPUIdx()); + } + } + } +} + +} // namespace maple diff --git a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp index e7d0665bbe..2d8ec7aa7e 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp @@ -258,7 +258,7 @@ MeExpr* SSAEPre::SRRepairInjuries(MeOccur *useocc, std::set *needRepairInjuringDefs, std::set *repairedInjuringDefs) { MeExpr *useexpr = nullptr; - if (useocc->GetOccType() == kOccReal) { + if (useocc->GetOccType() == kOccReal || useocc->GetOccType() == kOccCompare) { MeRealOcc *realocc = static_cast(useocc); useexpr = realocc->GetMeExpr(); } else { diff --git a/src/mapleall/maple_me/src/ssa_pre.cpp b/src/mapleall/maple_me/src/ssa_pre.cpp index 855af1e8ce..c26f957105 100644 --- a/src/mapleall/maple_me/src/ssa_pre.cpp +++ b/src/mapleall/maple_me/src/ssa_pre.cpp @@ -290,6 +290,18 @@ void SSAPre::CodeMotion() { GenerateSavePhiOcc(*phiOcc); break; } + case kOccCompare: { + MeRealOcc *compOcc = static_cast(occ); + if (!compOcc->IsReload()) { + break; + } + MeExpr *regorvar = SRRepairInjuries(compOcc, &needRepairInjuringDefs, &repairedInjuringDefs); + OpMeExpr *newCompare = FormLFTRCompare(compOcc, regorvar); + // replace compOcc->mestmt's occ with newCompare + irMap->ReplaceMeExprStmt(*compOcc->GetMeStmt(), *compOcc->GetMeExpr(), *newCompare); + CreateCompOcc(compOcc->GetMeStmt(), compOcc->GetSequence(), newCompare, true); + break; + } case kOccExit: break; case kOccMembar: @@ -318,7 +330,7 @@ void SSAPre::Finalize1() { std::vector availDefVec(classCount, nullptr); // traversal in preoder DT for (MeOccur *occ : allOccs) { - size_t classX = static_cast(static_cast(occ->GetClassID())); + int classX = occ->GetClassID(); switch (occ->GetOccType()) { case kOccPhiocc: { auto *phiOcc = static_cast(occ); @@ -340,6 +352,18 @@ void SSAPre::Finalize1() { } break; } + case kOccCompare: { + if (classX == 0) { + break; + } + MeOccur *availDef = availDefVec[classX]; + CHECK_FATAL(availDef != nullptr, "compare occ with class ID has no available def"); + CHECK_FATAL(availDef->IsDominate(*dom, *occ), "compare occ's available def not dominating it"); + MeRealOcc *compOcc = static_cast(occ); + compOcc->SetIsReload(true); + compOcc->SetDef(availDefVec[classX]); + break; + } case kOccPhiopnd: { // we assume one phiOpnd has only one phiOcc use because critical edge split the blocks auto *phiOpnd = static_cast(occ); @@ -773,6 +797,9 @@ void SSAPre::Rename1() { } else { for (auto varIt = varVec.begin(); varIt != varVec.end(); ++varIt) { MeExpr *varMeExpr = *varIt; + if (workCand->isSRCand) { + varMeExpr = ResolveAllInjuringDefs(varMeExpr); + } if (!DefVarDominateOcc(varMeExpr, *topOccur)) { isAllDom = false; } @@ -799,6 +826,56 @@ void SSAPre::Rename1() { } break; } + case kOccCompare: { + if (occStack.empty()) { + break; + } + MeOccur *topOccur = occStack.top(); + if (topOccur->GetOccType() == kOccUse || topOccur->GetOccType() == kOccMembar) { + break; + } + MeRealOcc *realOcc = static_cast(occ); + // set scalarOpnd to be the operand that is scalar + ScalarMeExpr *scalarOpnd = dynamic_cast(workCand->GetTheMeExpr()->GetOpnd(0)); + uint32 scalarOpndNo = 0; + if (scalarOpnd == nullptr) { + scalarOpnd = static_cast(workCand->GetTheMeExpr()->GetOpnd(1)); + scalarOpndNo = 1; + } + ScalarMeExpr *compareOpnd = nullptr; + MeExpr *opnd0 = realOcc->GetMeExpr()->GetOpnd(0); + MeExpr *opnd1 = realOcc->GetMeExpr()->GetOpnd(1); + if ((opnd0->GetMeOp() == kMeOpVar || opnd0->GetMeOp() == kMeOpReg) && + (static_cast(opnd0)->GetOst() == scalarOpnd->GetOst())) { + compareOpnd = static_cast(opnd0); + } else if ((opnd1->GetMeOp() == kMeOpVar || opnd1->GetMeOp() == kMeOpReg) && + (static_cast(opnd1)->GetOst() == scalarOpnd->GetOst())) { + compareOpnd = static_cast(opnd1); + } + CHECK_FATAL(compareOpnd != nullptr, "Rename1: compOcc does not correspond to realOcc"); + ScalarMeExpr *resolvedCompareOpnd = ResolveAllInjuringDefs(compareOpnd); + if (topOccur->GetOccType() == kOccReal) { + MeRealOcc *realTopOccur = static_cast(topOccur); + ScalarMeExpr *topOccurOpnd = static_cast(realTopOccur->GetMeExpr()->GetOpnd(scalarOpndNo)); + if (compareOpnd == topOccurOpnd || resolvedCompareOpnd == topOccurOpnd) { + realOcc->SetClassID(realTopOccur->GetClassID()); + if (realTopOccur->GetDef() != nullptr) { + realOcc->SetDef(realTopOccur->GetDef()); + } else { + realOcc->SetDef(realTopOccur); + } + } + break; + } + // top of stack is a PHI occurrence + ASSERT(topOccur->GetOccType() == kOccPhiocc, "invalid kOccPhiocc"); + if (DefVarDominateOcc(compareOpnd, *topOccur) || + (resolvedCompareOpnd && DefVarDominateOcc(resolvedCompareOpnd, *topOccur))) { + realOcc->SetClassID(topOccur->GetClassID()); + realOcc->SetDef(topOccur); + } + break; + } case kOccPhiocc: { // assign new class occ->SetClassID(classCount++); @@ -940,7 +1017,7 @@ void SSAPre::Rename2() { bool hasSameVersion = true; for (size_t ii = 0; ii < varVecX.size(); ii++) { MeExpr *resolvedY = ResolveAllInjuringDefs(varVecY[ii]); - if (varVecX[ii] != resolvedY) { + if (varVecX[ii] != resolvedY && varVecX[ii] != varVecY[ii]) { hasSameVersion = false; } } @@ -1104,6 +1181,7 @@ void SSAPre::CreateSortedOccs() { switch (pickedOcc->GetOccType()) { case kOccReal: case kOccMembar: + case kOccCompare: ++realOccIt; if (realOccIt != workCand->GetRealOccs().end()) { nextRealOcc = *realOccIt; -- Gitee From 2a5cba68813531bce6e61eefa7376c2df8a71b33 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Thu, 10 Jun 2021 00:00:14 -0700 Subject: [PATCH 2/5] Implement Linear Function Test Replacement (still off by default) When strength reduction is on, turn on via --lftr --- src/mapleall/maple_me/BUILD.gn | 1 + src/mapleall/maple_me/include/me_option.h | 1 + src/mapleall/maple_me/include/occur.h | 4 +- src/mapleall/maple_me/include/ssa_epre.h | 3 + src/mapleall/maple_me/include/ssa_pre.h | 4 +- src/mapleall/maple_me/src/irmap_build.cpp | 10 ++ src/mapleall/maple_me/src/me_option.cpp | 19 ++- src/mapleall/maple_me/src/me_ssa_epre.cpp | 3 + src/mapleall/maple_me/src/occur.cpp | 5 + src/mapleall/maple_me/src/ssa_epre.cpp | 6 +- .../maple_me/src/ssa_epre_for_lftr.cpp | 136 ++++++++++++++++++ src/mapleall/maple_me/src/ssa_epre_for_sr.cpp | 2 +- src/mapleall/maple_me/src/ssa_pre.cpp | 82 ++++++++++- 13 files changed, 268 insertions(+), 8 deletions(-) create mode 100644 src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp diff --git a/src/mapleall/maple_me/BUILD.gn b/src/mapleall/maple_me/BUILD.gn index 3593617942..635041c636 100755 --- a/src/mapleall/maple_me/BUILD.gn +++ b/src/mapleall/maple_me/BUILD.gn @@ -73,6 +73,7 @@ src_libmplme = [ "src/ssa_epre.cpp", "src/ssa_pre.cpp", "src/ssa_epre_for_sr.cpp", + "src/ssa_epre_for_lftr.cpp", "src/occur.cpp", "src/me_inequality_graph.cpp", "src/me_abco.cpp", diff --git a/src/mapleall/maple_me/include/me_option.h b/src/mapleall/maple_me/include/me_option.h index 61f8eaf7d0..5d06d3a0db 100644 --- a/src/mapleall/maple_me/include/me_option.h +++ b/src/mapleall/maple_me/include/me_option.h @@ -123,6 +123,7 @@ class MeOption : public MapleDriverOptionBase { static bool subsumRC; static bool performFSAA; static bool strengthReduction; + static bool doLFTR; static std::string inlineFuncList; static bool meVerify; #if MIR_JAVA diff --git a/src/mapleall/maple_me/include/occur.h b/src/mapleall/maple_me/include/occur.h index c4da174ec6..d8ce0e3c22 100644 --- a/src/mapleall/maple_me/include/occur.h +++ b/src/mapleall/maple_me/include/occur.h @@ -30,9 +30,11 @@ enum OccType { kOccGcmalloc, kOccUse, // for use appearances when candidate is dassign kOccMembar, // for representing occurrence of memory barriers (use MeRealOcc) + kOccCompare, // for linear function test replacement (uses MeRealOcc) }; class MePhiOcc; + class MeOccur { public: MeOccur(OccType ty, int cId, MeOccur *df) : occTy(ty), classID(cId), mirBB(nullptr), def(df) {} @@ -203,7 +205,7 @@ class MeRealOcc : public MeOccur { MeExpr *meExpr; // the expr it's corresponding to MeExpr *savedExpr; // the reall occ saved to, must be a VarMeExpr/RegMeExpr int seq; // meStmt sequence number in the bb - size_t position; // the position in the workCand->GetRealOccs() vector + size_t position; // the position in the workCand->realOccs vector bool isReload; bool isSave; bool isLHS; diff --git a/src/mapleall/maple_me/include/ssa_epre.h b/src/mapleall/maple_me/include/ssa_epre.h index 5db9da0a2a..191877614d 100644 --- a/src/mapleall/maple_me/include/ssa_epre.h +++ b/src/mapleall/maple_me/include/ssa_epre.h @@ -72,6 +72,9 @@ class SSAEPre : public SSAPre { bool epreIncludeRef; bool enableLHSIvar; + // here starts mtehods related to linear function test replacement + OpMeExpr *FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) override; + void CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *comapre, bool isRebuilt) override; }; } // namespace maple #endif // MAPLE_ME_INCLUDE_SSAEPRE_H diff --git a/src/mapleall/maple_me/include/ssa_pre.h b/src/mapleall/maple_me/include/ssa_pre.h index 2d6b0dd90b..4d75aa2b3e 100644 --- a/src/mapleall/maple_me/include/ssa_pre.h +++ b/src/mapleall/maple_me/include/ssa_pre.h @@ -140,6 +140,7 @@ class SSAPre { void GenerateSaveInsertedOcc(MeInsertedOcc &insertedOcc); void GenerateSavePhiOcc(MePhiOcc &phiOcc); void UpdateInsertedPhiOccOpnd(); + virtual OpMeExpr *FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { return nullptr; } virtual void CodeMotion(); // step 5 Finalize methods virtual void Finalize1(); @@ -187,6 +188,7 @@ class SSAPre { MeOccur *exitOcc = ssaPreMemPool->New(kOccExit, 0, bb, nullptr); exitOccs.push_back(exitOcc); } + virtual void CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *comapre, bool isRebuilt) {} bool CheckIfAnyLocalOpnd(const MeExpr &meExpr) const; MeRealOcc *CreateRealOcc(MeStmt &meStmt, int32 seqStmt, MeExpr &meExpr, bool isRebuilt, bool isLHS = false); @@ -200,7 +202,6 @@ class SSAPre { virtual bool IsLoopHeadBB(BBId) const { return false; } - virtual VarMeExpr *ResolveAllInjuringDefs(VarMeExpr *varx) const { return varx; } virtual RegMeExpr *ResolveAllInjuringDefs(RegMeExpr *regx) const { return regx; } virtual MeExpr *ResolveAllInjuringDefs(MeExpr *x) const { return x; } virtual void SubstituteOpnd(MeExpr *x, MeExpr *oldopnd, MeExpr *newopnd) { @@ -271,6 +272,7 @@ class SSAPre { bool addedNewLocalRefVars = false; public: bool strengthReduction = false; + bool doLFTR = false; }; } // namespace maple #endif // MAPLE_ME_INCLUDE_SSAPRE_H diff --git a/src/mapleall/maple_me/src/irmap_build.cpp b/src/mapleall/maple_me/src/irmap_build.cpp index 15cb82e7fd..63691fbe47 100644 --- a/src/mapleall/maple_me/src/irmap_build.cpp +++ b/src/mapleall/maple_me/src/irmap_build.cpp @@ -408,6 +408,16 @@ MeExpr *IRMapBuild::BuildExpr(BaseNode &mirNode, bool atParm, bool noProp) { } } + if (op == OP_mul) { + OpMeExpr *opMeExpr = static_cast(meExpr); + if (opMeExpr->GetOpnd(0)->GetMeOp() == kMeOpConst) { + // canonicalize constant operand to be operand 1 + MeExpr *savedOpnd = opMeExpr->GetOpnd(0); + opMeExpr->SetOpnd(0, opMeExpr->GetOpnd(1)); + opMeExpr->SetOpnd(1, savedOpnd); + } + } + MeExpr *retMeExpr = irMap->HashMeExpr(*meExpr); delete meExpr; diff --git a/src/mapleall/maple_me/src/me_option.cpp b/src/mapleall/maple_me/src/me_option.cpp index 01e8cd4030..4de8364b55 100644 --- a/src/mapleall/maple_me/src/me_option.cpp +++ b/src/mapleall/maple_me/src/me_option.cpp @@ -97,6 +97,7 @@ bool MeOption::placementRC = false; bool MeOption::subsumRC = false; bool MeOption::performFSAA = true; bool MeOption::strengthReduction = false; +bool MeOption::doLFTR = false; std::string MeOption::inlineFuncList = ""; bool MeOption::meVerify = false; #if MIR_JAVA @@ -186,6 +187,7 @@ enum OptionIndex { kSubsumRC, kPerformFSAA, kStrengthReduction, + kLFTR, kRegReadAtReturn, kProPatphi, kNoProPatphi, @@ -778,8 +780,18 @@ const Descriptor kUsage[] = { "strengthreduction", kBuildTypeExperimental, kArgCheckPolicyBool, - " --strengthreduction \tPerform flow sensitive alias analysis\n" - " --no-strengthreduction \tDisable flow sensitive alias analysis\n", + " --strengthreduction \tPerform strength reduction\n" + " --no-strengthreduction \tDisable strength reduction\n", + "me", + {} }, + { kLFTR, + kEnable, + "", + "lftr", + kBuildTypeExperimental, + kArgCheckPolicyBool, + " --lftr \tPerform linear function test replacement\n" + " --no-lftr \tDisable linear function test replacement\n", "me", {} }, { kCheckCastOpt, @@ -1378,6 +1390,9 @@ bool MeOption::SolveOptions(const std::vector &opts, bool i case kStrengthReduction: strengthReduction = (opt.Type() == kEnable); break; + case kLFTR: + doLFTR = (opt.Type() == kEnable); + break; case kMeInlineHint: inlineFuncList = opt.Args(); break; diff --git a/src/mapleall/maple_me/src/me_ssa_epre.cpp b/src/mapleall/maple_me/src/me_ssa_epre.cpp index 0335d5a007..1961754754 100644 --- a/src/mapleall/maple_me/src/me_ssa_epre.cpp +++ b/src/mapleall/maple_me/src/me_ssa_epre.cpp @@ -92,6 +92,9 @@ AnalysisResult *MeDoSSAEPre::Run(MeFunction *func, MeFuncResultMgr *m, ModuleRes ssaPre.SetSpillAtCatch(MeOption::spillAtCatch); if (MeOption::strengthReduction && !func->GetMIRModule().IsJavaModule()) { ssaPre.strengthReduction = true; + if (MeOption::doLFTR) { + ssaPre.doLFTR = true; + } } if (func->GetHints() & kPlacementRCed) { ssaPre.SetPlacementRC(true); diff --git a/src/mapleall/maple_me/src/occur.cpp b/src/mapleall/maple_me/src/occur.cpp index 2671631946..7ec6eb3e2b 100644 --- a/src/mapleall/maple_me/src/occur.cpp +++ b/src/mapleall/maple_me/src/occur.cpp @@ -49,6 +49,7 @@ bool MeOccur::IsDominate(Dominance &dom, MeOccur &occ) { switch (occTy) { case kOccReal: { switch (occ.GetOccType()) { + case kOccCompare: case kOccReal: { if (mirBB == occ.GetBB()) { auto *thisRealOcc = static_cast(this); @@ -162,6 +163,10 @@ void MeRealOcc::Dump(const IRMap &irMap) const { } else { mod->GetOut() << " classID " << GetClassID(); } + } else if (GetOccType() == kOccCompare) { + mod->GetOut() << "CompOcc "; + meExpr->Dump(&irMap); + mod->GetOut() << " at bb" << GetBB()->GetBBId() << " seq " << seq << " classID " << GetClassID(); } else { mod->GetOut() << "MembarOcc "; mod->GetOut() << " at bb" << GetBB()->GetBBId() << " seq " << seq; diff --git a/src/mapleall/maple_me/src/ssa_epre.cpp b/src/mapleall/maple_me/src/ssa_epre.cpp index 401745161a..351acd82c5 100644 --- a/src/mapleall/maple_me/src/ssa_epre.cpp +++ b/src/mapleall/maple_me/src/ssa_epre.cpp @@ -296,6 +296,9 @@ void SSAEPre::ComputeVarAndDfPhis() { CHECK_FATAL(!dom->IsBBVecEmpty(), "size to be allocated is 0"); for (auto it = realOccList.begin(); it != realOccList.end(); ++it) { MeRealOcc *realOcc = *it; + if (realOcc->GetOccType() == kOccCompare) { + continue; + } BB *defBB = realOcc->GetBB(); GetIterDomFrontier(defBB, &dfPhiDfns); MeExpr *meExpr = realOcc->GetMeExpr(); @@ -337,7 +340,8 @@ void SSAEPre::BuildWorkListExpr(MeStmt &meStmt, int32 seqStmt, MeExpr &meExpr, b if (meExpr.GetPrimType() == PTY_agg) { break; } - if (isRootExpr && kOpcodeInfo.IsCompare(meOpExpr->GetOp())) { + if (isRootExpr && kOpcodeInfo.IsCompare(meOpExpr->GetOp()) && doLFTR) { + CreateCompOcc(&meStmt, seqStmt, meOpExpr, isRebuild); break; } if (!epreIncludeRef && meOpExpr->GetPrimType() == PTY_ref) { diff --git a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp new file mode 100644 index 0000000000..7f42ac9d58 --- /dev/null +++ b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) [2021] Huawei Technologies Co., Ltd. All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. + * You can use this software according to the terms and conditions of the MulanPSL - 2.0. + * You may obtain a copy of MulanPSL - 2.0 at: + * + * https://opensource.org/licenses/MulanPSL-2.0 + * + * 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 MulanPSL - 2.0 for more details. + */ + +#include "ssa_epre.h" + +namespace maple { + +// one side of compare is an operand x in workCand->GetTheMeExpr() with current +// occurrence occExpr; replace that side of the compare by regorvar; replace the +// other side of compare by the expression formed by substituting x in occExpr +// by that side of the compare; if the new compare side cannot be folded to a +// leaf, enter into EPRE work list +// EXAMPLE 1: INPUT: workCand is (i + 4), compare is (i < n) +// RETURN: regorvar < (n + 4) +// (n + 4) added to EPRE work list +// EXAMPLE 2: INPUT: workCand is (i * 3), compare is (n == i) +// RETURN: n * 3 == regorvar +// (n * 3) added to EPRE work list +// EXAMPLE 3: INPUT: workCand is (i + &A), compare is (i < 100) +// RETURN: regorvar < 100 + &A +// 100 + &A is folded to an OP_addrof node +OpMeExpr *SSAEPre::FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { + MeExpr *compare = compOcc->GetMeExpr(); + // determine the ith operand of workCand that is the jth operand of compare + OpMeExpr *x = static_cast(workCand->GetTheMeExpr()); + size_t i; + size_t j = 0; + for (i = 0; i < x->GetNumOpnds(); i++) { + ScalarMeExpr *iv = dynamic_cast(x->GetOpnd(i)); + if (iv == nullptr) { + continue; + } + ScalarMeExpr *compareOpnd = dynamic_cast(compare->GetOpnd(0)); + if (compareOpnd != nullptr && iv->GetOst() == compareOpnd->GetOst()) { + j = 0; + break; + } + compareOpnd = dynamic_cast(compare->GetOpnd(1)); + if (compareOpnd != nullptr && iv->GetOst() == compareOpnd->GetOst()) { + j = 1; + break; + } + } + ASSERT(j == 0 || j == 1, "FormLFTRCompare: cannot correspond comp occ to workcand"); + // handle the ops corresponding to OpMeExpr::StrengthReducible() + OpMeExpr newSide(-1, x->GetOp(), x->GetPrimType(), x->GetNumOpnds()); + newSide.SetOpnd(i, compare->GetOpnd(1-j)); + switch (x->GetOp()) { + case OP_cvt: { + newSide.SetOpndType(x->GetOpndType()); + break; + } + case OP_mul: + case OP_add: { + newSide.SetOpnd(1-i, x->GetOpnd(1-i)); + break; + } + default: { + ASSERT(false, "FormLFTRCompare: unrecognized strength reduction operation"); + return nullptr; + } + } + // check if newSide can be folded + MeExpr *simplifyExpr = irMap->SimplifyOpMeExpr(&newSide); + MeExpr *hashedSide = nullptr; + if (simplifyExpr != nullptr) { + hashedSide = simplifyExpr; + } else { + hashedSide = irMap->HashMeExpr(newSide); + BuildWorkListExpr(*compOcc->GetMeStmt(), compOcc->GetSequence(), *hashedSide, false, nullptr, true); + } + OpMeExpr newcompare(-1, compare->GetOp(), compare->GetPrimType(), 2); + newcompare.SetOpndType(static_cast(compare)->GetOpndType()); + newcompare.SetOpnd(j, regorvar); + newcompare.SetOpnd(1-j, hashedSide); + return static_cast(irMap->HashMeExpr(newcompare)); +} + +void SSAEPre::CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *compare, bool isRebuilt) { + if (compare->GetOpnd(0)->GetNumOpnds() > 0 || + compare->GetOpnd(1)->GetNumOpnds() > 0) { + // both sides of compare must be leaf + return; + } + ScalarMeExpr *compareLHS = dynamic_cast(compare->GetOpnd(0)); + ScalarMeExpr *compareRHS = dynamic_cast(compare->GetOpnd(1)); + if (compareLHS == nullptr && compareRHS == nullptr) { + return; + } + // search for worklist candidates set isSRCand such that one of its operands + // is either compareLHS or compareRHS, and create MeRealOcc for each of them + for (PreWorkCand *wkCand : workList) { + if (!wkCand->isSRCand) { + continue; + } + MeExpr *x = wkCand->GetTheMeExpr(); + bool isRelevant = false; + for (size_t i = 0; i < x->GetNumOpnds(); i++) { + ScalarMeExpr *iv = dynamic_cast(x->GetOpnd(i)); + if (iv == nullptr) { + continue; + } + if ((compareLHS && iv->GetOst() == compareLHS->GetOst()) || + (compareRHS && iv->GetOst() == compareRHS->GetOst())) { + isRelevant = true; + } else { // disqualify as compocc if x has a scalar which is not an iv + isRelevant = false; + break; + } + } + if (isRelevant) { + MeRealOcc *compOcc = ssaPreMemPool->New(meStmt, seqStmt, compare); + compOcc->SetOccType(kOccCompare); + if (isRebuilt) { + // insert to realOccs in dt_preorder of the BBs and seq in each BB + wkCand->AddRealOccSorted(*dom, *compOcc, GetPUIdx()); + } else { + wkCand->AddRealOccAsLast(*compOcc, GetPUIdx()); + } + } + } +} + +} // namespace maple diff --git a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp index e7d0665bbe..2d8ec7aa7e 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp @@ -258,7 +258,7 @@ MeExpr* SSAEPre::SRRepairInjuries(MeOccur *useocc, std::set *needRepairInjuringDefs, std::set *repairedInjuringDefs) { MeExpr *useexpr = nullptr; - if (useocc->GetOccType() == kOccReal) { + if (useocc->GetOccType() == kOccReal || useocc->GetOccType() == kOccCompare) { MeRealOcc *realocc = static_cast(useocc); useexpr = realocc->GetMeExpr(); } else { diff --git a/src/mapleall/maple_me/src/ssa_pre.cpp b/src/mapleall/maple_me/src/ssa_pre.cpp index 855af1e8ce..c26f957105 100644 --- a/src/mapleall/maple_me/src/ssa_pre.cpp +++ b/src/mapleall/maple_me/src/ssa_pre.cpp @@ -290,6 +290,18 @@ void SSAPre::CodeMotion() { GenerateSavePhiOcc(*phiOcc); break; } + case kOccCompare: { + MeRealOcc *compOcc = static_cast(occ); + if (!compOcc->IsReload()) { + break; + } + MeExpr *regorvar = SRRepairInjuries(compOcc, &needRepairInjuringDefs, &repairedInjuringDefs); + OpMeExpr *newCompare = FormLFTRCompare(compOcc, regorvar); + // replace compOcc->mestmt's occ with newCompare + irMap->ReplaceMeExprStmt(*compOcc->GetMeStmt(), *compOcc->GetMeExpr(), *newCompare); + CreateCompOcc(compOcc->GetMeStmt(), compOcc->GetSequence(), newCompare, true); + break; + } case kOccExit: break; case kOccMembar: @@ -318,7 +330,7 @@ void SSAPre::Finalize1() { std::vector availDefVec(classCount, nullptr); // traversal in preoder DT for (MeOccur *occ : allOccs) { - size_t classX = static_cast(static_cast(occ->GetClassID())); + int classX = occ->GetClassID(); switch (occ->GetOccType()) { case kOccPhiocc: { auto *phiOcc = static_cast(occ); @@ -340,6 +352,18 @@ void SSAPre::Finalize1() { } break; } + case kOccCompare: { + if (classX == 0) { + break; + } + MeOccur *availDef = availDefVec[classX]; + CHECK_FATAL(availDef != nullptr, "compare occ with class ID has no available def"); + CHECK_FATAL(availDef->IsDominate(*dom, *occ), "compare occ's available def not dominating it"); + MeRealOcc *compOcc = static_cast(occ); + compOcc->SetIsReload(true); + compOcc->SetDef(availDefVec[classX]); + break; + } case kOccPhiopnd: { // we assume one phiOpnd has only one phiOcc use because critical edge split the blocks auto *phiOpnd = static_cast(occ); @@ -773,6 +797,9 @@ void SSAPre::Rename1() { } else { for (auto varIt = varVec.begin(); varIt != varVec.end(); ++varIt) { MeExpr *varMeExpr = *varIt; + if (workCand->isSRCand) { + varMeExpr = ResolveAllInjuringDefs(varMeExpr); + } if (!DefVarDominateOcc(varMeExpr, *topOccur)) { isAllDom = false; } @@ -799,6 +826,56 @@ void SSAPre::Rename1() { } break; } + case kOccCompare: { + if (occStack.empty()) { + break; + } + MeOccur *topOccur = occStack.top(); + if (topOccur->GetOccType() == kOccUse || topOccur->GetOccType() == kOccMembar) { + break; + } + MeRealOcc *realOcc = static_cast(occ); + // set scalarOpnd to be the operand that is scalar + ScalarMeExpr *scalarOpnd = dynamic_cast(workCand->GetTheMeExpr()->GetOpnd(0)); + uint32 scalarOpndNo = 0; + if (scalarOpnd == nullptr) { + scalarOpnd = static_cast(workCand->GetTheMeExpr()->GetOpnd(1)); + scalarOpndNo = 1; + } + ScalarMeExpr *compareOpnd = nullptr; + MeExpr *opnd0 = realOcc->GetMeExpr()->GetOpnd(0); + MeExpr *opnd1 = realOcc->GetMeExpr()->GetOpnd(1); + if ((opnd0->GetMeOp() == kMeOpVar || opnd0->GetMeOp() == kMeOpReg) && + (static_cast(opnd0)->GetOst() == scalarOpnd->GetOst())) { + compareOpnd = static_cast(opnd0); + } else if ((opnd1->GetMeOp() == kMeOpVar || opnd1->GetMeOp() == kMeOpReg) && + (static_cast(opnd1)->GetOst() == scalarOpnd->GetOst())) { + compareOpnd = static_cast(opnd1); + } + CHECK_FATAL(compareOpnd != nullptr, "Rename1: compOcc does not correspond to realOcc"); + ScalarMeExpr *resolvedCompareOpnd = ResolveAllInjuringDefs(compareOpnd); + if (topOccur->GetOccType() == kOccReal) { + MeRealOcc *realTopOccur = static_cast(topOccur); + ScalarMeExpr *topOccurOpnd = static_cast(realTopOccur->GetMeExpr()->GetOpnd(scalarOpndNo)); + if (compareOpnd == topOccurOpnd || resolvedCompareOpnd == topOccurOpnd) { + realOcc->SetClassID(realTopOccur->GetClassID()); + if (realTopOccur->GetDef() != nullptr) { + realOcc->SetDef(realTopOccur->GetDef()); + } else { + realOcc->SetDef(realTopOccur); + } + } + break; + } + // top of stack is a PHI occurrence + ASSERT(topOccur->GetOccType() == kOccPhiocc, "invalid kOccPhiocc"); + if (DefVarDominateOcc(compareOpnd, *topOccur) || + (resolvedCompareOpnd && DefVarDominateOcc(resolvedCompareOpnd, *topOccur))) { + realOcc->SetClassID(topOccur->GetClassID()); + realOcc->SetDef(topOccur); + } + break; + } case kOccPhiocc: { // assign new class occ->SetClassID(classCount++); @@ -940,7 +1017,7 @@ void SSAPre::Rename2() { bool hasSameVersion = true; for (size_t ii = 0; ii < varVecX.size(); ii++) { MeExpr *resolvedY = ResolveAllInjuringDefs(varVecY[ii]); - if (varVecX[ii] != resolvedY) { + if (varVecX[ii] != resolvedY && varVecX[ii] != varVecY[ii]) { hasSameVersion = false; } } @@ -1104,6 +1181,7 @@ void SSAPre::CreateSortedOccs() { switch (pickedOcc->GetOccType()) { case kOccReal: case kOccMembar: + case kOccCompare: ++realOccIt; if (realOccIt != workCand->GetRealOccs().end()) { nextRealOcc = *realOccIt; -- Gitee From 0f459e168f78ead09198ff88be4976e7537b8276 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Fri, 11 Jun 2021 09:03:43 -0700 Subject: [PATCH 3/5] LFTR and strength reduction bug fixes --- .../src/cg/aarch64/aarch64_cgfunc.cpp | 17 +++++-- src/mapleall/maple_me/src/irmap_build.cpp | 18 +++++-- src/mapleall/maple_me/src/me_ir.cpp | 19 ++++++-- src/mapleall/maple_me/src/ssa_epre.cpp | 9 ++-- .../maple_me/src/ssa_epre_for_lftr.cpp | 2 +- src/mapleall/maple_me/src/ssa_epre_for_sr.cpp | 14 ++++++ src/mapleall/maple_me/src/ssa_pre.cpp | 48 +++++++++++++------ 7 files changed, 98 insertions(+), 29 deletions(-) diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index eaacdf46ba..5ce6b60262 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -7736,12 +7736,16 @@ Operand *AArch64CGFunc::SelectCclz(IntrinsicopNode &intrnNode) { PrimType ptype = argexpr->GetPrimType(); Operand *opnd = HandleExpr(intrnNode, *argexpr); MOperator mop; + + RegOperand &ldDest = CreateRegisterOperandOfType(ptype); if (opnd->IsMemoryAccessOperand()) { - RegOperand &ldDest = CreateRegisterOperandOfType(ptype); Insn &insn = GetCG()->BuildInstruction(PickLdInsn(GetPrimTypeBitSize(ptype), ptype), ldDest, *opnd); GetCurBB()->AppendInsn(insn); - opnd = &ldDest; + } else if (opnd->IsImmediate()) { + SelectCopyImm(ldDest, *static_cast(opnd), ptype); } + opnd = &ldDest; + if (GetPrimTypeSize(ptype) == k4ByteSize) { mop = MOP_wclz; } else { @@ -7756,12 +7760,17 @@ Operand *AArch64CGFunc::SelectCctz(IntrinsicopNode &intrnNode) { BaseNode *argexpr = intrnNode.Opnd(0); PrimType ptype = argexpr->GetPrimType(); Operand *opnd = HandleExpr(intrnNode, *argexpr); + + RegOperand &ldDest = CreateRegisterOperandOfType(ptype); if (opnd->IsMemoryAccessOperand()) { - RegOperand &ldDest = CreateRegisterOperandOfType(ptype); Insn &insn = GetCG()->BuildInstruction(PickLdInsn(GetPrimTypeBitSize(ptype), ptype), ldDest, *opnd); GetCurBB()->AppendInsn(insn); - opnd = &ldDest; + } else if (opnd->IsImmediate()) { + RegOperand &ldDest = CreateRegisterOperandOfType(ptype); + SelectCopyImm(ldDest, *static_cast(opnd), ptype); } + opnd = &ldDest; + MOperator clzmop; MOperator rbitmop; if (GetPrimTypeSize(ptype) == k4ByteSize) { diff --git a/src/mapleall/maple_me/src/irmap_build.cpp b/src/mapleall/maple_me/src/irmap_build.cpp index 63691fbe47..6e949bfb05 100644 --- a/src/mapleall/maple_me/src/irmap_build.cpp +++ b/src/mapleall/maple_me/src/irmap_build.cpp @@ -539,6 +539,15 @@ MeStmt *IRMapBuild::BuildMeStmtWithNoSSAPart(StmtNode &stmt) { } } +static bool IncDecAmountIsSmallInteger(MeExpr *x) { + if (x->GetMeOp() != kMeOpConst) { + return false; + } + ConstMeExpr *cMeExpr = static_cast(x); + MIRIntConst *cnode = dynamic_cast(cMeExpr->GetConstVal()); + return cnode && cnode->GetValue() < 0x1000; +} + MeStmt *IRMapBuild::BuildDassignMeStmt(StmtNode &stmt, AccessSSANodes &ssaPart) { DassignMeStmt *meStmt = irMap->NewInPool(&stmt); DassignNode &dassiNode = static_cast(stmt); @@ -549,10 +558,13 @@ MeStmt *IRMapBuild::BuildDassignMeStmt(StmtNode &stmt, AccessSSANodes &ssaPart) // determine isIncDecStmt if (meStmt->GetChiList()->empty()) { MeExpr *rhs = meStmt->GetRHS(); - if (rhs->GetOp() == OP_add || rhs->GetOp() == OP_sub) { + OriginalSt *ost = varLHS->GetOst(); + if (ost->GetType()->GetSize() >= 4 && + (rhs->GetOp() == OP_add || rhs->GetOp() == OP_sub) && + IsPrimitivePureScalar(rhs->GetPrimType())) { OpMeExpr *oprhs = static_cast(rhs); - if (oprhs->GetOpnd(0)->GetMeOp() == kMeOpVar && oprhs->GetOpnd(1)->GetMeOp() == kMeOpConst) { - meStmt->isIncDecStmt = varLHS->GetOst() == static_cast(oprhs->GetOpnd(0))->GetOst(); + if (oprhs->GetOpnd(0)->GetMeOp() == kMeOpVar && IncDecAmountIsSmallInteger(oprhs->GetOpnd(1))) { + meStmt->isIncDecStmt = ost == static_cast(oprhs->GetOpnd(0))->GetOst(); } } } diff --git a/src/mapleall/maple_me/src/me_ir.cpp b/src/mapleall/maple_me/src/me_ir.cpp index 9c7209b8a0..ad8c56a0e1 100644 --- a/src/mapleall/maple_me/src/me_ir.cpp +++ b/src/mapleall/maple_me/src/me_ir.cpp @@ -306,11 +306,18 @@ bool OpMeExpr::IsCompareIdentical(const OpMeExpr &meExpr) const { return (meExpr.GetOpnd(1) == this->GetOpnd(0)) && (meExpr.GetOpnd(0) == this->GetOpnd(1)); } +static bool CompatibleIntegerTypes(PrimType pty1, PrimType pty2) { + if (IsPrimitiveInteger(pty1) && IsPrimitiveInteger(pty2)) { + return GetPrimTypeSize(pty1) == GetPrimTypeSize(pty2) && IsSignedInteger(pty1) == IsSignedInteger(pty2); + } + return false; +} + bool OpMeExpr::IsIdentical(const OpMeExpr &meExpr) const { if (meExpr.GetOp() != GetOp()) { return false; } - if (meExpr.GetPrimType() != GetPrimType() || meExpr.opndType != opndType || meExpr.bitsOffset != bitsOffset || + if (!CompatibleIntegerTypes(meExpr.GetPrimType(), GetPrimType()) || meExpr.opndType != opndType || meExpr.bitsOffset != bitsOffset || meExpr.bitsSize != bitsSize || meExpr.tyIdx != tyIdx || meExpr.fieldID != fieldID) { return false; } @@ -575,8 +582,14 @@ bool OpMeExpr::StrengthReducible() { case OP_cvt: { return IsPrimitiveInteger(opndType) && GetPrimTypeSize(primType) >= GetPrimTypeSize(opndType); } - case OP_mul: - return GetOpnd(1)->GetOp() == OP_constval; + case OP_mul: { + if (GetOpnd(1)->GetOp() == OP_constval) { + ConstMeExpr *cMeExpr = static_cast(GetOpnd(1)); + MIRIntConst *cnode = static_cast(cMeExpr->GetConstVal()); + return cnode->GetValue() < 0x1000; + } + return false; + } case OP_add: return true; default: return false; diff --git a/src/mapleall/maple_me/src/ssa_epre.cpp b/src/mapleall/maple_me/src/ssa_epre.cpp index 351acd82c5..940ac78969 100644 --- a/src/mapleall/maple_me/src/ssa_epre.cpp +++ b/src/mapleall/maple_me/src/ssa_epre.cpp @@ -225,8 +225,7 @@ MeExpr *SSAEPre::PhiOpndFromRes(MeRealOcc &realZ, size_t j) const { case kMeOpOp: { OpMeExpr opMeExpr(*static_cast(realZ.GetMeExpr()), -1); for (size_t i = 0; i < opMeExpr.GetNumOpnds(); ++i) { - MeExpr *resolvedOpnd = ResolveAllInjuringDefs(opMeExpr.GetOpnd(i)); - MeExpr *retOpnd = GetReplaceMeExpr(*resolvedOpnd, *ePhiBB, j); + MeExpr *retOpnd = GetReplaceMeExpr(*opMeExpr.GetOpnd(i), *ePhiBB, j); if (retOpnd != nullptr) { opMeExpr.SetOpnd(i, retOpnd); } @@ -340,8 +339,10 @@ void SSAEPre::BuildWorkListExpr(MeStmt &meStmt, int32 seqStmt, MeExpr &meExpr, b if (meExpr.GetPrimType() == PTY_agg) { break; } - if (isRootExpr && kOpcodeInfo.IsCompare(meOpExpr->GetOp()) && doLFTR) { - CreateCompOcc(&meStmt, seqStmt, meOpExpr, isRebuild); + if (isRootExpr && kOpcodeInfo.IsCompare(meOpExpr->GetOp())) { + if (doLFTR) { + CreateCompOcc(&meStmt, seqStmt, meOpExpr, isRebuild); + } break; } if (!epreIncludeRef && meOpExpr->GetPrimType() == PTY_ref) { diff --git a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp index 7f42ac9d58..506fc3fdbe 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp @@ -79,7 +79,7 @@ OpMeExpr *SSAEPre::FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { hashedSide = simplifyExpr; } else { hashedSide = irMap->HashMeExpr(newSide); - BuildWorkListExpr(*compOcc->GetMeStmt(), compOcc->GetSequence(), *hashedSide, false, nullptr, true); + BuildWorkListExpr(*compOcc->GetMeStmt(), compOcc->GetSequence(), *hashedSide, true, nullptr, true); } OpMeExpr newcompare(-1, compare->GetOp(), compare->GetPrimType(), 2); newcompare.SetOpndType(static_cast(compare)->GetOpndType()); diff --git a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp index 2d8ec7aa7e..ea476bc92e 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp @@ -254,6 +254,15 @@ MeExpr* SSAEPre::SRRepairOpndInjuries(MeExpr *curopnd, MeOccur *defocc, int32 i, return repairedTemp; } +static bool IsScalarInWorkCandExpr(ScalarMeExpr *scalar, OpMeExpr *theMeExpr) { + ScalarMeExpr *iv = dynamic_cast(theMeExpr->GetOpnd(0)); + if (iv && iv->GetOst() == scalar->GetOst()) { + return true; + } + iv = dynamic_cast(theMeExpr->GetOpnd(1)); + return iv && iv->GetOst() == scalar->GetOst(); +} + MeExpr* SSAEPre::SRRepairInjuries(MeOccur *useocc, std::set *needRepairInjuringDefs, std::set *repairedInjuringDefs) { @@ -287,6 +296,11 @@ MeExpr* SSAEPre::SRRepairInjuries(MeOccur *useocc, if (curopnd->GetMeOp() != kMeOpVar && curopnd->GetMeOp() != kMeOpReg) { continue; } + if (useocc->GetOccType() == kOccCompare) { + if (!IsScalarInWorkCandExpr(static_cast(curopnd), static_cast(workCand->GetTheMeExpr()))) { + continue; + } + } if (!OpndInDefOcc(curopnd, defocc, i)) { repairedTemp = SRRepairOpndInjuries(curopnd, defocc, i, repairedTemp, needRepairInjuringDefs, repairedInjuringDefs); diff --git a/src/mapleall/maple_me/src/ssa_pre.cpp b/src/mapleall/maple_me/src/ssa_pre.cpp index c26f957105..5d3c92d027 100644 --- a/src/mapleall/maple_me/src/ssa_pre.cpp +++ b/src/mapleall/maple_me/src/ssa_pre.cpp @@ -295,6 +295,17 @@ void SSAPre::CodeMotion() { if (!compOcc->IsReload()) { break; } + if (compOcc->GetDef()->GetOccType() == kOccReal) { + MeRealOcc *defRealOcc = static_cast(compOcc->GetDef()); + if (!defRealOcc->IsReload() && !defRealOcc->IsSave()) { + break; + } + } else { + MePhiOcc *phiOcc = static_cast(compOcc->GetDef()); + if (phiOcc->IsRemoved() || !phiOcc->IsWillBeAvail() || !phiOcc->IsDownSafe()) { + break; + } + } MeExpr *regorvar = SRRepairInjuries(compOcc, &needRepairInjuringDefs, &repairedInjuringDefs); OpMeExpr *newCompare = FormLFTRCompare(compOcc, regorvar); // replace compOcc->mestmt's occ with newCompare @@ -357,7 +368,17 @@ void SSAPre::Finalize1() { break; } MeOccur *availDef = availDefVec[classX]; - CHECK_FATAL(availDef != nullptr, "compare occ with class ID has no available def"); + if (availDef == nullptr) { + occ->SetClassID(0); + break; + } + if (availDef->GetOccType() == kOccReal) { + MeRealOcc *realOcc = static_cast(availDef); + if (!realOcc->IsReload() && !realOcc->IsSave()) { + occ->SetClassID(0); + break; + } + } CHECK_FATAL(availDef->IsDominate(*dom, *occ), "compare occ's available def not dominating it"); MeRealOcc *compOcc = static_cast(occ); compOcc->SetIsReload(true); @@ -869,8 +890,8 @@ void SSAPre::Rename1() { } // top of stack is a PHI occurrence ASSERT(topOccur->GetOccType() == kOccPhiocc, "invalid kOccPhiocc"); - if (DefVarDominateOcc(compareOpnd, *topOccur) || - (resolvedCompareOpnd && DefVarDominateOcc(resolvedCompareOpnd, *topOccur))) { + if (DefVarDominateOcc(compareOpnd, *topOccur) /* || + (resolvedCompareOpnd && DefVarDominateOcc(resolvedCompareOpnd, *topOccur))*/) { realOcc->SetClassID(topOccur->GetClassID()); realOcc->SetDef(topOccur); } @@ -959,25 +980,21 @@ void SSAPre::Rename1() { } } -// if opnd is defined by phi, return the jth opnd of the phi; +// if opnd has a phi definition at ePhiBB, return the jth opnd of the phi; // return nullptr otherwise MeExpr *SSAPre::GetReplaceMeExpr(const MeExpr &opnd, const BB &ePhiBB, size_t j) const { if (opnd.GetMeOp() != kMeOpVar && opnd.GetMeOp() != kMeOpReg) { return nullptr; } - MeExpr *retExpr = nullptr; const ScalarMeExpr *expr = static_cast(&opnd); - if (expr->IsDefByPhi()) { - MePhiNode *defPhi = expr->GetMePhiDef(); - if (ePhiBB.GetBBId() == defPhi->GetDefBB()->GetBBId()) { - ASSERT(j < defPhi->GetOpnds().size(), "index out of range in SSAPre::GetReplaceMeExpr"); - ASSERT(defPhi->GetOpnds()[j]->GetMeOp() == opnd.GetMeOp(), "invalid defPhi"); - retExpr = defPhi->GetOpnds()[j]; - } + auto it = ePhiBB.GetMePhiList().find(expr->GetOst()->GetIndex()); + if (it == ePhiBB.GetMePhiList().end()) { + return nullptr; } - - if (retExpr != nullptr && retExpr->GetPrimType() == kPtyInvalid) { + MePhiNode *defPhi = it->second; + MeExpr *retExpr = defPhi->GetOpnds()[j]; + if (retExpr->GetPrimType() == kPtyInvalid) { ASSERT_NOT_NULL(workCand); retExpr->SetPtyp(workCand->GetPrimType()); } @@ -1057,6 +1074,9 @@ void SSAPre::Rename2() { mirModule->GetOut() << "--- rename2 adds to rename2Set manufactured "; occY->Dump(*irMap); mirModule->GetOut() << '\n'; + mirModule->GetOut() << " with def at\n"; + occY->GetDef()->Dump(*irMap); + mirModule->GetOut() << "\n"; } } else { phiOpnd->SetDef(nullptr); -- Gitee From b83fba1969ee09dc628e0c51d7e386122a655913 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Wed, 16 Jun 2021 16:26:54 -0700 Subject: [PATCH 4/5] Include OP_sub as strength reduction candidate; tune and cover more cases in LFTR --- src/mapleall/maple_me/include/me_ir.h | 4 +- src/mapleall/maple_me/include/occur.h | 4 +- src/mapleall/maple_me/src/me_ir.cpp | 25 ++++++-- src/mapleall/maple_me/src/me_ssa_epre.cpp | 4 -- .../maple_me/src/ssa_epre_for_lftr.cpp | 41 ++++++++++--- src/mapleall/maple_me/src/ssa_epre_for_sr.cpp | 4 +- src/mapleall/maple_me/src/ssa_pre.cpp | 58 ++++++++++++++----- 7 files changed, 102 insertions(+), 38 deletions(-) diff --git a/src/mapleall/maple_me/include/me_ir.h b/src/mapleall/maple_me/include/me_ir.h index 0793a28f5f..7bee6a505a 100644 --- a/src/mapleall/maple_me/include/me_ir.h +++ b/src/mapleall/maple_me/include/me_ir.h @@ -164,7 +164,7 @@ class MeExpr { return 0; } virtual bool StrengthReducible() { return false; } - virtual int64 SRMultiplier() { return 1; } + virtual int64 SRMultiplier(OriginalSt *ost) { return 1; } protected: MeExpr *FindSymAppearance(OStIdx oidx); // find the appearance of the symbol @@ -867,7 +867,7 @@ class OpMeExpr : public MeExpr { return nullptr; } bool StrengthReducible() override; - int64 SRMultiplier() override; + int64 SRMultiplier(OriginalSt *ost) override; private: std::array opnds = { nullptr }; // kid diff --git a/src/mapleall/maple_me/include/occur.h b/src/mapleall/maple_me/include/occur.h index d8ce0e3c22..2b095c8146 100644 --- a/src/mapleall/maple_me/include/occur.h +++ b/src/mapleall/maple_me/include/occur.h @@ -503,7 +503,8 @@ class PreWorkCand { hasLocalOpnd(false), redo2HandleCritEdges(false), needLocalRefVar(false), - isSRCand(false) { + isSRCand(false), + onlyInvariantOpnds(false) { ASSERT(pIdx != 0, "PreWorkCand: initial puIdx cannot be 0"); } @@ -633,6 +634,7 @@ class PreWorkCand { bool needLocalRefVar : 1; // for the candidate, if necessary to introduce public: bool isSRCand : 1; // is a strength reduction candidate + bool onlyInvariantOpnds : 1; // all operands have only 1 SSA version // localrefvar in addition to the temp register to for saving the value }; diff --git a/src/mapleall/maple_me/src/me_ir.cpp b/src/mapleall/maple_me/src/me_ir.cpp index ad8c56a0e1..bf5a312ba9 100644 --- a/src/mapleall/maple_me/src/me_ir.cpp +++ b/src/mapleall/maple_me/src/me_ir.cpp @@ -591,19 +591,32 @@ bool OpMeExpr::StrengthReducible() { return false; } case OP_add: + case OP_sub: return true; default: return false; } } -int64 OpMeExpr::SRMultiplier() { +int64 OpMeExpr::SRMultiplier(OriginalSt *ost) { ASSERT(StrengthReducible(), "OpMeExpr::SRMultiplier: operation is not strength reducible"); - if (op != OP_mul) { - return 1; + switch (op) { + case OP_cvt: + case OP_add: return 1; + case OP_sub: { + ScalarMeExpr *scalarOpnd1 = dynamic_cast(GetOpnd(1)); + if (scalarOpnd1 && scalarOpnd1->GetOst() == ost) { + return -1; + } + return 1; + } + case OP_mul: { + MIRConst *constVal = static_cast(GetOpnd(1))->GetConstVal(); + ASSERT(constVal->GetKind() == kConstInt, "OpMeExpr::SRMultiplier: multiplier not an integer constant"); + return static_cast(constVal)->GetValueUnderType(); + } + default: CHECK_FATAL(false, "SRMultiplier: unexpected strength reduction opcode"); } - MIRConst *constVal = static_cast(GetOpnd(1))->GetConstVal(); - ASSERT(constVal->GetKind() == kConstInt, "OpMeExpr::SRMultiplier: multiplier not an integer constant"); - return static_cast(constVal)->GetValueUnderType(); + return 0; } // first, make sure it's int const and return true if the int const great or eq 0 diff --git a/src/mapleall/maple_me/src/me_ssa_epre.cpp b/src/mapleall/maple_me/src/me_ssa_epre.cpp index 1961754754..d98741c1b9 100644 --- a/src/mapleall/maple_me/src/me_ssa_epre.cpp +++ b/src/mapleall/maple_me/src/me_ssa_epre.cpp @@ -125,10 +125,6 @@ AnalysisResult *MeDoSSAEPre::Run(MeFunction *func, MeFuncResultMgr *m, ModuleRes hdse.hdseKeepRef = MeOption::dseKeepRef; hdse.DoHDSE(); } - if (DEBUGFUNC(func)) { - LogInfo::MapleLogger() << "\n============== EPRE =============" << "\n"; - func->Dump(false); - } ++puCount; return nullptr; } diff --git a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp index 506fc3fdbe..785aa748a5 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp @@ -57,13 +57,15 @@ OpMeExpr *SSAEPre::FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { // handle the ops corresponding to OpMeExpr::StrengthReducible() OpMeExpr newSide(-1, x->GetOp(), x->GetPrimType(), x->GetNumOpnds()); newSide.SetOpnd(i, compare->GetOpnd(1-j)); + bool isRebuild = !newSide.GetOpnd(i)->IsLeaf(); // so hashedSide will always create new workcand switch (x->GetOp()) { case OP_cvt: { newSide.SetOpndType(x->GetOpndType()); break; } case OP_mul: - case OP_add: { + case OP_add: + case OP_sub: { newSide.SetOpnd(1-i, x->GetOpnd(1-i)); break; } @@ -79,7 +81,7 @@ OpMeExpr *SSAEPre::FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { hashedSide = simplifyExpr; } else { hashedSide = irMap->HashMeExpr(newSide); - BuildWorkListExpr(*compOcc->GetMeStmt(), compOcc->GetSequence(), *hashedSide, true, nullptr, true); + BuildWorkListExpr(*compOcc->GetMeStmt(), compOcc->GetSequence(), *hashedSide, isRebuild, nullptr, true); } OpMeExpr newcompare(-1, compare->GetOp(), compare->GetPrimType(), 2); newcompare.SetOpndType(static_cast(compare)->GetOpndType()); @@ -94,19 +96,40 @@ void SSAEPre::CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *compare, bool // both sides of compare must be leaf return; } + if (!IsPrimitiveInteger(compare->GetPrimType())) { + return; + } ScalarMeExpr *compareLHS = dynamic_cast(compare->GetOpnd(0)); ScalarMeExpr *compareRHS = dynamic_cast(compare->GetOpnd(1)); if (compareLHS == nullptr && compareRHS == nullptr) { return; } + // see if either side is a large integer + bool largeIntLimit = false; + ConstMeExpr *constopnd = dynamic_cast(compare->GetOpnd(0)); + if (constopnd == nullptr) { + constopnd = dynamic_cast(compare->GetOpnd(1)); + } + if (constopnd) { + MIRIntConst *intconst = dynamic_cast(constopnd->GetConstVal()); + if (intconst && ((uint64) intconst->GetValue()) > 0x8000000) + largeIntLimit = true; + } // search for worklist candidates set isSRCand such that one of its operands // is either compareLHS or compareRHS, and create MeRealOcc for each of them for (PreWorkCand *wkCand : workList) { if (!wkCand->isSRCand) { continue; } + if (largeIntLimit && (wkCand->GetTheMeExpr()->GetOp() == OP_add || wkCand->GetTheMeExpr()->GetOp() == OP_sub)) { + continue; + } + if (wkCand->GetTheMeExpr()->GetOp() == OP_sub && IsUnsignedInteger(wkCand->GetTheMeExpr()->GetPrimType())) { + continue; + } MeExpr *x = wkCand->GetTheMeExpr(); - bool isRelevant = false; + uint32 numRelevantOpnds = 0; + bool isRelevant = true; for (size_t i = 0; i < x->GetNumOpnds(); i++) { ScalarMeExpr *iv = dynamic_cast(x->GetOpnd(i)); if (iv == nullptr) { @@ -114,13 +137,15 @@ void SSAEPre::CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *compare, bool } if ((compareLHS && iv->GetOst() == compareLHS->GetOst()) || (compareRHS && iv->GetOst() == compareRHS->GetOst())) { - isRelevant = true; - } else { // disqualify as compocc if x has a scalar which is not an iv - isRelevant = false; - break; + numRelevantOpnds++; + } else { // disqualify as compocc if x has a scalar which is not used in the comparison and has multiple SSA versions + if (iv->GetOst()->GetVersionsIndices().size() > 1) { + isRelevant = false; + break; + } } } - if (isRelevant) { + if (isRelevant && numRelevantOpnds == 1) { MeRealOcc *compOcc = ssaPreMemPool->New(meStmt, seqStmt, compare); compOcc->SetOccType(kOccCompare); if (isRebuilt) { diff --git a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp index ea476bc92e..b34a85d240 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp @@ -209,7 +209,7 @@ MeExpr* SSAEPre::SRRepairOpndInjuries(MeExpr *curopnd, MeOccur *defocc, int32 i, } } while (!done); // generate the increment statement at latestInjuringDef - repairedTemp = InsertRepairStmt(repairedTemp, increAmt * workCand->GetTheMeExpr()->SRMultiplier(), + repairedTemp = InsertRepairStmt(repairedTemp, increAmt * workCand->GetTheMeExpr()->SRMultiplier(varx->GetOst()), latestInjuringDef); } else { // find the last repair increment statement @@ -244,7 +244,7 @@ MeExpr* SSAEPre::SRRepairOpndInjuries(MeExpr *curopnd, MeOccur *defocc, int32 i, } } while (!done); // generate the increment statement at latestInjuringDef - repairedTemp = InsertRepairStmt(repairedTemp, increAmt * workCand->GetTheMeExpr()->SRMultiplier(), + repairedTemp = InsertRepairStmt(repairedTemp, increAmt * workCand->GetTheMeExpr()->SRMultiplier(regx->GetOst()), latestInjuringDef); } else { // find the last repair increment statement diff --git a/src/mapleall/maple_me/src/ssa_pre.cpp b/src/mapleall/maple_me/src/ssa_pre.cpp index 5d3c92d027..78ac3c3e87 100644 --- a/src/mapleall/maple_me/src/ssa_pre.cpp +++ b/src/mapleall/maple_me/src/ssa_pre.cpp @@ -856,22 +856,31 @@ void SSAPre::Rename1() { break; } MeRealOcc *realOcc = static_cast(occ); - // set scalarOpnd to be the operand that is scalar - ScalarMeExpr *scalarOpnd = dynamic_cast(workCand->GetTheMeExpr()->GetOpnd(0)); + ScalarMeExpr *scalarOpnd0 = dynamic_cast(workCand->GetTheMeExpr()->GetOpnd(0)); + ScalarMeExpr *scalarOpnd1 = dynamic_cast(workCand->GetTheMeExpr()->GetOpnd(1)); + ScalarMeExpr *compareOpnd0 = dynamic_cast(realOcc->GetMeExpr()->GetOpnd(0)); + ScalarMeExpr *compareOpnd1 = dynamic_cast(realOcc->GetMeExpr()->GetOpnd(1)); + // set compareOpnd to be the scalar operand that is common to + // workCand->theMeExpr and realOcc->meExpr + ScalarMeExpr *compareOpnd = nullptr; uint32 scalarOpndNo = 0; - if (scalarOpnd == nullptr) { - scalarOpnd = static_cast(workCand->GetTheMeExpr()->GetOpnd(1)); - scalarOpndNo = 1; + if (scalarOpnd0) { + if (compareOpnd0 && scalarOpnd0->GetOst() == compareOpnd0->GetOst()) { + compareOpnd = compareOpnd0; + scalarOpndNo = 0; + } else if (compareOpnd1 && scalarOpnd0->GetOst() == compareOpnd1->GetOst()) { + compareOpnd = compareOpnd1; + scalarOpndNo = 0; + } } - ScalarMeExpr *compareOpnd = nullptr; - MeExpr *opnd0 = realOcc->GetMeExpr()->GetOpnd(0); - MeExpr *opnd1 = realOcc->GetMeExpr()->GetOpnd(1); - if ((opnd0->GetMeOp() == kMeOpVar || opnd0->GetMeOp() == kMeOpReg) && - (static_cast(opnd0)->GetOst() == scalarOpnd->GetOst())) { - compareOpnd = static_cast(opnd0); - } else if ((opnd1->GetMeOp() == kMeOpVar || opnd1->GetMeOp() == kMeOpReg) && - (static_cast(opnd1)->GetOst() == scalarOpnd->GetOst())) { - compareOpnd = static_cast(opnd1); + if (scalarOpnd1) { + if (compareOpnd0 && scalarOpnd1->GetOst() == compareOpnd0->GetOst()) { + compareOpnd = compareOpnd0; + scalarOpndNo = 1; + } else if (compareOpnd1 && scalarOpnd1->GetOst() == compareOpnd1->GetOst()) { + compareOpnd = compareOpnd1; + scalarOpndNo = 1; + } } CHECK_FATAL(compareOpnd != nullptr, "Rename1: compOcc does not correspond to realOcc"); ScalarMeExpr *resolvedCompareOpnd = ResolveAllInjuringDefs(compareOpnd); @@ -1415,7 +1424,20 @@ MeRealOcc *SSAPre::CreateRealOcc(MeStmt &meStmt, int seqStmt, MeExpr &meExpr, bo } else if (strengthReduction && meExpr.StrengthReducible() && meStmt.GetBB()->GetAttributes(kBBAttrIsInLoop)) { wkCand->isSRCand = true; } - workList.push_front(wkCand); + // determine onlyInvariantOpnds flag + wkCand->onlyInvariantOpnds = true; + for (int i = 0; i < meExpr.GetNumOpnds(); i++) { + ScalarMeExpr *scalarOpnd = dynamic_cast(meExpr.GetOpnd(i)); + if (scalarOpnd != nullptr && scalarOpnd->GetOst()->GetVersionsIndices().size() > 1) { + wkCand->onlyInvariantOpnds = false; + break; + } + } + if (wkCand->onlyInvariantOpnds) { + workList.push_front(wkCand); + } else { + workList.push_back(wkCand); + } wkCand->AddRealOccAsLast(*newOcc, GetPUIdx()); // add to bucket at workcandHashTable[hashIdx] wkCand->SetNext(*preWorkCandHashTable.GetWorkcandFromIndex(hashIdx)); @@ -1732,6 +1754,12 @@ void SSAPre::ApplySSAPRE() { mirModule->GetOut() << "||||||| SSAPRE candidate " << cnt << " at worklist index " << workCand->GetIndex() << ": "; workCand->DumpCand(*irMap); + if (workCand->isSRCand) { + mirModule->GetOut() << " srCand"; + } + if (workCand->onlyInvariantOpnds) { + mirModule->GetOut() << " onlyInvairantOpnds"; + } mirModule->GetOut() << '\n'; } allOccs.clear(); -- Gitee From 0d3b2177bfa0bcf786bd2146a8aab2af6c324219 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Wed, 16 Jun 2021 18:09:36 -0700 Subject: [PATCH 5/5] make lftr handle more forms of comparisons --- .../maple_me/src/ssa_epre_for_lftr.cpp | 4 +- src/mapleall/maple_me/src/ssa_epre_for_sr.cpp | 145 +++++------------- 2 files changed, 44 insertions(+), 105 deletions(-) diff --git a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp index 785aa748a5..a440c124ed 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp @@ -91,9 +91,9 @@ OpMeExpr *SSAEPre::FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { } void SSAEPre::CreateCompOcc(MeStmt *meStmt, int seqStmt, OpMeExpr *compare, bool isRebuilt) { - if (compare->GetOpnd(0)->GetNumOpnds() > 0 || + if (compare->GetOpnd(0)->GetNumOpnds() > 0 && compare->GetOpnd(1)->GetNumOpnds() > 0) { - // both sides of compare must be leaf + // one side of compare must be leaf return; } if (!IsPrimitiveInteger(compare->GetPrimType())) { diff --git a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp index b34a85d240..0682d15434 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_sr.cpp @@ -101,24 +101,13 @@ void SSAEPre::SRSetNeedRepair(MeOccur *useocc, std::set *needRepairInj } } -static int64 GetIncreAmtAndRhsVar(MeExpr *x, VarMeExpr *&rhsvar) { +static int64 GetIncreAmtAndRhsScalar(MeExpr *x, ScalarMeExpr *&rhsScalar) { OpMeExpr *opexpr = static_cast(x); - CHECK_FATAL(opexpr->GetOpnd(0)->GetMeOp() == kMeOpVar, "GetIncreAmtAndRhsVar: cannot find var operand"); - CHECK_FATAL(opexpr->GetOpnd(1)->GetMeOp() == kMeOpConst, "GetIncreAmtAndRhsVar: cannot find constant inc/dec amount"); - rhsvar = static_cast(opexpr->GetOpnd(0)); + rhsScalar = dynamic_cast(opexpr->GetOpnd(0)); + CHECK_FATAL(rhsScalar != nullptr, "GetIncreAmtAndRhsScalar: cannot find scalar operand"); + CHECK_FATAL(opexpr->GetOpnd(1)->GetMeOp() == kMeOpConst, "GetIncreAmtAndRhsScalar: cannot find constant inc/dec amount"); MIRConst *constVal = static_cast(opexpr->GetOpnd(1))->GetConstVal(); - CHECK_FATAL(constVal->GetKind() == kConstInt, "GetIncreAmtAndRhsVar: unexpected constant type"); - int64 amt = static_cast(constVal)->GetValueUnderType(); - return (opexpr->GetOp() == OP_sub) ? -amt : amt; -} - -static int64 GetIncreAmtAndRhsReg(MeExpr *x, RegMeExpr *&rhsreg) { - OpMeExpr *opexpr = static_cast(x); - CHECK_FATAL(opexpr->GetOpnd(0)->GetMeOp() == kMeOpReg, "GetIncreAmtAndRhsReg: cannot find reg operand"); - CHECK_FATAL(opexpr->GetOpnd(1)->GetMeOp() == kMeOpConst, "GetIncreAmtAndRhsReg: cannot find constant inc/dec amount"); - rhsreg = static_cast(opexpr->GetOpnd(0)); - MIRConst *constVal = static_cast(opexpr->GetOpnd(1))->GetConstVal(); - CHECK_FATAL(constVal->GetKind() == kConstInt, "GetIncreAmtAndRhsReg: unexpected constant type"); + CHECK_FATAL(constVal->GetKind() == kConstInt, "GetIncreAmtAndRhsScalar: unexpected constant type"); int64 amt = static_cast(constVal)->GetValueUnderType(); return (opexpr->GetOp() == OP_sub) ? -amt : amt; } @@ -150,26 +139,13 @@ MeExpr* SSAEPre::InsertRepairStmt(MeExpr *temp, int64 increAmt, MeStmt *injuring } static MeExpr *FindLaterRepairedTemp(MeExpr *temp, MeStmt *injuringDef) { - if (temp->GetMeOp() == kMeOpReg) { - AssignMeStmt *rass = static_cast(injuringDef->GetNext()); - while (rass != nullptr) { - CHECK_FATAL(rass->GetOp() == OP_regassign && rass->isIncDecStmt, - "FindLaterRepairedTemp: failed to find repair statement"); - if (rass->GetLHS()->GetRegIdx() == static_cast(temp)->GetRegIdx()) { - return rass->GetLHS(); - } - rass = static_cast(rass->GetNext()); - } - } else { // kMeOpVar - DassignMeStmt *dass = static_cast(injuringDef->GetNext()); - while (dass != nullptr) { - CHECK_FATAL(dass->GetOp() == OP_dassign && dass->isIncDecStmt, - "FindLaterRepairedTemp: failed to find repair statement"); - if (dass->GetLHS()->GetOst() == static_cast(temp)->GetOst()) { - return dass->GetLHS(); - } - dass = static_cast(dass->GetNext()); + AssignMeStmt *ass = static_cast(injuringDef->GetNext()); + while (ass != nullptr) { + CHECK_FATAL(ass->isIncDecStmt, "FindLaterRepairedTemp: failed to find repair statement"); + if (ass->GetLHS()->GetOst() == static_cast(temp)->GetOst()) { + return ass->GetLHS(); } + ass = static_cast(ass->GetNext()); } CHECK_FATAL(false, "FindLaterRepairedTemp: failed to find repair statement"); return nullptr; @@ -180,76 +156,39 @@ MeExpr* SSAEPre::SRRepairOpndInjuries(MeExpr *curopnd, MeOccur *defocc, int32 i, std::set *needRepairInjuringDefs, std::set *repairedInjuringDefs) { MeExpr *repairedTemp = tempAtDef; - if (curopnd->GetMeOp() == kMeOpVar) { - VarMeExpr *varx = static_cast(curopnd); - DassignMeStmt *dass = static_cast(varx->GetDefStmt()); - CHECK_FATAL(dass->isIncDecStmt, "SRRepairOpndInjuries: not an inc/dec statement"); - MeStmt *latestInjuringDef = dass; - if (repairedInjuringDefs->count(dass) == 0) { - repairedInjuringDefs->insert(dass); - bool done = false; - int64 increAmt = 0; - VarMeExpr *rhsvar = nullptr; - do { - increAmt += GetIncreAmtAndRhsVar(dass->GetRHS(), rhsvar); - if (OpndInDefOcc(rhsvar, defocc, i)) { - done = true; - } else { - varx = rhsvar; - dass = static_cast(varx->GetDefStmt()); - CHECK_FATAL(dass->isIncDecStmt, "SRRepairOpndInjuries: not an inc/dec statement"); - done = needRepairInjuringDefs->count(dass) == 1; - if (done) { - if (repairedInjuringDefs->count(dass) == 0) { - repairedTemp = SRRepairOpndInjuries(varx, defocc, i, tempAtDef, needRepairInjuringDefs, - repairedInjuringDefs); - } - repairedTemp = FindLaterRepairedTemp(repairedTemp, dass); - } - } - } while (!done); - // generate the increment statement at latestInjuringDef - repairedTemp = InsertRepairStmt(repairedTemp, increAmt * workCand->GetTheMeExpr()->SRMultiplier(varx->GetOst()), - latestInjuringDef); - } else { - // find the last repair increment statement - repairedTemp = FindLaterRepairedTemp(repairedTemp, latestInjuringDef); - } - } else { // kMeOpReg - RegMeExpr *regx = static_cast(curopnd); - AssignMeStmt *rass = static_cast(regx->GetDefStmt()); - CHECK_FATAL(rass->isIncDecStmt, "SRRepairOpndInjuries: not an inc/dec statement"); - MeStmt *latestInjuringDef = rass; - if (repairedInjuringDefs->count(rass) == 0) { - repairedInjuringDefs->insert(rass); - bool done = false; - int64 increAmt = 0; - RegMeExpr *rhsreg = nullptr; - do { - increAmt += GetIncreAmtAndRhsReg(rass->GetRHS(), rhsreg); - if (OpndInDefOcc(rhsreg, defocc, i)) { - done = true; - } else { - regx = rhsreg; - rass = static_cast(regx->GetDefStmt()); - CHECK_FATAL(rass->isIncDecStmt, "SRRepairOpndInjuries: not an inc/dec statement"); - done = needRepairInjuringDefs->count(rass) == 1; - if (done) { - if (repairedInjuringDefs->count(rass) == 0) { - repairedTemp = SRRepairOpndInjuries(regx, defocc, i, tempAtDef, needRepairInjuringDefs, - repairedInjuringDefs); - } - repairedTemp = FindLaterRepairedTemp(repairedTemp, rass); + ScalarMeExpr *scalarx = static_cast(curopnd); + AssignMeStmt *ass = static_cast(scalarx->GetDefStmt()); + CHECK_FATAL(ass->isIncDecStmt, "SRRepairOpndInjuries: not an inc/dec statement"); + MeStmt *latestInjuringDef = ass; + if (repairedInjuringDefs->count(ass) == 0) { + repairedInjuringDefs->insert(ass); + bool done = false; + int64 increAmt = 0; + ScalarMeExpr *rhsScalar = nullptr; + do { + increAmt += GetIncreAmtAndRhsScalar(ass->GetRHS(), rhsScalar); + if (OpndInDefOcc(rhsScalar, defocc, i)) { + done = true; + } else { + scalarx = rhsScalar; + ass = static_cast(scalarx->GetDefStmt()); + CHECK_FATAL(ass->isIncDecStmt, "SRRepairOpndInjuries: not an inc/dec statement"); + done = needRepairInjuringDefs->count(ass) == 1; + if (done) { + if (repairedInjuringDefs->count(ass) == 0) { + repairedTemp = SRRepairOpndInjuries(scalarx, defocc, i, tempAtDef, needRepairInjuringDefs, + repairedInjuringDefs); } + repairedTemp = FindLaterRepairedTemp(repairedTemp, ass); } - } while (!done); - // generate the increment statement at latestInjuringDef - repairedTemp = InsertRepairStmt(repairedTemp, increAmt * workCand->GetTheMeExpr()->SRMultiplier(regx->GetOst()), - latestInjuringDef); - } else { - // find the last repair increment statement - repairedTemp = FindLaterRepairedTemp(repairedTemp, latestInjuringDef); - } + } + } while (!done); + // generate the increment statement at latestInjuringDef + repairedTemp = InsertRepairStmt(repairedTemp, increAmt * workCand->GetTheMeExpr()->SRMultiplier(scalarx->GetOst()), + latestInjuringDef); + } else { + // find the last repair increment statement + repairedTemp = FindLaterRepairedTemp(repairedTemp, latestInjuringDef); } return repairedTemp; } -- Gitee