diff --git a/src/mapleall/maple_me/include/me_option.h b/src/mapleall/maple_me/include/me_option.h index 5d06d3a0db12804865de20fb31698ab77eeac604..a9a854ff319210ea3ea0ef0d9ed6be52414f08fc 100644 --- a/src/mapleall/maple_me/include/me_option.h +++ b/src/mapleall/maple_me/include/me_option.h @@ -114,6 +114,7 @@ class MeOption : public MapleDriverOptionBase { static bool propIloadRefNonParm; static bool propAtPhi; static bool propDuringBuild; + static bool propWithInverse; static bool lpreSpeculate; static bool spillAtCatch; static bool optDirectCall; diff --git a/src/mapleall/maple_me/include/prop.h b/src/mapleall/maple_me/include/prop.h index 12ce985d51a36d509035144406d6ea36b06a4bc6..895db727ef402f0a67c3fdfe4fd69588f28f0dd3 100644 --- a/src/mapleall/maple_me/include/prop.h +++ b/src/mapleall/maple_me/include/prop.h @@ -24,6 +24,13 @@ #include "safe_ptr.h" namespace maple { + +enum Propagatability { + kPropNo, + kPropOnlyWithInverse, + kPropYes, +}; + class Prop { public: struct PropConfig { @@ -33,14 +40,15 @@ class Prop { bool propagateFinalIloadRef; bool propagateIloadRefNonParm; bool propagateAtPhi; + bool propagateWithInverse; }; Prop(IRMap&, Dominance&, MemPool&, uint32 bbvecsize, const PropConfig &config); virtual ~Prop() = default; MeExpr *CheckTruncation(MeExpr *lhs, MeExpr *rhs) const; - MeExpr &PropVar(VarMeExpr &varmeExpr, bool atParm, bool checkPhi) const; - MeExpr &PropReg(RegMeExpr ®meExpr, bool atParm) const; + MeExpr &PropVar(VarMeExpr &varmeExpr, bool atParm, bool checkPhi); + MeExpr &PropReg(RegMeExpr ®meExpr, bool atParm); MeExpr &PropIvar(IvarMeExpr &ivarMeExpr); void PropUpdateDef(MeExpr &meExpr); void PropUpdateChiListDef(const MapleMap &chiList); @@ -77,7 +85,11 @@ class Prop { const MapleVector *> &vstLiveStack) const; bool IvarIsFinalField(const IvarMeExpr &ivarMeExpr) const; bool CanBeReplacedByConst(MIRSymbol &symbol) const; - bool Propagatable(const MeExpr &expr, const BB &fromBB, bool atParm) const; + int32 InvertibleOccurrences(ScalarMeExpr *scalar, MeExpr *x); + bool IsFunctionOfCurVersion(ScalarMeExpr *scalar, ScalarMeExpr *cur); + Propagatability Propagatable(MeExpr *x, BB *fromBB, bool atParm, bool checkInverse = false, ScalarMeExpr *propagatingScalar = nullptr); + MeExpr *FormInverse(ScalarMeExpr *v, MeExpr *x, MeExpr *formingExp); + MeExpr *RehashUsingInverse(MeExpr *x); MeExpr &PropMeExpr(MeExpr &meExpr, bool &isproped, bool atParm); IRMap &irMap; diff --git a/src/mapleall/maple_me/src/me_option.cpp b/src/mapleall/maple_me/src/me_option.cpp index 9782e5e25ec9526d0912fb8ccd33ae4a0908dc0e..e7d658aba77cd5a26f785d3a9d9389e2159941cd 100644 --- a/src/mapleall/maple_me/src/me_option.cpp +++ b/src/mapleall/maple_me/src/me_option.cpp @@ -71,6 +71,7 @@ bool MeOption::rcLowering = true; bool MeOption::optDirectCall = false; bool MeOption::propAtPhi = true; bool MeOption::propDuringBuild = true; +bool MeOption::propWithInverse = false; bool MeOption::dseKeepRef = false; bool MeOption::decoupleStatic = false; bool MeOption::dumpBefore = false; @@ -192,6 +193,7 @@ enum OptionIndex { kProPatphi, kNoProPatphi, kPropDuringBuild, + kPropWithInverse, kOptInterfaceCall, kNoOptInterfaceCall, kOptVirtualCall, @@ -884,6 +886,16 @@ const Descriptor kUsage[] = { " --no-propduringbuild \tDisable propduringbuild\n", "me", {} }, + { kPropWithInverse, + kEnable, + "", + "propwithinverse", + kBuildTypeExperimental, + kArgCheckPolicyBool, + " --propwithinverse \tEnable copy propagation across statements with inverse functions" + " --no-propwithinverse \tDisable copy propagation across statements with inverse functions\n", + "me", + {} }, { kMeNativeOpt, kEnable, "", @@ -1354,6 +1366,9 @@ bool MeOption::SolveOptions(const std::vector &opts, bool i case kPropDuringBuild: propDuringBuild = (opt.Type() == kEnable); break; + case kPropWithInverse: + propWithInverse = (opt.Type() == kEnable); + break; case kMeNativeOpt: nativeOpt = (opt.Type() == kEnable); break; diff --git a/src/mapleall/maple_me/src/me_prop.cpp b/src/mapleall/maple_me/src/me_prop.cpp index a187fb52d94c9370ae2b23c3e5231213baa7e866..8d49a4967d5e0a3f58d1b3cf6ed1fc39d3967b96 100644 --- a/src/mapleall/maple_me/src/me_prop.cpp +++ b/src/mapleall/maple_me/src/me_prop.cpp @@ -50,7 +50,7 @@ AnalysisResult *MeDoMeProp::Run(MeFunction *func, MeFuncResultMgr *m, ModuleResu } } MeProp meProp(*hMap, *dom, *NewMemPool(), Prop::PropConfig { MeOption::propBase, propIloadRef, - MeOption::propGlobalRef, MeOption::propFinaliLoadRef, MeOption::propIloadRefNonParm, MeOption::propAtPhi }); + MeOption::propGlobalRef, MeOption::propFinaliLoadRef, MeOption::propIloadRefNonParm, MeOption::propAtPhi, MeOption::propWithInverse }); meProp.TraversalBB(*func->GetCfg()->GetCommonEntryBB()); if (DEBUGFUNC(func)) { LogInfo::MapleLogger() << "\n============== After Copy Propagation =============" << '\n'; diff --git a/src/mapleall/maple_me/src/prop.cpp b/src/mapleall/maple_me/src/prop.cpp index 3c98e49532a0ce9a88003b6f880f6cd92d250730..b76df23b6d721dd20312da24a4e1334246b6b8b0 100644 --- a/src/mapleall/maple_me/src/prop.cpp +++ b/src/mapleall/maple_me/src/prop.cpp @@ -142,103 +142,364 @@ bool Prop::IvarIsFinalField(const IvarMeExpr &ivarMeExpr) const { return structType->IsFieldFinal(fieldID) && !structType->IsFieldRCUnownedRef(fieldID); } -// check if the expression x can be legally forward-substitute the variable that -// it was assigned to; x is from bb -bool Prop::Propagatable(const MeExpr &expr, const BB &fromBB, bool atParm) const { - MeExprOp meOp = expr.GetMeOp(); +// if x contains operations that has no accurate inverse, return -1; also return +// -1 if x contains any scalar other than x that is not current version; +// otherwise, the return value is the number of occurrences of scalar. +int32 Prop::InvertibleOccurrences(ScalarMeExpr *scalar, MeExpr *x) { + switch (x->GetMeOp()) { + case kMeOpConst: return 0; + case kMeOpReg: { + RegMeExpr *regreadx = static_cast(x); + if (regreadx->GetRegIdx() < 0) { + return -1; + } + } + // fall thru + case kMeOpVar: + if (x == scalar) { + return 1; + } + if (Propagatable(x, nullptr, false, false, nullptr) == kPropYes) { + return 0; + } + return -1; + case kMeOpOp: + if (!IsPrimitiveInteger(x->GetPrimType())) { + return -1; + } + if (x->GetOp() == OP_neg) { + return InvertibleOccurrences(scalar, x->GetOpnd(0)); + } + if (x->GetOp() == OP_add || x->GetOp() == OP_sub) { + int32 invertibleOccs0 = InvertibleOccurrences(scalar, x->GetOpnd(0)); + if (invertibleOccs0 == -1) { + return -1; + } + int32 invertibleOccs1 = InvertibleOccurrences(scalar, x->GetOpnd(1)); + if (invertibleOccs1 == -1 || (invertibleOccs0 + invertibleOccs1 > 1)) { + return -1; + } + return invertibleOccs0 + invertibleOccs1; + } + // fall thru + default: return -1; + } +} + +// return true if scalar can be expressed as a function of current version cur +bool Prop::IsFunctionOfCurVersion(ScalarMeExpr *scalar, ScalarMeExpr *cur) { + if (!config.propagateWithInverse) { + return false; + } + if (cur == nullptr || cur->GetDefBy() != kDefByStmt) { + return false; + } + AssignMeStmt *ass = static_cast(cur->GetDefStmt()); + return InvertibleOccurrences(scalar, ass->GetRHS()) == 1; +} + +// check if the expression x can legally forward-substitute the variable that it +// was assigned to; x is from bb; if checkInverse is true and there is live range +// overlap for a scalar within x, do the additional check of whether the scalar's +// previous version can be expressed in terms of its current version. +// propagatingScalar is used only if checkInverse is true; it gives the +// propagating scalar so we can avoid doing the checkInverse checking for it. +Propagatability Prop::Propagatable(MeExpr *x, BB *fromBB, bool atParm, bool checkInverse, ScalarMeExpr *propagatingScalar) { + MeExprOp meOp = x->GetMeOp(); switch (meOp) { + case kMeOpAddrof: + case kMeOpAddroffunc: + case kMeOpAddroflabel: + case kMeOpConst: + case kMeOpSizeoftype: + return kPropYes; case kMeOpGcmalloc: - return false; + return kPropNo; case kMeOpNary: { - if (expr.GetOp() == OP_intrinsicop || expr.GetOp() == OP_intrinsicopwithtype) { - return false; + if (x->GetOp() == OP_intrinsicop || x->GetOp() == OP_intrinsicopwithtype) { + return kPropNo; + } + NaryMeExpr *narymeexpr = static_cast(x); + Propagatability propmin = kPropYes; + for (uint32 i = 0; i < narymeexpr->GetNumOpnds(); i++) { + Propagatability prop = Propagatable(narymeexpr->GetOpnd(i), fromBB, false, checkInverse, propagatingScalar); + if (prop == kPropNo) { + return kPropNo; + } + propmin = std::min(propmin, prop); } - break; + return propmin; } case kMeOpReg: { - auto ®Read = static_cast(expr); - if (regRead.GetRegIdx() < 0) { - return false; + RegMeExpr *regRead = static_cast(x); + if (regRead->GetRegIdx() < 0) { + return kPropNo; } // get the current definition version std::vector regReadVec; - CollectSubVarMeExpr(expr, regReadVec); - if (!IsVersionConsistent(regReadVec, vstLiveStackVec)) { - return false; + CollectSubVarMeExpr(*x, regReadVec); + if (IsVersionConsistent(regReadVec, vstLiveStackVec)) { + return kPropYes; + } else if (checkInverse && regRead->GetOst() != propagatingScalar->GetOst()) { + MapleStack *pstack = vstLiveStackVec[regRead->GetOst()->GetIndex()]; + return IsFunctionOfCurVersion(regRead, static_cast(pstack->top())) ? kPropOnlyWithInverse : kPropNo; + } else { + return kPropNo; } - break; } case kMeOpVar: { - auto &varMeExpr = static_cast(expr); - if (varMeExpr.IsVolatile()) { - return false; + VarMeExpr *varMeExpr = static_cast(x); + if (varMeExpr->IsVolatile()) { + return kPropNo; } - const MIRSymbol *st = varMeExpr.GetOst()->GetMIRSymbol(); + const MIRSymbol *st = varMeExpr->GetOst()->GetMIRSymbol(); if (!config.propagateGlobalRef && st->IsGlobal() && !st->IsFinal() && !st->IgnoreRC()) { - return false; + return kPropNo; } - if (LocalToDifferentPU(st->GetStIdx(), fromBB)) { - return false; + if (LocalToDifferentPU(st->GetStIdx(), *fromBB)) { + return kPropNo; } - if (varMeExpr.GetDefBy() == kDefByMustDef && varMeExpr.GetType()->GetPrimType() == PTY_agg) { - return false; // keep temps for storing call return values single use + if (varMeExpr->GetDefBy() == kDefByMustDef && varMeExpr->GetType()->GetPrimType() == PTY_agg) { + return kPropNo; // keep temps for storing call return values single use } // get the current definition version std::vector varMeExprVec; - CollectSubVarMeExpr(expr, varMeExprVec); - if (!IsVersionConsistent(varMeExprVec, vstLiveStackVec)) { - return false; + CollectSubVarMeExpr(*x, varMeExprVec); + if (IsVersionConsistent(varMeExprVec, vstLiveStackVec)) { + return kPropYes; + } else if (checkInverse && varMeExpr->GetOst() != propagatingScalar->GetOst() && + varMeExpr->GetType()->GetKind() != kTypeBitField) { + MapleStack *pstack = vstLiveStackVec[varMeExpr->GetOst()->GetIndex()]; + return IsFunctionOfCurVersion(varMeExpr, static_cast(pstack->top())) ? kPropOnlyWithInverse : kPropNo; + } else { + return kPropNo; } - break; } case kMeOpIvar: { - auto &ivarMeExpr = static_cast(expr); - if (!IvarIsFinalField(ivarMeExpr) && - !GetTypeFromTyIdx(ivarMeExpr.GetTyIdx()).PointsToConstString()) { + IvarMeExpr *ivarMeExpr = static_cast(x); + if (!IvarIsFinalField(*ivarMeExpr) && + !GetTypeFromTyIdx(ivarMeExpr->GetTyIdx()).PointsToConstString()) { if ((!config.propagateIloadRef || (config.propagateIloadRefNonParm && atParm)) && - ivarMeExpr.GetPrimType() == PTY_ref) { - return false; + ivarMeExpr->GetPrimType() == PTY_ref) { + return kPropNo; } } ASSERT_NOT_NULL(curBB); - if (fromBB.GetAttributes(kBBAttrIsTry) && !curBB->GetAttributes(kBBAttrIsTry)) { - return false; + if (fromBB->GetAttributes(kBBAttrIsTry) && !curBB->GetAttributes(kBBAttrIsTry)) { + return kPropNo; } - if (ivarMeExpr.IsVolatile() || ivarMeExpr.IsRCWeak()) { - return false; + if (ivarMeExpr->IsVolatile() || ivarMeExpr->IsRCWeak()) { + return kPropNo; + } + Propagatability prop0 = Propagatable(ivarMeExpr->GetBase(), fromBB, false, false, nullptr); + if (prop0 == kPropNo) { + return kPropNo; } // get the current definition version std::vector varMeExprVec; - CollectSubVarMeExpr(expr, varMeExprVec); - if (!IsVersionConsistent(varMeExprVec, vstLiveStackVec)) { - return false; - } - break; + CollectSubVarMeExpr(*x, varMeExprVec); + return IsVersionConsistent(varMeExprVec, vstLiveStackVec) ? prop0 : kPropNo; } case kMeOpOp: { - if (kOpcodeInfo.NotPure(expr.GetOp())) { - return false; + if (kOpcodeInfo.NotPure(x->GetOp())) { + return kPropNo; } - break; + if (x->GetOp() == OP_gcmallocjarray) { + return kPropNo; + } + OpMeExpr *meopexpr = static_cast(x); + MeExpr *opnd0 = meopexpr->GetOpnd(0); + Propagatability prop0 = Propagatable(opnd0, fromBB, false, checkInverse, propagatingScalar); + if (prop0 == kPropNo) { + return kPropNo; + } + MeExpr *opnd1 = meopexpr->GetOpnd(1); + if (!opnd1) { + return prop0; + } + Propagatability prop1 = Propagatable(opnd1, fromBB, false, checkInverse, propagatingScalar); + if (prop1 == kPropNo) { + return kPropNo; + } + prop1 = std::min(prop0, prop1); + MeExpr *opnd2 = meopexpr->GetOpnd(2); + if (!opnd2) { + return prop1; + } + Propagatability prop2 = Propagatable(opnd2, fromBB, false, checkInverse, propagatingScalar); + return std::min(prop1, prop2); } case kMeOpConststr: case kMeOpConststr16: { if (mirModule.IsCModule()) { - return false; + return kPropNo; } - break; + return kPropYes; } default: - break; + CHECK_FATAL(false, "MeProp::Propagatable() NYI"); + return kPropNo; } +} - for (size_t i = 0; i < expr.GetNumOpnds(); ++i) { - if (!Propagatable(utils::ToRef(expr.GetOpnd(i)), fromBB, false)) { - return false; +// Expression x contains v; form and return the inverse of this expression based +// on the current version of v by descending x; formingExp is the tree being +// constructed during the descent; x must contain one and only one occurrence of +// v; work is done when it reaches the v node inside x. +MeExpr *Prop::FormInverse(ScalarMeExpr *v, MeExpr *x, MeExpr *formingExp) { + MeExpr *newx = nullptr; + switch (x->GetMeOp()) { + case kMeOpVar: + case kMeOpReg: + if (x == v) { + return formingExp; + }; + return x; + case kMeOpOp: { + OpMeExpr *opx = static_cast(x); + if (opx->GetOp() == OP_neg) { // negate formingExp and recurse down + OpMeExpr negx(-1, OP_neg, opx->GetPrimType(), 1); + negx.SetOpnd(0, formingExp); + newx = irMap.HashMeExpr(negx); + return FormInverse(v, opx->GetOpnd(0), newx); + } + if (opx->GetOp() == OP_add) { // 2 patterns depending on which side contains v + OpMeExpr subx(-1, OP_sub, opx->GetPrimType(), 2); + subx.SetOpnd(0, formingExp); + if (InvertibleOccurrences(v, opx->GetOpnd(0)) == 0) { + // ( ..i2.. ) = y + ( ..i1.. ) becomes ( ..i2.. ) - y = ( ..i1.. ) + // form formingExp - opx->GetOpnd(0) + subx.SetOpnd(1, opx->GetOpnd(0)); + newx = irMap.HashMeExpr(subx); + return FormInverse(v, opx->GetOpnd(1), newx); + } else { + // ( ..i2.. ) = ( ..i1.. ) + y becomes ( ..i2.. ) - y = ( ..i1.. ) + // form formingExp - opx->GetOpnd(1) + subx.SetOpnd(1, opx->GetOpnd(1)); + newx = irMap.HashMeExpr(subx); + return FormInverse(v, opx->GetOpnd(0), newx); + } + } + if (opx->GetOp() == OP_sub) { + if (InvertibleOccurrences(v, opx->GetOpnd(0)) == 0) { + // ( ..i2.. ) = y - ( ..i1.. ) becomes y - ( ..i2.. ) = ( ..i1.. ) + // form opx->GetOpnd(0) - formingExp + OpMeExpr subx(-1, OP_sub, opx->GetPrimType(), 2); + subx.SetOpnd(0, opx->GetOpnd(0)); + subx.SetOpnd(1, formingExp); + newx = irMap.HashMeExpr(subx); + return FormInverse(v, opx->GetOpnd(1), newx); + } else { + // ( ..i2.. ) = ( ..i1.. ) - y becomes ( ..i2.. ) + y = ( ..i1.. ) + // form formingExp + opx->GetOpnd(1) + OpMeExpr addx(-1, OP_add, opx->GetPrimType(), 2); + addx.SetOpnd(0, formingExp); + addx.SetOpnd(1, opx->GetOpnd(1)); + newx = irMap.HashMeExpr(addx); + return FormInverse(v, opx->GetOpnd(0), newx); + } } + // fall-thru } + default: CHECK_FATAL(false, "FormInverse: should not see these nodes"); + } +} - return true; +// recurse down the expression tree x; at the scalar whose version is different +// from the current version, replace it by an expression corresponding to the +// inverse of how its current version is computed from it; if there is no change +// return NULL; if there is change, rehash on the way back +MeExpr *Prop::RehashUsingInverse(MeExpr *x) { + switch (x->GetMeOp()) { + case kMeOpVar: + case kMeOpReg: { + ScalarMeExpr *scalar = static_cast(x); + MapleStack *pstack = vstLiveStackVec[scalar->GetOst()->GetIndex()]; + if (pstack == nullptr || pstack->empty() || pstack->top() == scalar) { + return nullptr; + } + ScalarMeExpr *curScalar = static_cast(pstack->top()); + return FormInverse(scalar, curScalar->GetDefStmt()->GetRHS(), curScalar); + } + case kMeOpIvar: { + IvarMeExpr *ivarx = static_cast(x); + MeExpr *result = RehashUsingInverse(ivarx->GetBase()); + if (result != nullptr) { + IvarMeExpr newivarx(-1, ivarx->GetPrimType(), ivarx->GetTyIdx(), ivarx->GetFieldID()); + newivarx.SetBase(result); + newivarx.SetMuVal(ivarx->GetMu()); + return irMap.HashMeExpr(newivarx); + } + return nullptr; + } + case kMeOpOp: { + OpMeExpr *opx = static_cast(x); + MeExpr *res0 = RehashUsingInverse(opx->GetOpnd(0)); + MeExpr *res1 = nullptr; + MeExpr *res2 = nullptr; + if (opx->GetNumOpnds() > 1) { + res1 = RehashUsingInverse(opx->GetOpnd(1)); + if (opx->GetNumOpnds() > 2) { + res2 = RehashUsingInverse(opx->GetOpnd(2)); + } + } + if (res0 == nullptr && res1 == nullptr && res2 == nullptr) { + return nullptr; + } + OpMeExpr newopx(-1, opx->GetOp(), opx->GetPrimType(), opx->GetNumOpnds()); + newopx.SetOpndType(opx->GetOpndType()); + newopx.SetBitsOffSet(opx->GetBitsOffSet()); + newopx.SetBitsSize(opx->GetBitsSize()); + newopx.SetTyIdx(opx->GetTyIdx()); + newopx.SetFieldID(opx->GetFieldID()); + if (res0) { + newopx.SetOpnd(0, res0); + } else { + newopx.SetOpnd(0, opx->GetOpnd(0)); + } + if (opx->GetNumOpnds() > 1) { + if (res1) { + newopx.SetOpnd(1, res1); + } else { + newopx.SetOpnd(1, opx->GetOpnd(1)); + } + if (opx->GetNumOpnds() > 2) { + if (res1) { + newopx.SetOpnd(2, res2); + } else { + newopx.SetOpnd(2, opx->GetOpnd(2)); + } + } + } + return irMap.HashMeExpr(newopx); + } + case kMeOpNary: { + NaryMeExpr *naryx = static_cast(x); + std::vector results(naryx->GetNumOpnds(), nullptr); + bool needRehash = false; + uint32 i; + for (i = 0; i < naryx->GetNumOpnds(); i++) { + results[i] = RehashUsingInverse(naryx->GetOpnd(i)); + if (results[i] != nullptr) { + needRehash = true; + } + } + if (!needRehash) { + return nullptr; + } + NaryMeExpr newnaryx(&propMapAlloc, -1, naryx->GetOp(), naryx->GetPrimType(), + naryx->GetNumOpnds(), naryx->GetTyIdx(), naryx->GetIntrinsic(), naryx->GetBoundCheck()); + for (i = 0; i < naryx->GetNumOpnds(); i++) { + if (results[i] != nullptr) { + newnaryx.SetOpnd(i, results[i]); + } else { + newnaryx.SetOpnd(i, naryx->GetOpnd(i)); + } + } + return irMap.HashMeExpr(newnaryx); + } + default: return nullptr; + } } // if lhs is smaller than rhs, insert operation to simulate the truncation @@ -338,7 +599,7 @@ MeExpr *Prop::CheckTruncation(MeExpr *lhs, MeExpr *rhs) const { } // return varMeExpr itself if no propagation opportunity -MeExpr &Prop::PropVar(VarMeExpr &varMeExpr, bool atParm, bool checkPhi) const { +MeExpr &Prop::PropVar(VarMeExpr &varMeExpr, bool atParm, bool checkPhi) { const MIRSymbol *st = varMeExpr.GetOst()->GetMIRSymbol(); if (st->IsInstrumented() || varMeExpr.IsVolatile()) { return varMeExpr; @@ -348,14 +609,19 @@ MeExpr &Prop::PropVar(VarMeExpr &varMeExpr, bool atParm, bool checkPhi) const { DassignMeStmt *defStmt = static_cast(varMeExpr.GetDefStmt()); ASSERT(defStmt != nullptr, "dynamic cast result is nullptr"); MeExpr *rhs = defStmt->GetRHS(); - if (rhs->GetDepth() <= kPropTreeLevel && - Propagatable(utils::ToRef(rhs), utils::ToRef(defStmt->GetBB()), atParm)) { + if (rhs->GetDepth() > kPropTreeLevel) { + return varMeExpr; + } + Propagatability propagatable = Propagatable(rhs, defStmt->GetBB(), atParm, true, &varMeExpr); + if (propagatable != kPropNo) { // mark propagated for iread ref if (rhs->GetMeOp() == kMeOpIvar && rhs->GetPrimType() == PTY_ref) { defStmt->SetPropagated(true); } - rhs = CheckTruncation(&varMeExpr, rhs); - return utils::ToRef(rhs); + if (propagatable == kPropOnlyWithInverse) { + rhs = RehashUsingInverse(rhs); + } + return *CheckTruncation(&varMeExpr, rhs); } else { return varMeExpr; } @@ -383,11 +649,18 @@ MeExpr &Prop::PropVar(VarMeExpr &varMeExpr, bool atParm, bool checkPhi) const { return varMeExpr; } -MeExpr &Prop::PropReg(RegMeExpr ®MeExpr, bool atParm) const { +MeExpr &Prop::PropReg(RegMeExpr ®MeExpr, bool atParm) { if (regMeExpr.GetDefBy() == kDefByStmt) { AssignMeStmt *defStmt = static_cast(regMeExpr.GetDefStmt()); MeExpr &rhs = utils::ToRef(defStmt->GetRHS()); - if (rhs.GetDepth() <= kPropTreeLevel && Propagatable(rhs, utils::ToRef(defStmt->GetBB()), atParm)) { + if (rhs.GetDepth() <= kPropTreeLevel) { + return regMeExpr; + } + Propagatability propagatable = Propagatable(&rhs, defStmt->GetBB(), atParm, true, ®MeExpr); + if (propagatable != kPropNo) { + if (propagatable == kPropOnlyWithInverse) { + rhs = *RehashUsingInverse(&rhs); + } return rhs; } } @@ -400,8 +673,8 @@ MeExpr &Prop::PropIvar(IvarMeExpr &ivarMeExpr) { return ivarMeExpr; } MeExpr &rhs = utils::ToRef(defStmt->GetRHS()); - if (rhs.GetDepth() <= kPropTreeLevel && Propagatable(rhs, utils::ToRef(defStmt->GetBB()), false)) { - return rhs; + if (rhs.GetDepth() <= kPropTreeLevel && Propagatable(&rhs, defStmt->GetBB(), false) != kPropNo) { + return *CheckTruncation(&ivarMeExpr, &rhs); } if (mirModule.IsCModule() && ivarMeExpr.GetPrimType() != PTY_agg) { auto *tmpReg = irMap.CreateRegMeExpr(ivarMeExpr); 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 3a1e1c16f9998d3d82ccdf34d9fa54d6594558ee..192602aba5fa5b01a89799e6ba0981c15deba3c6 100644 --- a/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp +++ b/src/mapleall/maple_me/src/ssa_epre_for_lftr.cpp @@ -84,7 +84,7 @@ OpMeExpr *SSAEPre::FormLFTRCompare(MeRealOcc *compOcc, MeExpr *regorvar) { BuildWorkListExpr(*compOcc->GetMeStmt(), compOcc->GetSequence(), *hashedSide, isRebuild, nullptr, true); } OpMeExpr newcompare(-1, compare->GetOp(), compare->GetPrimType(), 2); - newcompare.SetOpndType(static_cast(compare)->GetOpndType()); + newcompare.SetOpndType(regorvar->GetPrimType()); newcompare.SetOpnd(j, regorvar); newcompare.SetOpnd(1-j, hashedSide); return static_cast(irMap->HashMeExpr(newcompare));