From 4439c12fc6a26f2f773db24558ad6362b81d1bb0 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Sat, 16 Oct 2021 08:52:01 -0700 Subject: [PATCH] Implemented CheckReductionLoop() that determines if a doloop is a reduction loop --- src/mapleall/maple_me/include/lfo_dep_test.h | 2 + src/mapleall/maple_me/src/lfo_dep_test.cpp | 112 ++++++++++++++++++- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/mapleall/maple_me/include/lfo_dep_test.h b/src/mapleall/maple_me/include/lfo_dep_test.h index 52b712ee83..eaf992ef7a 100644 --- a/src/mapleall/maple_me/include/lfo_dep_test.h +++ b/src/mapleall/maple_me/include/lfo_dep_test.h @@ -89,6 +89,7 @@ class DoloopInfo { flowDepTestList(alloc->Adapter()) {} ~DoloopInfo() = default; bool IsLoopInvariant(MeExpr *x); + bool OnlyInvariantScalars(MeExpr *x); SubscriptDesc *BuildOneSubscriptDesc(BaseNode *subsX); ArrayAccessDesc *BuildOneArrayAccessDesc(ArrayNode *arr, BaseNode *parent); void CreateRHSArrayAccessDesc(BaseNode *x, BaseNode *parent); @@ -96,6 +97,7 @@ class DoloopInfo { void CreateDepTestLists(); void TestDependences(MapleVector *depTestList, bool bothLHS); bool Parallelizable(); + bool CheckReductionLoop(); ArrayAccessDesc* GetArrayAccessDesc(ArrayNode *node, bool isRHS); }; diff --git a/src/mapleall/maple_me/src/lfo_dep_test.cpp b/src/mapleall/maple_me/src/lfo_dep_test.cpp index 8441fe9c7e..01702f76e7 100644 --- a/src/mapleall/maple_me/src/lfo_dep_test.cpp +++ b/src/mapleall/maple_me/src/lfo_dep_test.cpp @@ -128,6 +128,55 @@ bool DoloopInfo::IsLoopInvariant(MeExpr *x) { return false; } +// check if all the scalars contained in x are loop-invariant unless it is IV +bool DoloopInfo::OnlyInvariantScalars(MeExpr *x) { + if (x == nullptr) { + return true; + } + switch (x->GetMeOp()) { + case kMeOpAddrof: + case kMeOpAddroffunc: + case kMeOpConst: + case kMeOpConststr: + case kMeOpConststr16: + case kMeOpSizeoftype: + case kMeOpFieldsDist: return true; + case kMeOpVar: { + VarMeExpr *varx = static_cast(x); + if (varx->GetOst()->GetMIRSymbol()->GetStIdx() == doloop->GetDoVarStIdx()) { + return true; // it is the IV + } + // fall thru + } + case kMeOpReg: { + ScalarMeExpr *scalar = static_cast(x); + BB *defBB = scalar->DefByBB(); + return defBB == nullptr || (defBB != doloopBB && depInfo->dom->Dominate(*defBB, *doloopBB)); + } + case kMeOpIvar: { + return OnlyInvariantScalars(x->GetOpnd(0)); + } + case kMeOpOp: { + OpMeExpr *opexp = static_cast(x); + return OnlyInvariantScalars(opexp->GetOpnd(0)) && + OnlyInvariantScalars(opexp->GetOpnd(1)) && + OnlyInvariantScalars(opexp->GetOpnd(2)); + } + case kMeOpNary: { + NaryMeExpr *opexp = static_cast(x); + for (uint32 i = 0; i < opexp->GetNumOpnds(); i++) { + if (!OnlyInvariantScalars(opexp->GetOpnd(i))) { + return false; + } + } + return true; + } + default: + break; + } + return false; +} + SubscriptDesc *DoloopInfo::BuildOneSubscriptDesc(BaseNode *subsX) { MeExpr *meExpr = depInfo->preEmit->GetMexpr(subsX); SubscriptDesc *subsDesc = alloc->GetMemPool()->New(meExpr); @@ -213,7 +262,7 @@ ArrayAccessDesc *DoloopInfo::BuildOneArrayAccessDesc(ArrayNode *arr, BaseNode *p hasPtrAccess = true; return nullptr; } - // determine arrayOst + // determine arryOst IvarMeExpr *ivarMeExpr = nullptr; OriginalSt *arryOst = nullptr; if (parent->op == OP_iread) { @@ -434,6 +483,64 @@ bool DoloopInfo::Parallelizable() { return true; } +static bool IsDreadOf(BaseNode *x, StIdx stIdx, FieldID fieldID) { + if (x->op != OP_dread) { + return false; + } + DreadNode *dread = static_cast(x); + return dread->GetStIdx() == stIdx && dread->GetFieldID() == fieldID; +} + +bool DoloopInfo::CheckReductionLoop() { + if (hasPtrAccess || hasOtherCtrlFlow || !hasScalarAssign || hasMayDef) { + return false; + } + if (!lhsArrays.empty()) { + return false; + } + // make sure all rhsArrays are either loopInvariant or not messy + for (int i = 0; i < rhsArrays.size(); i++) { + ArrayAccessDesc *arrAcc = rhsArrays[i]; + for (int j = 0; j < arrAcc->subscriptVec.size(); j++) { + SubscriptDesc *subs = arrAcc->subscriptVec[j]; + if (!subs->loopInvariant && subs->tooMessy) { + return false; + } + } + } + // go thru all statements in loop body to check reduction form in scalar assignments + StmtNode *stmt = doloop->GetDoBody()->GetFirst(); + while (stmt) { + if (stmt->op != OP_dassign) { + return false; + } + DassignNode *dass = static_cast(stmt); + BaseNode *rhs = dass->GetRHS(); + if (rhs->GetOpCode() != OP_add && rhs->GetOpCode() != OP_sub) { + return false; + } + StIdx stIdx = dass->GetStIdx(); + FieldID fieldID = dass->GetFieldID(); + BinaryNode *binrhs = static_cast(rhs); + BaseNode *otherOpnd = nullptr; + if (IsDreadOf(binrhs->GetBOpnd(0), stIdx, fieldID)) { + otherOpnd = binrhs->GetBOpnd(1); + } else if (binrhs->GetOpCode() == OP_add && IsDreadOf(binrhs->GetBOpnd(1), stIdx, fieldID)) { + otherOpnd = binrhs->GetBOpnd(0); + // swap the 2 sides + binrhs->SetBOpnd(binrhs->GetBOpnd(1), 0); + binrhs->SetBOpnd(otherOpnd, 1); + } else { + return false; + } + if (!OnlyInvariantScalars(depInfo->preEmit->GetMexpr(otherOpnd))) { + return false; + } + stmt = stmt->GetNext(); + } + return true; +} + ArrayAccessDesc* DoloopInfo::GetArrayAccessDesc(ArrayNode *node, bool isRHS) { MapleVector* arrayDescptr = isRHS ? &rhsArrays : &lhsArrays; for (auto it = arrayDescptr->begin(); it != arrayDescptr->end(); it++) { @@ -549,6 +656,9 @@ void LfoDepInfo::PerformDepTest() { if (doloopInfo->Parallelizable()) { LogInfo::MapleLogger() << "LOOP CAN BE VECTORIZED\n"; } + if (doloopInfo->CheckReductionLoop()) { + LogInfo::MapleLogger() << "LOOP IS REDUCTION LOOP\n"; + } } } } -- Gitee