diff --git a/src/mapleall/maple_driver/defs/phases.def b/src/mapleall/maple_driver/defs/phases.def index cd56a454402a44ee8c7045306852af4689a7945b..9db9b21400b64143e4651792ab5035b8083e30a7 100644 --- a/src/mapleall/maple_driver/defs/phases.def +++ b/src/mapleall/maple_driver/defs/phases.def @@ -24,6 +24,8 @@ ADD_PHASE("gencheckcast", JAVALANG) ADD_PHASE("javaintrnlowering", JAVALANG) ADD_PHASE("inline", Options::O2 && Options::useInline) // mephase begin +ADD_PHASE("mecfgbuild", CLANG && MeOption::optLevel >= 3) +ADD_PHASE("injectiv", CLANG && MeOption::optLevel >= 3) ADD_PHASE("mecfgbuild", MeOption::optLevel >= 2 || JAVALANG) ADD_PHASE("bypatheh", JAVALANG && MeOption::optLevel >= 2) ADD_PHASE("loopcanon", MeOption::optLevel >= 2) diff --git a/src/mapleall/maple_ir/include/mir_lower.h b/src/mapleall/maple_ir/include/mir_lower.h index fb7969347caa39115d249af61c62613d89b4a14a..039c3402315ea3ceea940d73efaa356803f41a75 100644 --- a/src/mapleall/maple_ir/include/mir_lower.h +++ b/src/mapleall/maple_ir/include/mir_lower.h @@ -116,9 +116,9 @@ class MIRLower { } static bool ShouldOptArrayMrt(const MIRFunction &func); - - private: + protected: MIRModule &mirModule; + private: MIRFunction *mirFunc; MIRBuilder *mirBuilder = nullptr; uint32 lowerPhase = 0; diff --git a/src/mapleall/maple_me/BUILD.gn b/src/mapleall/maple_me/BUILD.gn index 73bbf1403a6793585af1916953f497cd63d7a4c0..9e6567c90f34981ae41a62a811fa187e1f31f7a2 100755 --- a/src/mapleall/maple_me/BUILD.gn +++ b/src/mapleall/maple_me/BUILD.gn @@ -90,6 +90,8 @@ src_libmplme = [ "src/me_func_opt.cpp", "src/me_verify.cpp", "src/me_fsaa.cpp", + "src/lfo_mir_lower.cpp", + "src/lfo_inject_iv.cpp", ] src_libmplmewpo = [ diff --git a/src/mapleall/maple_me/include/lfo_function.h b/src/mapleall/maple_me/include/lfo_function.h new file mode 100644 index 0000000000000000000000000000000000000000..5a74f9ff37b19ee025a3f46e859ef7e176a5d185 --- /dev/null +++ b/src/mapleall/maple_me/include/lfo_function.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) [2020] 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. + */ + +#ifndef MAPLE_LFO_INCLUDE_LFO_FUNCTION_H +#define MAPLE_LFO_INCLUDE_LFO_FUNCTION_H +#include "lfo_mir_nodes.h" +#include "me_ir.h" + +namespace maple { + +class MeFunction; + +class LfoWhileInfo { + public: + MIRSymbol *injectedIVSym = nullptr; // the injected IV + OriginalSt *ivOst = nullptr; // the primary IV + MeExpr *initExpr = nullptr; + int32 stepValue = 0; + MeExpr *tripCount = nullptr; + bool canConvertDoloop = false; +}; + +class LfoIfInfo { + public: + LabelIdx endLabel = 0; // the label that is out of the if statement + LabelIdx elseLabel = 0; // the label that is the begin of else branch +}; + + +class LfoFunction { + public: + MemPool *lfomp; + MapleAllocator lfoAlloc; + MeFunction *meFunc; + MapleMap label2WhileInfo; // key is label at beginning of lowered while code sequence + MapleMap label2IfInfo; // key is target label of first conditional branch of lowered if code sequence + MapleSet lfoCreatedLabelSet; // for the labels that were created by lfo, we won't emit it + + public: + LfoFunction(MemPool *mp, MeFunction *func) : + lfomp(mp), + lfoAlloc(mp), + meFunc(func), + label2WhileInfo(lfoAlloc.Adapter()), + label2IfInfo(lfoAlloc.Adapter()), + lfoCreatedLabelSet(lfoAlloc.Adapter()) {} + + void SetLabelCreatedByLfo(LabelIdx lbidx) { + lfoCreatedLabelSet.insert(lbidx); + } + + bool LabelCreatedByLfo(LabelIdx lbidx) { + return lfoCreatedLabelSet.count(lbidx) != 0; + } +}; + +} // namespace maple +#endif // MAPLE_LFO_INCLUDE_LFO_FUNCTION_H diff --git a/src/mapleall/maple_me/include/lfo_inject_iv.h b/src/mapleall/maple_me/include/lfo_inject_iv.h new file mode 100644 index 0000000000000000000000000000000000000000..1181f2b6f20fd052ca18c310b5939bc6e8f6deb4 --- /dev/null +++ b/src/mapleall/maple_me/include/lfo_inject_iv.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) [2020] 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. + */ + +#ifndef MAPLE_ME_INCLUDE_LFO_INJECT_IV_H +#define MAPLE_ME_INCLUDE_LFO_INJECT_IV_H +#include "me_phase.h" + +namespace maple { + +/*emit ir to specified file*/ +class DoLfoInjectIV : public MeFuncPhase { + public: + DoLfoInjectIV(MePhaseID id) : MeFuncPhase(id) {} + + AnalysisResult *Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr*) override; + std::string PhaseName() const override { return "injectiv"; } +}; + +} // namespace maple +#endif // MAPLE_ME_INCLUDE_LFO_INJECT_IV_H diff --git a/src/mapleall/maple_me/include/lfo_mir_lower.h b/src/mapleall/maple_me/include/lfo_mir_lower.h new file mode 100644 index 0000000000000000000000000000000000000000..cb3aa490db63c9d41c860372fbc54d5d32f90908 --- /dev/null +++ b/src/mapleall/maple_me/include/lfo_mir_lower.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) [2020] 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. + */ + +#ifndef MAPLE_ME_INCLUDE_LFO_MIR_LOWER_H +#define MAPLE_ME_INCLUDE_LFO_MIR_LOWER_H +#include "mir_lower.h" +#include "me_function.h" +namespace maple { +class LFOMIRLower : public MIRLower { + public: + MeFunction *func; + LfoFunction *lfoFunc; + + public: + LFOMIRLower(MIRModule &mod, MeFunction *f) : MIRLower(mod, f->GetMirFunc()), + func(f), + lfoFunc(f->GetLfoFunc()) {} + + BlockNode *LowerWhileStmt(WhileStmtNode&); + BlockNode *LowerIfStmt(IfStmtNode &ifstmt, bool recursive = true); +}; +} +#endif // MAPLE_ME_INCLUDE_LFO_MIR_LOWER_H diff --git a/src/mapleall/maple_me/include/lfo_mir_nodes.h b/src/mapleall/maple_me/include/lfo_mir_nodes.h new file mode 100644 index 0000000000000000000000000000000000000000..fe408391352d1a824148b2548fb65f35f8fa4e16 --- /dev/null +++ b/src/mapleall/maple_me/include/lfo_mir_nodes.h @@ -0,0 +1,335 @@ +/* + * Copyright (c) [2020] 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. + */ + +#ifndef MAPLE_ME_INCLUDE_LFO_MIR_NODES_H_ +#define MAPLE_ME_INCLUDE_LFO_MIR_NODES_H_ +#include "me_ir.h" +#include "mir_nodes.h" + +namespace maple { + +class LfoParentPart { + public: + LfoParentPart *parent; + + public: + LfoParentPart (LfoParentPart *pt) : parent(pt) {} + virtual BaseNode *Cvt2BaseNode() = 0; + bool IsParentOf(LfoParentPart *canNode) { + LfoParentPart *dParent = canNode->parent; + while(dParent && dParent != this) + dParent = dParent->parent; + return dParent != NULL; + } +}; + +class LfoUnaryNode : public UnaryNode, public LfoParentPart{ + public: + LfoUnaryNode(Opcode o, PrimType ptyp, LfoParentPart *parent) : UnaryNode(o, ptyp), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoTypeCvtNode : public TypeCvtNode, public LfoParentPart { + public: + LfoTypeCvtNode(Opcode o, PrimType ptyp, LfoParentPart *parent) : + TypeCvtNode(o, ptyp), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoRetypeNode : public RetypeNode, public LfoParentPart { + public: + LfoRetypeNode(Opcode o, PrimType ptyp, LfoParentPart *parent) : + RetypeNode(ptyp), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoExtractbitsNode : public ExtractbitsNode, public LfoParentPart { + public: + LfoExtractbitsNode(Opcode o, PrimType ptyp, LfoParentPart *parent) : ExtractbitsNode(o, ptyp), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoIreadNode : public IreadNode, public LfoParentPart { + public: + IvarMeExpr *ivarx; + + public: + LfoIreadNode(Opcode o, PrimType ptyp, LfoParentPart *parent, IvarMeExpr *v) : + IreadNode(o, ptyp), LfoParentPart(parent), ivarx(v) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoIaddrofNode : public IreadNode, public LfoParentPart { + public: + LfoIaddrofNode(Opcode o, PrimType pty, LfoParentPart *parent) : IreadNode(o, pty), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoBinaryNode : public BinaryNode, public LfoParentPart { + public: + LfoBinaryNode (Opcode o, PrimType typ, LfoParentPart *parent) : BinaryNode (o,typ), + LfoParentPart (parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoCompareNode : public CompareNode, public LfoParentPart { + public: + LfoCompareNode (Opcode o, PrimType typ, PrimType otype, BaseNode *l, BaseNode *r, LfoParentPart *parent) : + CompareNode (o, typ, otype, l, r), LfoParentPart (parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoTernaryNode : public TernaryNode, public LfoParentPart { + public: + LfoTernaryNode (Opcode o, PrimType ptyp, LfoParentPart *parent) : TernaryNode(o, ptyp), + LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoNaryNode : public NaryNode, public LfoParentPart { + public: + LfoNaryNode (MapleAllocator *allc, Opcode o, PrimType pty, LfoParentPart *parent) : NaryNode (*allc, o, pty), + LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoIntrinsicopNode : public IntrinsicopNode, public LfoParentPart { + public: + LfoIntrinsicopNode (MapleAllocator *allc, Opcode o, PrimType ptyp, TyIdx tidx, LfoParentPart *parent) : + IntrinsicopNode(*allc, o, ptyp, tidx), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoConstvalNode : public ConstvalNode, public LfoParentPart { + public: + LfoConstvalNode(MIRConst *constv, LfoParentPart *parent) : ConstvalNode(constv->GetType().GetPrimType(), constv), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoConststrNode : public ConststrNode, public LfoParentPart { + public: + LfoConststrNode(PrimType ptyp, UStrIdx i, LfoParentPart *parent) : ConststrNode(ptyp, i), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoConststr16Node : public Conststr16Node, public LfoParentPart { + public: + LfoConststr16Node(PrimType ptyp, U16StrIdx i, LfoParentPart *parent) : Conststr16Node(ptyp, i), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoSizeoftypeNode : public SizeoftypeNode, public LfoParentPart { + public: + LfoSizeoftypeNode(PrimType ptyp, TyIdx tidx, LfoParentPart *parent) : SizeoftypeNode(ptyp, tidx), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoArrayNode : public ArrayNode, public LfoParentPart { + public: + LfoArrayNode(MapleAllocator *allc, PrimType typ, TyIdx idx, LfoParentPart *parent) : ArrayNode (*allc, typ, idx), LfoParentPart (parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoDreadNode : public AddrofNode, public LfoParentPart { + public: + VarMeExpr *varx; + + public: + LfoDreadNode(PrimType ptyp, StIdx sidx, FieldID fid, LfoParentPart *parent, VarMeExpr *v) : + AddrofNode(OP_dread, ptyp, sidx, fid), LfoParentPart(parent), varx(v) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoAddrofNode : public AddrofNode, public LfoParentPart { + public: + LfoAddrofNode(PrimType ptyp, StIdx sidx, FieldID fid, LfoParentPart *parent) : AddrofNode(OP_addrof, ptyp, sidx, fid), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoRegreadNode : public RegreadNode, public LfoParentPart { + public: + ScalarMeExpr *scalarx; + + public: + LfoRegreadNode(LfoParentPart *parent, ScalarMeExpr *s) : RegreadNode(), LfoParentPart(parent), scalarx(s) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoAddroffuncNode : public AddroffuncNode, public LfoParentPart { + public: + LfoAddroffuncNode(PrimType ptyp, PUIdx pidx, LfoParentPart *parent) : AddroffuncNode(ptyp, pidx), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoAddroflabelNode : public AddroflabelNode, public LfoParentPart { + public: + LfoAddroflabelNode(uint32 o, LfoParentPart *parent) : AddroflabelNode(o), LfoParentPart (parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoGCMallocNode : public GCMallocNode, public LfoParentPart { + public: + LfoGCMallocNode(Opcode o, PrimType pty, TyIdx tidx, LfoParentPart *parent) : GCMallocNode(o, pty, tidx), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoFieldsDistNode : public FieldsDistNode, public LfoParentPart { + public: + LfoFieldsDistNode(PrimType ptyp, TyIdx tidx, FieldID f1, FieldID f2, LfoParentPart *parent) : + FieldsDistNode(ptyp, tidx, f1, f2), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoIassignNode : public IassignNode, public LfoParentPart { + public: + IassignMeStmt *iasgn; + + public: + LfoIassignNode(LfoParentPart *parent, IassignMeStmt *ia) : IassignNode(), LfoParentPart(parent), iasgn(ia) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoGotoNode : public GotoNode, public LfoParentPart { + public: + LfoGotoNode (Opcode o, LfoParentPart *parent) : GotoNode(o), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoDassignNode : public DassignNode, public LfoParentPart { + public: + DassignMeStmt *dasgn; + + public: + LfoDassignNode(LfoParentPart *parent, DassignMeStmt *das) : DassignNode(), LfoParentPart(parent), dasgn(das) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoRegassignNode : public RegassignNode, public LfoParentPart { + public: + AssignMeStmt *asgn; + + public: + LfoRegassignNode(LfoParentPart *parent, AssignMeStmt *as) : RegassignNode(), LfoParentPart(parent), asgn(as) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoCondGotoNode : public CondGotoNode, public LfoParentPart { + public: + LfoCondGotoNode(Opcode o, LfoParentPart *parent) : CondGotoNode(o), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoWhileStmtNode : public WhileStmtNode, public LfoParentPart { + public: + LfoWhileStmtNode(LfoParentPart *parent) : WhileStmtNode(OP_while), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoDoloopNode : public DoloopNode, public LfoParentPart { + public: + LfoDoloopNode (LfoParentPart *parent) : DoloopNode (), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } + void InitLfoDoloopNode (StIdx stIdx, bool ispg, BaseNode *startExp, BaseNode *contExp, BaseNode *incrExp, BlockNode *blk) { + SetDoVarStIdx(stIdx); + SetIsPreg(ispg); + SetStartExpr(startExp); + SetContExpr(contExp); + SetIncrExpr(incrExp); + SetDoBody(blk); + } +}; + +class LfoNaryStmtNode : public NaryStmtNode, public LfoParentPart { + public: + LfoNaryStmtNode (MapleAllocator *allc, Opcode o, LfoParentPart *parent) : + NaryStmtNode(*allc, o), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoReturnStmtNode : public NaryStmtNode, public LfoParentPart { + public: + RetMeStmt *retmestmt; + + public: + LfoReturnStmtNode(MapleAllocator *allc, LfoParentPart *parent, RetMeStmt *ret) : + NaryStmtNode(*allc, OP_return), LfoParentPart(parent), retmestmt(ret) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoCallNode : public CallNode, public LfoParentPart { + public: + CallMeStmt *callmestmt; + + public: + LfoCallNode(MapleAllocator *allc, Opcode o, LfoParentPart *parent, CallMeStmt *cl) : CallNode(*allc, o), LfoParentPart(parent), callmestmt(cl) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoIcallNode : public IcallNode, public LfoParentPart { + public: + IcallMeStmt *icallmestmt; + + public: + LfoIcallNode (MapleAllocator *allc, Opcode o, TyIdx idx, LfoParentPart *parent, IcallMeStmt *ic) : + IcallNode (*allc, o, idx), LfoParentPart(parent), icallmestmt(ic) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoIntrinsiccallNode : public IntrinsiccallNode, public LfoParentPart { + public: + IntrinsiccallMeStmt *intrinmestmt; + + public: + LfoIntrinsiccallNode (MapleAllocator *allc, Opcode o, MIRIntrinsicID id, LfoParentPart *parent, IntrinsiccallMeStmt *intncall) : + IntrinsiccallNode(*allc, o, id), LfoParentPart(parent), intrinmestmt(intncall) {} + BaseNode *Cvt2BaseNode () { return this; } +}; + +class LfoIfStmtNode : public IfStmtNode, public LfoParentPart { + public: + LfoIfStmtNode(LfoParentPart *parent) : IfStmtNode(),LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoBlockNode : public BlockNode, public LfoParentPart { + public: + LfoBlockNode (LfoParentPart *parent) : BlockNode(),LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoStmtNode : public StmtNode, public LfoParentPart { + public: + LfoStmtNode (LfoParentPart *parent, Opcode o) : StmtNode (o), + LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +class LfoUnaryStmtNode : public UnaryStmtNode, public LfoParentPart { + public: + LfoUnaryStmtNode(Opcode o, LfoParentPart *parent) : UnaryStmtNode(o), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { + return this; + } +}; + +class LfoSwitchNode : public SwitchNode, public LfoParentPart { + public: + LfoSwitchNode(MapleAllocator *allc, LfoParentPart *parent) : + SwitchNode(*allc), LfoParentPart(parent) {} + BaseNode *Cvt2BaseNode() { return this; } +}; + +} // namespace maple +#endif // MAPLE_LFO_INCLUDE_LFO_MIR_NODES_H_ diff --git a/src/mapleall/maple_me/include/me_function.h b/src/mapleall/maple_me/include/me_function.h index ab38ee0cd13168d1de1add7a0b635c6e24ca9a7f..b64e32ce0217b9825396be64d8926dd4ff2f7e8d 100644 --- a/src/mapleall/maple_me/include/me_function.h +++ b/src/mapleall/maple_me/include/me_function.h @@ -26,6 +26,7 @@ #include "func_emit.h" #include "me_ir.h" #include "profile.h" +#include "lfo_function.h" namespace maple { class MeCFG; // circular dependency exists, no other choice @@ -156,7 +157,10 @@ class MeFunction : public FuncEmit { mirModule(*mod), mirFunc(func), laidOutBBVec(alloc.Adapter()), - fileName(fileName, memPool) {} + fileName(fileName, memPool), + lfoFunc(nullptr), lfoMp(nullptr) { + isLfo = (MeOption::optLevel == 3); + } ~MeFunction() override = default; @@ -311,6 +315,11 @@ class MeFunction : public FuncEmit { MIRFunction *CurFunction() const { return mirModule.CurFunction(); } + void SetLfoFunc(LfoFunction *lfoF) { lfoFunc = lfoF; } + LfoFunction *GetLfoFunc() { return lfoFunc; } + void SetLfoMempool(MemPool *mp) { lfoMp = mp; } + MemPool *GetLfoMempool() { return lfoMp; } + bool IsLfo() const { return isLfo; } private: MemPool *memPool; StackMemPool &stackMP; @@ -332,6 +341,10 @@ class MeFunction : public FuncEmit { bool profValid = false; IRProfileDesc *profileDesc = nullptr; uint32 frequency = 0; + // lfo + bool isLfo; + LfoFunction *lfoFunc; + MemPool *lfoMp; // used for lfo function }; } // namespace maple #endif // MAPLE_ME_INCLUDE_ME_FUNCTION_H diff --git a/src/mapleall/maple_me/include/me_phases.def b/src/mapleall/maple_me/include/me_phases.def index c625af60c7c8621f1060c3b410105365dfa25343..290eeab33a9d16bb63eb1b56bd04b3dae6d4db22 100644 --- a/src/mapleall/maple_me/include/me_phases.def +++ b/src/mapleall/maple_me/include/me_phases.def @@ -50,6 +50,7 @@ FUNCAPHASE(MeFuncPhase_MEVERIFY, MeDoVerify) FUNCTPHASE(MeFuncPhase_INTRACONSTPROP, MeDoIntraConstProp) FUNCTPHASE(MeFuncPhase_INTERCONSTPROP, MeDoInterConstProp) FUNCAPHASE(MeFuncPhase_MECFG, MeDoMeCfg) +FUNCTPHASE(MeFuncPhase_LFOINJECTIV, DoLfoInjectIV) #if MIR_JAVA FUNCTPHASE(MeFuncPhase_SYNCSELECT, MeDoSyncSelect) #endif diff --git a/src/mapleall/maple_me/src/lfo_inject_iv.cpp b/src/mapleall/maple_me/src/lfo_inject_iv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffbdc5825ea6eaf6a48d27f60a5e70c4e2bf8524 --- /dev/null +++ b/src/mapleall/maple_me/src/lfo_inject_iv.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) [2020] 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 "lfo_inject_iv.h" +#include "dominance.h" +#include "me_loop_analysis.h" +#include "me_option.h" +#include "mir_builder.h" +#include + +namespace maple { + +AnalysisResult *DoLfoInjectIV::Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr*) { + Dominance *dom = static_cast(m->GetAnalysisResult(MeFuncPhase_DOMINANCE, func)); + CHECK_FATAL(dom, "dominance phase has problem"); + IdentifyLoops *identloops = static_cast(m->GetAnalysisResult(MeFuncPhase_MELOOP, func)); + CHECK_FATAL(identloops != nullptr, "identloops has problem"); + + uint32 ivCount = 0; + MIRBuilder *mirbuilder = func->GetMIRModule().GetMIRBuilder(); + LfoFunction *lfoFunc = func->GetLfoFunc(); + + for (LoopDesc *aloop : identloops->GetMeLoops()) { + BB *headbb = aloop->head; + // check if the label has associated LfoWhileInfo + if (headbb->GetBBLabel() == 0) { + continue; + } + if (headbb->GetPred().size() != 2) { + continue; // won't insert IV for loops with > 1 tail bbs + } + MapleMap::iterator it = lfoFunc->label2WhileInfo.find(headbb->GetBBLabel()); + if (it == lfoFunc->label2WhileInfo.end()) { + continue; + } + LfoWhileInfo *whileInfo = it->second; + // find the entry BB as the predecessor of headbb that dominates headbb + MapleVector::iterator predit = headbb->GetPred().begin(); + for ( ; predit != headbb->GetPred().end(); predit++) { + if (dom->Dominate(**predit, *headbb)) + break; + } + if (predit == headbb->GetPred().end()) { + continue; // cannot insert IV for this loop + } + BB *entrybb = *predit; + + // create the IV for this loop + std::string ivName("injected.iv"); + ivName.append(std::to_string(++ivCount)); + GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(ivName); + MIRSymbol *st = mirbuilder->CreateSymbol((TyIdx)PTY_i64, strIdx, kStVar, kScAuto, func->GetMirFunc(), kScopeLocal); + whileInfo->injectedIVSym = st; + if (DEBUGFUNC(func)) { + LogInfo::MapleLogger() << "****** Injected IV " << st->GetName() << " in while loop at label "; + LogInfo::MapleLogger() << "@" << func->GetMirFunc()->GetLabelName(headbb->GetBBLabel()) << std::endl; + } + + // initialize IV to 0 at loop entry + DassignNode *dass = mirbuilder->CreateStmtDassign(st->GetStIdx(), 0, mirbuilder->CreateIntConst(0, PTY_i64)); + StmtNode *laststmt = entrybb->IsEmpty() ? NULL : &entrybb->GetLast(); + if (laststmt && + (laststmt->op == OP_brfalse || laststmt->op == OP_brtrue || laststmt->op == OP_goto || laststmt->op == OP_igoto || laststmt->op == OP_switch)) { + entrybb->InsertStmtBefore(laststmt, dass); + } else { + entrybb->AddStmtNode(dass); + } + + // insert IV increment at loop tail BB + BB *tailbb = aloop->tail; + AddrofNode *dread = mirbuilder->CreateExprDread(*GlobalTables::GetTypeTable().GetInt64(), *st); + BinaryNode *addnode = mirbuilder->CreateExprBinary(OP_add, *GlobalTables::GetTypeTable().GetInt64(), dread, mirbuilder->CreateIntConst(1, PTY_i64)); + dass = mirbuilder->CreateStmtDassign(*st, 0, addnode); + laststmt = &tailbb->GetLast(); + tailbb->InsertStmtBefore(laststmt, dass); + } + return nullptr; +} + +} // namespace maple diff --git a/src/mapleall/maple_me/src/lfo_mir_lower.cpp b/src/mapleall/maple_me/src/lfo_mir_lower.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a23ef211eed584b3f2c94b23abbc31d7da9624d --- /dev/null +++ b/src/mapleall/maple_me/src/lfo_mir_lower.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) [2020] 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 "mir_builder.h" +#include "lfo_mir_lower.h" + +using namespace maple; + +// is lowered to : +// label +// brfalse +// +// goto +// label + +BlockNode *LFOMIRLower::LowerWhileStmt(WhileStmtNode &whilestmt) { + MIRBuilder *mirbuilder = mirModule.GetMIRBuilder(); +//DoCondVarProp(whilestmt); + whilestmt.SetBody(LowerBlock(*whilestmt.GetBody())); + BlockNode *blk = mirModule.CurFuncCodeMemPool()->New(); + LabelIdx whilelblidx = func->GetMirFunc()->GetLabelTab()->CreateLabel(); + mirModule.CurFunction()->GetLabelTab()->AddToStringLabelMap(whilelblidx); + LabelNode *whilelblstmt = mirModule.CurFuncCodeMemPool()->New(); + whilelblstmt->SetLabelIdx(whilelblidx); + LfoWhileInfo *whileInfo = lfoFunc->lfomp->New(); + lfoFunc->SetLabelCreatedByLfo(whilelblidx); + lfoFunc->label2WhileInfo.insert(std::make_pair(whilelblidx, whileInfo)); + blk->AddStatement(whilelblstmt); + CondGotoNode *brfalsestmt = mirModule.CurFuncCodeMemPool()->New(OP_brfalse); + brfalsestmt->SetOpnd(whilestmt.Opnd(), 0); + brfalsestmt->SetSrcPos(whilestmt.GetSrcPos()); + // add jump label target later + blk->AddStatement(brfalsestmt); + + // create body + CHECK_FATAL(whilestmt.GetBody(), "null ptr check"); + blk->AppendStatementsFromBlock(*whilestmt.GetBody()); + GotoNode *whilegotonode = mirbuilder->CreateStmtGoto(OP_goto, whilelblidx); + blk->AddStatement(whilegotonode); + // create endlabel + LabelIdx endlblidx = mirModule.CurFunction()->GetLabelTab()->CreateLabel(); + lfoFunc->SetLabelCreatedByLfo(endlblidx); + mirModule.CurFunction()->GetLabelTab()->AddToStringLabelMap(endlblidx); + LabelNode *endlblstmt = mirModule.CurFuncCodeMemPool()->New(); + endlblstmt->SetLabelIdx(endlblidx); + brfalsestmt->SetOffset(endlblidx); + blk->AddStatement(endlblstmt); + return blk; +} + +BlockNode *LFOMIRLower::LowerIfStmt(IfStmtNode &ifstmt, bool recursive) { + bool thenempty = ifstmt.GetThenPart() == nullptr || ifstmt.GetThenPart()->GetFirst() == nullptr; + bool elseempty = ifstmt.GetElsePart() == nullptr || ifstmt.GetElsePart()->GetFirst() == nullptr; + + if (recursive) { + if (!thenempty) { + ifstmt.SetThenPart(LowerBlock(*ifstmt.GetThenPart())); + } + if (!elseempty) { + ifstmt.SetElsePart(LowerBlock(*ifstmt.GetElsePart())); + } + } + + BlockNode *blk = mirModule.CurFuncCodeMemPool()->New(); + MIRFunction *mirFunc = func->GetMirFunc(); + MIRBuilder *mirbuilder = mirModule.GetMIRBuilder(); + + if (thenempty && elseempty) { + // generate EVAL statement + UnaryStmtNode *evalstmt = mirModule.CurFuncCodeMemPool()->New(OP_eval); + evalstmt->SetOpnd(ifstmt.Opnd(), 0); + evalstmt->SetSrcPos(ifstmt.GetSrcPos()); + blk->AddStatement(evalstmt); + } else if (elseempty) { + // brfalse + // + // label + CondGotoNode *brfalsestmt = mirModule.CurFuncCodeMemPool()->New(OP_brfalse); + brfalsestmt->SetOpnd(ifstmt.Opnd(), 0); + brfalsestmt->SetSrcPos(ifstmt.GetSrcPos()); + LabelIdx endlabelidx = mirFunc->GetLabelTab()->CreateLabel(); + mirFunc->GetLabelTab()->AddToStringLabelMap(endlabelidx); + lfoFunc->SetLabelCreatedByLfo(endlabelidx); + LfoIfInfo *ifInfo = lfoFunc->lfomp->New(); + brfalsestmt->SetOffset(endlabelidx); + blk->AddStatement(brfalsestmt); + + blk->AppendStatementsFromBlock(*ifstmt.GetThenPart()); + + LabelNode *labstmt = mirModule.CurFuncCodeMemPool()->New(); + labstmt->SetLabelIdx(endlabelidx); + ifInfo->endLabel = endlabelidx; + lfoFunc->label2IfInfo.insert(std::make_pair(endlabelidx, ifInfo)); + blk->AddStatement(labstmt); + } else if (thenempty) { + // brtrue + // + // label + CondGotoNode *brtruestmt = mirModule.CurFuncCodeMemPool()->New(OP_brtrue); + brtruestmt->SetOpnd(ifstmt.Opnd(), 0); + brtruestmt->SetSrcPos(ifstmt.GetSrcPos()); + LabelIdx endlabelidx = mirFunc->GetLabelTab()->CreateLabel(); + lfoFunc->SetLabelCreatedByLfo(endlabelidx); + LfoIfInfo *ifInfo = lfoFunc->lfomp->New(); + mirFunc->GetLabelTab()->AddToStringLabelMap(endlabelidx); + brtruestmt->SetOffset(endlabelidx); + blk->AddStatement(brtruestmt); + + blk->AppendStatementsFromBlock(*ifstmt.GetElsePart()); + LabelNode *labstmt = mirModule.CurFuncCodeMemPool()->New(); + labstmt->SetLabelIdx(endlabelidx); + ifInfo->endLabel = endlabelidx; + lfoFunc->label2IfInfo.insert(std::make_pair(endlabelidx, ifInfo)); + blk->AddStatement(labstmt); + } else { + // brfalse + // + // goto + // label + // + // label + CondGotoNode *brfalsestmt = mirModule.CurFuncCodeMemPool()->New(OP_brfalse); + brfalsestmt->SetOpnd(ifstmt.Opnd(), 0); + brfalsestmt->SetSrcPos(ifstmt.GetSrcPos()); + LabelIdx elselabelidx = mirFunc->GetLabelTab()->CreateLabel(); + mirFunc->GetLabelTab()->AddToStringLabelMap(elselabelidx); + lfoFunc->SetLabelCreatedByLfo(elselabelidx); + LfoIfInfo *ifInfo = lfoFunc->lfomp->New(); + brfalsestmt->SetOffset(elselabelidx); + blk->AddStatement(brfalsestmt); + ifInfo->elseLabel = elselabelidx; + lfoFunc->label2IfInfo.insert(std::make_pair(elselabelidx, ifInfo)); + + blk->AppendStatementsFromBlock(*ifstmt.GetThenPart()); + bool fallthru_from_then = !OpCodeNoFallThrough(ifstmt.GetThenPart()->GetLast()->GetOpCode()); + LabelIdx endlabelidx = 0; + + if (fallthru_from_then) { + GotoNode *gotostmt = mirModule.CurFuncCodeMemPool()->New(OP_goto); + endlabelidx = mirFunc->GetLabelTab()->CreateLabel(); + mirFunc->GetLabelTab()->AddToStringLabelMap(endlabelidx); + lfoFunc->SetLabelCreatedByLfo(endlabelidx); + gotostmt->SetOffset(endlabelidx); + blk->AddStatement(gotostmt); + } + + LabelNode *labstmt = mirModule.CurFuncCodeMemPool()->New(); + labstmt->SetLabelIdx(elselabelidx); + blk->AddStatement(labstmt); + + blk->AppendStatementsFromBlock(*ifstmt.GetElsePart()); + + if (fallthru_from_then) { + labstmt = mirModule.CurFuncCodeMemPool()->New(); + labstmt->SetLabelIdx(endlabelidx); + blk->AddStatement(labstmt); + } + if (endlabelidx == 0) { // create end label + endlabelidx = mirbuilder->CreateLabIdx(*mirFunc); + lfoFunc->SetLabelCreatedByLfo(endlabelidx); + LabelNode *endlabelnode = mirbuilder->CreateStmtLabel(endlabelidx); + blk->AddStatement(endlabelnode); + } + ifInfo->endLabel = endlabelidx; + } + return blk; +} diff --git a/src/mapleall/maple_me/src/me_cfg.cpp b/src/mapleall/maple_me/src/me_cfg.cpp index c21505dfbb339cac65b7777a74262195722cabd9..8535b4952110e0db09833501fbf565e112164973 100644 --- a/src/mapleall/maple_me/src/me_cfg.cpp +++ b/src/mapleall/maple_me/src/me_cfg.cpp @@ -1478,6 +1478,15 @@ void MeCFG::CreateBasicBlocks() { SetBBTryNodeMap(*newBB, *tryStmt); } curBB = newBB; + } else if (func.GetLfoFunc() && + (func.GetLfoFunc()->label2WhileInfo.find(labelIdx) != func.GetLfoFunc()->label2WhileInfo.end())) { + curBB->SetKind(kBBFallthru); + BB *newBB = NewBasicBlock(); + if (tryStmt != nullptr) { + newBB->SetAttributes(kBBAttrIsTry); + SetBBTryNodeMap(*newBB, *tryStmt); + } + curBB = newBB; } labelBBIdMap[labelIdx] = curBB; curBB->SetBBLabel(labelIdx); diff --git a/src/mapleall/maple_me/src/me_function.cpp b/src/mapleall/maple_me/src/me_function.cpp index 20755bd3856f6ba50b004897cbe4c7ec9029a954..e9a62fc9b40d7cadf6fb52071f45654f4af31f6a 100644 --- a/src/mapleall/maple_me/src/me_function.cpp +++ b/src/mapleall/maple_me/src/me_function.cpp @@ -22,6 +22,7 @@ #include "constantfold.h" #include "me_irmap.h" #include "me_phase.h" +#include "lfo_mir_lower.h" namespace maple { #if DEBUG @@ -130,14 +131,22 @@ void MeFunction::Prepare(unsigned long rangeNum) { << "] ---\n"; } /* lower first */ - MIRLower mirLowerer(mirModule, CurFunction()); - mirLowerer.Init(); - mirLowerer.SetLowerME(); - if (mirModule.IsJavaModule()) { - mirLowerer.SetLowerExpandArray(); + if (MeOption::optLevel >= 3) { + MemPool* lfomp = memPoolCtrler.NewMemPool("lfo", true); + SetLfoFunc(lfomp->New(lfomp, this)); + SetLfoMempool(lfomp); + LFOMIRLower lfomirlowerer(mirModule, this); + lfomirlowerer.LowerFunc(*CurFunction()); + } else { + MIRLower mirLowerer(mirModule, CurFunction()); + mirLowerer.Init(); + mirLowerer.SetLowerME(); + if (mirModule.IsJavaModule()) { + mirLowerer.SetLowerExpandArray(); + } + ASSERT(CurFunction() != nullptr, "nullptr check"); + mirLowerer.LowerFunc(*CurFunction()); } - ASSERT(CurFunction() != nullptr, "nullptr check"); - mirLowerer.LowerFunc(*CurFunction()); } void MeFunction::Verify() const { diff --git a/src/mapleall/maple_me/src/me_phase_manager.cpp b/src/mapleall/maple_me/src/me_phase_manager.cpp index 96d1572c82af9ef04106ced2d2a4f0e42aefb3b7..b3926c9fbe4783d779a71174fe7bd8a9f5ad8b7c 100644 --- a/src/mapleall/maple_me/src/me_phase_manager.cpp +++ b/src/mapleall/maple_me/src/me_phase_manager.cpp @@ -69,6 +69,7 @@ #include "mpl_timer.h" #include "constantfold.h" #include "me_verify.h" +#include "lfo_inject_iv.h" #define JAVALANG (mirModule.IsJavaModule()) @@ -312,6 +313,10 @@ void MeFuncPhaseManager::Run(MIRFunction *mirFunc, uint64 rangeNum, const std::s extraMeTimers["invalidResult"] += invalidTimer.ElapsedMicroseconds(); } } + // release lfo mempool + if (MeOption::optLevel >= 3) { + memPoolCtrler.DeleteMemPool(func.GetLfoMempool()); + } } MeFuncPhaseManager &MeFuncPhaseManager::Clone(MemPool &mp, MemPoolCtrler &ctrler) const {