diff --git a/src/bin/jbc2mpl b/src/bin/jbc2mpl index 8fbb0ee1934a282fd06465a09712a785718fe337..e31b636fe5462a07668d36afacf4b9675633e90e 100755 Binary files a/src/bin/jbc2mpl and b/src/bin/jbc2mpl differ diff --git a/src/bin/maple b/src/bin/maple index 65e789cabf2f2cb194ca9e9cbcee733a6ea4350b..d0a8417ee7b654267946bdcb730170f80842ffd9 100755 Binary files a/src/bin/maple and b/src/bin/maple differ diff --git a/src/deplibs/libmplphase.a b/src/deplibs/libmplphase.a index 8052303ccf5d7f038c1d36a71c31f8680ef9b168..5a5f202d2746a6a6fc2cc537309d7ad9ca5985f4 100644 Binary files a/src/deplibs/libmplphase.a and b/src/deplibs/libmplphase.a differ diff --git a/src/deplibs/libmplutil.a b/src/deplibs/libmplutil.a index 2b4054555a9da5b61a36ffb3342da81b7080ac5a..5b358fb12d955ccd30ccf5780eb762b634450d90 100644 Binary files a/src/deplibs/libmplutil.a and b/src/deplibs/libmplutil.a differ diff --git a/src/maple_be/include/ad/cortex_a55/sched_cortex_a55.td b/src/maple_be/include/ad/cortex_a55/sched_cortex_a55.td index 90d3c0175c46aef9c2bfe8fea3ddbcacdcd510a5..bb1127d737296c7a1e95732956f677fc8495b33f 100644 --- a/src/maple_be/include/ad/cortex_a55/sched_cortex_a55.td +++ b/src/maple_be/include/ad/cortex_a55/sched_cortex_a55.td @@ -83,7 +83,7 @@ Def Reservation : kLtStore2 {2, [ kUnitIdSlotSAgen, kUnitIdStAgu]}; Def Reservation : kLtLoad3plus {6, [kUnitIdSlotDAgen, kUnitIdSlot0LdAgu, kUnitIdLdAgu]}; Def Reservation : kLtStore3plus {2, [kUnitIdSlotDAgen, kUnitIdSlot0StAgu, kUnitIdStAgu]}; Def Reservation : kLtBranch {0, [kUnitIdSlotSBranch]}; -Def Reservation : kLtFpalu {4, [kUnitIdSlotS]}; +Def Reservation : kLtFpalu {4, [kUnitIdSlotS, kUnitIdFpAluS]}; Def Reservation : kLtFconst {2, [kUnitIdSlotS, kUnitIdFpAluS]}; Def Reservation : kLtFpmul {4, [kUnitIdSlotS, kUnitIdFpMulS]}; Def Reservation : kLtFpmac {8, [kUnitIdSlotS, kUnitIdFpMulS, nothing, nothing, nothing, kUnitIdFpAluS]}; diff --git a/src/maple_be/include/ad/target/mplad_reservation_define.def b/src/maple_be/include/ad/target/mplad_reservation_define.def index 9d54a27148eb0932ac449069654f43e5ff73c73c..d0591b70162898690b676c83d7c75bce201c0b95 100644 --- a/src/maple_be/include/ad/target/mplad_reservation_define.def +++ b/src/maple_be/include/ad/target/mplad_reservation_define.def @@ -124,8 +124,9 @@ if(resvInstkLtBranch == nullptr) { } ASSERT(resvInstkLtBranch, "Reservation allocation for kLtBranch failed."); -Reservation *resvInstkLtFpalu = new Reservation(kLtFpalu, 4, 1, - GetUnitByUnitId(kUnitIdSlotS)); +Reservation *resvInstkLtFpalu = new Reservation(kLtFpalu, 4, 2, + GetUnitByUnitId(kUnitIdSlotS), + GetUnitByUnitId(kUnitIdFpAluS)); if(resvInstkLtFpalu == nullptr) { maple::logInfo.MapleLogger(maple::kLlErr) << "Reservation allocation for kLtFpalu failed." << std::endl; } diff --git a/src/maple_be/include/cg/insn.h b/src/maple_be/include/cg/insn.h index 57f36a41a80aa41b9cd2d9feea7b07ce80ca29d1..eb24e5462b5702431bbef8f4a47ee6dfc337b40a 100644 --- a/src/maple_be/include/cg/insn.h +++ b/src/maple_be/include/cg/insn.h @@ -148,6 +148,10 @@ class Insn { return false; } + virtual bool IsPCLoad() const { + return false; + } + virtual uint32 GetOpndNum() const { return 0; } diff --git a/src/maple_be/include/cg/operand.h b/src/maple_be/include/cg/operand.h index 4e425757fa8a12ad49cf8908e25bb71e1c96a902..6330c9c8d95ed1265c5abef0f246b6ceee69a026 100644 --- a/src/maple_be/include/cg/operand.h +++ b/src/maple_be/include/cg/operand.h @@ -538,6 +538,7 @@ class MemOperand : public Operand { } CHECK_FATAL(baseOpnd != nullptr, "baseOpnd is null in Equals"); CHECK_FATAL(indexOpnd != nullptr, "indexOpnd is null in Equals"); + ASSERT(op.GetBaseRegister() != nullptr, "nullptr check"); return (baseOpnd->Equals(*op.GetBaseRegister()) && indexOpnd->Equals(*op.GetIndexRegister())); } diff --git a/src/maple_be/mdgen/src/mdgenerator.cpp b/src/maple_be/mdgen/src/mdgenerator.cpp index 0191e4519b7cdeebdcdcda624c7dd35d83249ed7..994698667a997f53f660a8673c9ccdd58704953a 100644 --- a/src/maple_be/mdgen/src/mdgenerator.cpp +++ b/src/maple_be/mdgen/src/mdgenerator.cpp @@ -62,6 +62,7 @@ void SchedInfoGen::EmitArchDef() { void SchedInfoGen::EmitUnitIdDef() { MDClass unitClass = GetSpecificClass("Unit"); outFile.open(GetOFileDir() + "/mplad_unit_id.def", std::ios::out); + ASSERT(outFile.is_open(), "Failed to open output file: %s/mplad_unit_id.def", GetOFileDir().c_str()); EmitFileHead(outFile, "function unit ID"); for (auto unitIdx : unitClass.GetchildObjNames()) { outFile << " " << curKeeper.GetStrByIdx(unitIdx) << ",\n"; @@ -72,6 +73,7 @@ void SchedInfoGen::EmitUnitIdDef() { void SchedInfoGen::EmitUnitNameDef() { MDClass unitClass = GetSpecificClass("Unit"); outFile.open(GetOFileDir() + "/mplad_unit_name.def", std::ios::out); + ASSERT(outFile.is_open(), "Failed to open output file: %s/mplad_unit_name.def", GetOFileDir().c_str()); EmitFileHead(outFile, "function unit name"); for (auto unitIdx : unitClass.GetchildObjNames()) { std::string unitPureName = curKeeper.GetStrByIdx(unitIdx); @@ -87,6 +89,7 @@ void SchedInfoGen::EmitUnitNameDef() { void SchedInfoGen::EmitUnitDef() { MDClass unitClass = GetSpecificClass("Unit"); outFile.open(GetOFileDir() + "/mplad_unit_define.def", std::ios::out); + ASSERT(outFile.is_open(), "Failed to open output file: %s/mplad_unit_define.def", GetOFileDir().c_str()); EmitFileHead(outFile, "function units "); bool isUnitNumDef = false; for (size_t i = 0; i < unitClass.GetMDObjectSize(); ++i) { @@ -135,6 +138,7 @@ void SchedInfoGen::EmitUnitDef() { void SchedInfoGen::EmitLatencyDef() { MDClass resvClass = GetSpecificClass("Reservation"); outFile.open(GetOFileDir() + "/mplad_latency_type.def", std::ios::out); + ASSERT(outFile.is_open(), "Failed to open output file: %s/mplad_latency_type.def", GetOFileDir().c_str()); EmitFileHead(outFile, " latency type definition "); for (auto resvIdx : resvClass.GetchildObjNames()) { outFile << " " << curKeeper.GetStrByIdx(resvIdx) << ",\n"; @@ -145,6 +149,8 @@ void SchedInfoGen::EmitLatencyDef() { void SchedInfoGen::EmitResvDef() { MDClass resvClass = GetSpecificClass("Reservation"); outFile.open(GetOFileDir() + "/mplad_reservation_define.def", std::ios::out); + ASSERT(outFile.is_open(), "Failed to open output file: %s/mplad_reservation_define.def", + GetOFileDir().c_str()); EmitFileHead(outFile, "reservations"); for (size_t i = 0; i < resvClass.GetMDObjectSize(); ++i) { const MDObject &singleResv = resvClass.GetOneMDObject(i); diff --git a/src/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index b9e7454ae426d2f913ef572bd7c87769df5a7773..6b2f72ea1f1bc2483cfd4e9fd894758b98f67729 100644 --- a/src/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -193,6 +193,7 @@ void AArch64CGFunc::SelectLoadAcquire(Operand &dest, PrimType dtype, Operand &sr RegOperand *origBaseReg = memOpnd.GetBaseRegister(); if (offset != 0) { RegOperand &resOpnd = CreateRegisterOperandOfType(PTY_i64); + ASSERT(origBaseReg != nullptr, "nullptr check"); SelectAdd(resOpnd, *origBaseReg, *immOpnd, PTY_i64); newSrc = &CreateReplacementMemOperand(ssize, resOpnd, 0); } @@ -252,7 +253,6 @@ void AArch64CGFunc::SelectLoadAcquire(Operand &dest, PrimType dtype, Operand &sr void AArch64CGFunc::SelectStoreRelease(Operand &dest, PrimType dtype, Operand &src, PrimType stype, AArch64isa::MemoryOrdering memOrd, bool isDirect) { ASSERT(dest.GetKind() == Operand::kOpdMem, "Just checking"); - ASSERT(memOrd != AArch64isa::kMoNone, "Just checking"); uint32 dsize = isDirect ? dest.GetSize() : GetPrimTypeBitSize(stype); MOperator mOp = PickStInsn(dsize, stype, memOrd); @@ -264,6 +264,7 @@ void AArch64CGFunc::SelectStoreRelease(Operand &dest, PrimType dtype, Operand &s RegOperand *origBaseReg = memOpnd->GetBaseRegister(); if (offset != 0) { RegOperand &resOpnd = CreateRegisterOperandOfType(PTY_i64); + ASSERT(origBaseReg != nullptr, "nullptr check"); SelectAdd(resOpnd, *origBaseReg, *immOpnd, PTY_i64); newDest = &CreateReplacementMemOperand(dsize, resOpnd, 0); } @@ -564,7 +565,7 @@ void AArch64CGFunc::SelectCopyRegOpnd(Operand &dest, PrimType dtype, Operand::Op } AArch64MemOperand *memOpnd = static_cast(&dest); - ASSERT(memOpnd, "memOpnd should not be nullptr"); + ASSERT(memOpnd != nullptr, "memOpnd should not be nullptr"); if (memOpnd->GetAddrMode() == AArch64MemOperand::kAddrModeLo12Li) { GetCurBB()->AppendInsn(GetCG()->BuildInstruction(strMop, src, dest)); return; @@ -574,7 +575,7 @@ void AArch64CGFunc::SelectCopyRegOpnd(Operand &dest, PrimType dtype, Operand::Op return; } ImmOperand *immOpnd = static_cast(memOpnd->GetOffsetOperand()); - ASSERT(immOpnd, "immOpnd should not be nullptr"); + ASSERT(immOpnd != nullptr, "immOpnd should not be nullptr"); int64 immVal = immOpnd->GetValue(); bool isIntactIndexed = memOpnd->IsIntactIndexed(); bool isPostIndexed = memOpnd->IsPostIndexed(); @@ -585,6 +586,7 @@ void AArch64CGFunc::SelectCopyRegOpnd(Operand &dest, PrimType dtype, Operand::Op GetCurBB()->AppendInsn(GetCG()->BuildInstruction(strMop, src, dest)); return; } + ASSERT(memOpnd->GetBaseRegister() != nullptr, "nullptr check"); if (isIntactIndexed) { RegOperand ® = CreateRegisterOperandOfType(PTY_i64); AArch64ImmOperand *aarch64ImmOpnd = static_cast(immOpnd); @@ -734,6 +736,7 @@ AArch64MemOperand &AArch64CGFunc::SplitOffsetWithAddInstruction(const AArch64Mem int32 r1 = static_cast(r0) & ((1u << static_cast(alignment)) - 1); addend = addend + r1; RegOperand *origBaseReg = memOpnd.GetBaseRegister(); + ASSERT(origBaseReg != nullptr, "nullptr check"); if (addend > 0) { int32 t = addend; constexpr uint32 suffixClear = 0xfffff000; @@ -781,6 +784,7 @@ RegOperand *AArch64CGFunc::ExtractNewMemBase(MemOperand &memOpnd) { return nullptr; } RegOperand *baseOpnd = memOpnd.GetBaseRegister(); + ASSERT(baseOpnd != nullptr, "nullptr check"); RegOperand &resultOpnd = CreateRegisterOperandOfType(baseOpnd->GetRegisterType(), baseOpnd->GetSize() / kBitsPerByte); bool is64Bits = (baseOpnd->GetSize() == k64BitSize); if (mode == AArch64MemOperand::kAddrModeLo12Li) { @@ -1382,6 +1386,7 @@ void AArch64CGFunc::SelectAddrof(Operand &result, AArch64MemOperand &memOpnd) { if (symbol->GetStorageClass() == kScAuto) { auto *offsetOpnd = static_cast(memOpnd.GetOffsetImmediate()); Operand &immOpnd = CreateImmOperand(offsetOpnd->GetOffsetValue(), PTY_u32, false); + ASSERT(memOpnd.GetBaseRegister() != nullptr, "nullptr check"); SelectAdd(result, *memOpnd.GetBaseRegister(), immOpnd, PTY_u32); } else { GetCurBB()->AppendInsn(GetCG()->BuildInstruction(MOP_xadrp, result, memOpnd)); @@ -5261,6 +5266,7 @@ MemOperand &AArch64CGFunc::GetOrCreateMemOpnd(const MIRSymbol &symbol, int32 off AArch64MemOperand &AArch64CGFunc::GetOrCreateMemOpnd(AArch64MemOperand::AArch64AddressingMode mode, uint32 size, RegOperand *base, RegOperand *index, OfstOperand *offset, const MIRSymbol *st) { + ASSERT(base != nullptr, "nullptr check"); AArch64MemOperand tMemOpnd(mode, size, *base, index, offset, st); auto it = hashMemOpndTable.find(tMemOpnd); if (it != hashMemOpndTable.end()) { @@ -5274,6 +5280,7 @@ AArch64MemOperand &AArch64CGFunc::GetOrCreateMemOpnd(AArch64MemOperand::AArch64A AArch64MemOperand &AArch64CGFunc::GetOrCreateMemOpnd(AArch64MemOperand::AArch64AddressingMode mode, uint32 size, RegOperand *base, RegOperand *index, int32 shift, bool isSigned) { + ASSERT(base != nullptr, "nullptr check"); AArch64MemOperand tMemOpnd(mode, size, *base, *index, shift, isSigned); auto it = hashMemOpndTable.find(tMemOpnd); if (it != hashMemOpndTable.end()) { diff --git a/src/maple_be/src/cg/aarch64/aarch64_color_ra.cpp b/src/maple_be/src/cg/aarch64/aarch64_color_ra.cpp index cf3ae63706044cf251216fedd13e977e5d8d396f..9f158ecf367182bfb6df1205b0cf0ee9b644e260 100644 --- a/src/maple_be/src/cg/aarch64/aarch64_color_ra.cpp +++ b/src/maple_be/src/cg/aarch64/aarch64_color_ra.cpp @@ -3019,6 +3019,7 @@ void GraphColorRegAllocator::FinalizeRegisters() { static_cast(fInfo->GetBaseOperand())->Clone(*cgFunc->GetMemoryPool())); insn->SetOperand(fInfo->GetMemOperandIdx(), *memOpnd); Operand *base = memOpnd->GetBaseRegister(); + ASSERT(base != nullptr, "nullptr check"); /* if base register is both defReg and useReg, defSpillIdx should also be increased. But it doesn't exist yet */ RegOperand *phyOpnd = GetReplaceOpnd(*insn, *base, useSpillIdx, usedRegMask, false); if (phyOpnd != nullptr) { diff --git a/src/maple_be/src/cg/cg.cpp b/src/maple_be/src/cg/cg.cpp index b2261d73e90cd37be0c8e201bd1288f545b06b58..2eb6f62a5e38991486bc5598ab44fea0ba5c02ab 100644 --- a/src/maple_be/src/cg/cg.cpp +++ b/src/maple_be/src/cg/cg.cpp @@ -65,6 +65,7 @@ void CG::GenExtraTypeMetadata(const std::string &classListFileName, const std::s } else { /* Visit listed classes. */ std::ifstream inFile(classListFileName); + ASSERT(inFile.is_open(), "Failed to open file: %s", classListFileName.c_str()); std::string str; /* check each class name first and expose all unknown classes */ diff --git a/src/maple_me/include/irmap.h b/src/maple_me/include/irmap.h index c9ad8f5d78e6abc915a981b4a042b26030283a71..bf3937bedbb4abb9faf0ba18e012959a687d2542 100644 --- a/src/maple_me/include/irmap.h +++ b/src/maple_me/include/irmap.h @@ -101,6 +101,7 @@ class IRMap : public AnalysisResult { MeExpr *CreateIntConstMeExpr(int64, PrimType); MeExpr *CreateConstMeExpr(PrimType, MIRConst&); MeExpr *CreateMeExprBinary(Opcode, PrimType, MeExpr&, MeExpr&); + MeExpr *CreateMeExprCompare(Opcode, PrimType, PrimType, MeExpr&, MeExpr&); MeExpr *CreateMeExprSelect(PrimType, MeExpr&, MeExpr&, MeExpr&); MeExpr *CreateMeExprTypeCvt(PrimType, PrimType, MeExpr&); IntrinsiccallMeStmt *CreateIntrinsicCallMeStmt(MIRIntrinsicID idx, std::vector &opnds, @@ -238,7 +239,6 @@ class IRMap : public AnalysisResult { MeStmt *BuildMeStmt(StmtNode&); MeExpr *BuildLHSReg(const VersionSt &vst, RegassignMeStmt &defMeStmt, const RegassignNode ®assign); RegMeExpr *CreateRefRegMeExpr(const MIRSymbol&); - MeExpr *CreateMeExprCompare(Opcode, PrimType, PrimType, MeExpr&, MeExpr&); VarMeExpr *GetOrCreateVarFromVerSt(const VersionSt &vst); RegMeExpr *GetOrCreateRegFromVerSt(const VersionSt &vst); void BuildChiList(MeStmt&, MapleMap&, MapleMap&); diff --git a/src/maple_me/include/me_ir.h b/src/maple_me/include/me_ir.h index f12d59f0c75a8e3cede89295aefc910d758691a7..9282ba943c364098d6399924ccb1e33e7a8fecc3 100644 --- a/src/maple_me/include/me_ir.h +++ b/src/maple_me/include/me_ir.h @@ -1742,6 +1742,11 @@ class MaydassignMeStmt : public MeStmt { : MeStmt(stt), chiList(std::less(), alloc->Adapter()) {} + MaydassignMeStmt(MapleAllocator *alloc, MaydassignMeStmt &maydass) + : MeStmt(maydass.GetOp()), rhs(maydass.GetRHS()), mayDSSym(maydass.GetMayDassignSym()), + fieldID(maydass.GetFieldID()), chiList(std::less(), alloc->Adapter()), + needDecref(maydass.NeedDecref()), needIncref(maydass.NeedIncref()) {} + ~MaydassignMeStmt() = default; size_t NumMeStmtOpnds() const { @@ -1788,6 +1793,10 @@ class MaydassignMeStmt : public MeStmt { needIncref = false; } + OriginalSt *GetMayDassignSym() { + return mayDSSym; + } + const OriginalSt *GetMayDassignSym() const { return mayDSSym; } @@ -1856,6 +1865,11 @@ class IassignMeStmt : public MeStmt { l->SetDefStmt(this); } + IassignMeStmt(MapleAllocator *alloc, TyIdx tidx, IvarMeExpr &l, MeExpr &r) + : MeStmt(OP_iassign), tyIdx(tidx), lhsVar(&l), rhs(&r), chiList(std::less(), alloc->Adapter()) { + l.SetDefStmt(this); + } + ~IassignMeStmt() = default; TyIdx GetTyIdx() const { @@ -2065,6 +2079,12 @@ class CallMeStmt : public NaryMeStmt, public MuChiMePart, public AssignedPart { CallMeStmt(MapleAllocator *alloc, Opcode op) : NaryMeStmt(alloc, op), MuChiMePart(alloc), AssignedPart(alloc) {} + CallMeStmt(MapleAllocator *alloc, NaryMeStmt *cstmt, PUIdx idx) + : NaryMeStmt(alloc, cstmt), + MuChiMePart(alloc), + AssignedPart(alloc), + puIdx(idx) {} + CallMeStmt(MapleAllocator *alloc, const CallMeStmt *cstmt) : NaryMeStmt(alloc, cstmt), MuChiMePart(alloc), @@ -2287,6 +2307,14 @@ class IntrinsiccallMeStmt : public NaryMeStmt, public MuChiMePart, public Assign tyIdx(intrn->tyIdx), retPType(intrn->retPType) {} + IntrinsiccallMeStmt(MapleAllocator *alloc, const NaryMeStmt *nary, MIRIntrinsicID id, TyIdx idx, PrimType type) + : NaryMeStmt(alloc, nary), + MuChiMePart(alloc), + AssignedPart(alloc), + intrinsic(id), + tyIdx(idx), + retPType(type) {} + virtual ~IntrinsiccallMeStmt() = default; void Dump(const IRMap*) const; @@ -2367,6 +2395,10 @@ class IntrinsiccallMeStmt : public NaryMeStmt, public MuChiMePart, public Assign return tyIdx; } + PrimType GetReturnPrimType() const { + return retPType; + } + private: MIRIntrinsicID intrinsic; TyIdx tyIdx; @@ -2432,6 +2464,7 @@ class UnaryMeStmt : public MeStmt { class GotoMeStmt : public MeStmt { public: explicit GotoMeStmt(const StmtNode *stt) : MeStmt(stt), offset(static_cast(stt)->GetOffset()) {} + explicit GotoMeStmt(const GotoMeStmt &condGoto) : MeStmt(MeStmt(condGoto.GetOp())), offset(condGoto.GetOffset()) {} ~GotoMeStmt() = default; @@ -2454,6 +2487,12 @@ class CondGotoMeStmt : public UnaryMeStmt { explicit CondGotoMeStmt(const StmtNode *stt) : UnaryMeStmt(stt), offset(static_cast(stt)->GetOffset()) {} + explicit CondGotoMeStmt(const CondGotoMeStmt &condGoto) + : UnaryMeStmt(static_cast(&condGoto)), offset(condGoto.GetOffset()) {} + + CondGotoMeStmt(const UnaryMeStmt &unaryMeStmt, uint32 o) + : UnaryMeStmt(&unaryMeStmt), offset(o) {} + ~CondGotoMeStmt() = default; uint32 GetOffset() const { diff --git a/src/maple_me/include/me_loop_analysis.h b/src/maple_me/include/me_loop_analysis.h index ea79c5950409ef9e6161f0c1d0af14936328adc8..9ef5673613dceed3f73414b8cc600b9f23af90aa 100644 --- a/src/maple_me/include/me_loop_analysis.h +++ b/src/maple_me/include/me_loop_analysis.h @@ -18,22 +18,77 @@ #include "bb.h" #include "me_phase.h" #include "dominance.h" +#include namespace maple { class IdentifyLoops; // describes a specific loop, including the loop head, tail and sets of bb. struct LoopDesc { + MapleAllocator *alloc; BB *head; BB *tail; + BB *preheader; + BB *latch; + MapleMap*> inloopBB2exitBBs; MapleSet loopBBs; LoopDesc *parent; // points to its closest nesting loop uint32 nestDepth; // the nesting depth - LoopDesc(MapleAllocator &alloc, BB *headBB, BB *tailBB) - : head(headBB), tail(tailBB), loopBBs(alloc.Adapter()), parent(nullptr), nestDepth(0) {} + bool hasTryBB = false; + bool isCanonicalLoop = false; + LoopDesc(MapleAllocator &mapleAllocator, BB *headBB, BB *tailBB) + : alloc(&mapleAllocator), head(headBB), tail(tailBB), preheader(nullptr), latch(nullptr), + inloopBB2exitBBs(alloc->Adapter()), loopBBs(alloc->Adapter()), parent(nullptr), nestDepth(0), hasTryBB(false) {} bool Has(const BB &bb) const { return loopBBs.find(bb.GetBBId()) != loopBBs.end(); } + + bool IsNormalizationLoop() const { + if (!hasTryBB && preheader != nullptr && !inloopBB2exitBBs.empty()) { + return true; + } + return false; + } + + void InsertInloopBB2exitBBs(BB &key, BB &value) { + if (inloopBB2exitBBs.find(&key) == inloopBB2exitBBs.end()) { + inloopBB2exitBBs[&key] = alloc->GetMemPool()->New>(alloc->Adapter()); + inloopBB2exitBBs[&key]->push_back(&value); + } else { + auto it = find(inloopBB2exitBBs[&key]->begin(), inloopBB2exitBBs[&key]->end(), &value); + if (it == inloopBB2exitBBs[&key]->end()) { + inloopBB2exitBBs[&key]->push_back(&value); + } + } + } + + void ReplaceInloopBB2exitBBs(BB &key, BB &oldValue, BB &value) { + CHECK_FATAL(inloopBB2exitBBs.find(&key) != inloopBB2exitBBs.end(), "key must exits"); + auto mapIt = inloopBB2exitBBs[&key]; + auto it = find(mapIt->begin(), mapIt->end(), &oldValue); + CHECK_FATAL(it != inloopBB2exitBBs[&key]->end(), "old Vvalue must exits"); + *it = &value; + CHECK_FATAL(find(inloopBB2exitBBs[&key]->begin(), inloopBB2exitBBs[&key]->end(), &value) != + inloopBB2exitBBs[&key]->end(), "replace fail"); + CHECK_FATAL(find(inloopBB2exitBBs[&key]->begin(), inloopBB2exitBBs[&key]->end(), &oldValue) == + inloopBB2exitBBs[&key]->end(), "replace fail"); + } + + void SetHasTryBB(bool has) { + hasTryBB = has; + } + + bool HasTryBB() const { + return hasTryBB; + } + + void SetIsCanonicalLoop(bool is) { + isCanonicalLoop = is; + } + + bool IsCanonicalLoop() const { + return isCanonicalLoop; + } }; // IdentifyLoop records all the loops in a MeFunction. @@ -60,9 +115,12 @@ class IdentifyLoops : public AnalysisResult { LoopDesc *CreateLoopDesc(BB &hd, BB &tail); void SetLoopParent4BB(const BB &bb, LoopDesc &loopDesc); + void InsertExitBB(LoopDesc &loop); void ProcessBB(BB *bb); void MarkBB(); void Dump() const; + bool ProcessPreheaderAndLatch(LoopDesc &loop); + void SetTryBB(); private: MemPool *meLoopMemPool; @@ -76,9 +134,8 @@ class IdentifyLoops : public AnalysisResult { class MeDoMeLoop : public MeFuncPhase { public: explicit MeDoMeLoop(MePhaseID id) : MeFuncPhase(id) {} - virtual ~MeDoMeLoop() = default; - AnalysisResult *Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr *mrm) override; + AnalysisResult *Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr*) override; std::string PhaseName() const override { return "identloops"; } diff --git a/src/maple_me/include/me_loop_canon.h b/src/maple_me/include/me_loop_canon.h index 0183b7792ad195409d572031764ea83792330006..b02414be4abc5eda8d3b5f43c9d2e1867af75f4f 100644 --- a/src/maple_me/include/me_loop_canon.h +++ b/src/maple_me/include/me_loop_canon.h @@ -16,6 +16,7 @@ #define MAPLE_ME_INCLUDE_MELOOPCANON_H #include "me_function.h" #include "me_phase.h" +#include "me_loop_analysis.h" namespace maple { // convert loop to do-while format @@ -25,15 +26,25 @@ class MeDoLoopCanon : public MeFuncPhase { ~MeDoLoopCanon() = default; - AnalysisResult *Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr *mrm) override; + AnalysisResult *Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr*) override; std::string PhaseName() const override { return "loopcanon"; } private: using Key = std::pair; + std::map> heads; void Convert(MeFunction &func, BB &bb, BB &pred, MapleMap &swapSuccs); bool NeedConvert(BB &bb, BB &pred, MapleAllocator &alloc, MapleMap &swapSuccs) const; + void FindHeadBBs(MeFunction &func, Dominance &dom, BB *bb); + bool IsDoWhileLoop(const LoopDesc &loop) const; + void Merge(MeFunction &func); + void AddPreheader(MeFunction &func); + void InsertNewExitBB(MeFunction &func, LoopDesc &loop); + void InsertExitBB(MeFunction &func, LoopDesc &loop); + void SplitCondGotBB(MeFunction &func, LoopDesc &loop); + void ExecuteLoopCanon(MeFunction &func, MeFuncResultMgr &m, Dominance &dom); + void ExecuteLoopNormalization(MeFunction &func, MeFuncResultMgr *m, Dominance &dom); }; } // namespace maple #endif // MAPLE_ME_INCLUDE_MELOOPCANON_H diff --git a/src/maple_me/src/me_loop_analysis.cpp b/src/maple_me/src/me_loop_analysis.cpp index a53e34d57999b83c21f2c1cda595ef6e9e94139e..f29d4889867e235a33548034017401aff18b2f49 100644 --- a/src/maple_me/src/me_loop_analysis.cpp +++ b/src/maple_me/src/me_loop_analysis.cpp @@ -38,6 +38,47 @@ void IdentifyLoops::SetLoopParent4BB(const BB &bb, LoopDesc &loopDesc) { bbLoopParent[bb.GetBBId()] = &loopDesc; } +void IdentifyLoops::InsertExitBB(LoopDesc &loop) { + std::set traveledBBs; + std::queue inLoopBBs; + inLoopBBs.push(loop.head); + CHECK_FATAL(loop.inloopBB2exitBBs.empty(), "inloopBB2exitBBs must be empty"); + while (!inLoopBBs.empty()) { + BB *curBB = inLoopBBs.front(); + inLoopBBs.pop(); + for (BB *succ : curBB->GetSucc()) { + if (traveledBBs.count(succ) != 0) { + continue; + } + if (loop.Has(*succ)) { + inLoopBBs.push(succ); + traveledBBs.insert(succ); + } else { + loop.InsertInloopBB2exitBBs(*curBB, *succ); + } + if (curBB->GetKind() == kBBCondGoto) { + if (curBB->GetSucc().size() == 1) { + // When the size of succs is one, one of succs may be commonExitBB. Need insert to loopBB2exitBBs. + CHECK_FATAL(false, "return bb"); + } + } else if (!curBB->GetStmtNodes().empty() && curBB->GetLast().GetOpCode() == OP_return) { + CHECK_FATAL(false, "return bb"); + } + } + } + for (auto pair : loop.inloopBB2exitBBs) { + MapleVector *succBB = pair.second; + for (auto it : *succBB) { + for (auto pred : it->GetPred()) { + if (!loop.Has(*pred)) { + loop.inloopBB2exitBBs.clear(); + return; + } + } + } + } +} + // process each BB in preorder traversal of dominator tree void IdentifyLoops::ProcessBB(BB *bb) { if (bb == nullptr || bb == func.GetCommonExitBB()) { @@ -98,12 +139,90 @@ void IdentifyLoops::MarkBB() { } } +void IdentifyLoops::SetTryBB() { + for (auto loop : meLoops) { + for (auto pred : loop->head->GetPred()) { + if (pred->GetAttributes(kBBAttrIsTry)) { + loop->SetHasTryBB(true); + break; + } + } + if (loop->HasTryBB()) { + continue; + } + for (auto bbId : loop->loopBBs) { + BB *bb = func.GetBBFromID(bbId); + if (bb->GetAttributes(kBBAttrIsTry) || bb->GetAttributes(kBBAttrWontExit)) { + loop->SetHasTryBB(true); + break; + } + } + } +} + +bool IdentifyLoops::ProcessPreheaderAndLatch(LoopDesc &loop) { + // If predsize of head is one, it means that one is entry bb. + if (loop.head->GetPred().size() == 1) { + CHECK_FATAL(func.GetCommonEntryBB()->GetSucc(0) == loop.head, "succ of entry bb must be head"); + loop.preheader = func.GetCommonEntryBB(); + CHECK_FATAL(!loop.head->GetPred(0)->GetAttributes(kBBAttrIsTry), "must not be kBBAttrIsTry"); + loop.latch = loop.head->GetPred(0); + return true; + } + /* for example: GetInstance.java : 152 + * There are two loop in identifyLoops, and one has no try no catch. + * In loop canon whould ont merge loops with latch bb. + * for () { + * if () { + * do somthing + * continue + * } + * try { + * do somthing + * } catch (NoSuchAlgorithmException e) { + * do somthing + * } + * } + */ + if (loop.head->GetPred().size() != 2) { // Head must has two preds. + loop.SetIsCanonicalLoop(false); + loop.SetHasTryBB(true); + return false; + } + if (!loop.Has(*loop.head->GetPred(0))) { + loop.preheader = loop.head->GetPred(0); + CHECK_FATAL(loop.preheader->GetKind() == kBBFallthru, "must be kBBFallthru"); + CHECK_FATAL(loop.Has(*loop.head->GetPred(1)), "must be latch bb"); + loop.latch = loop.head->GetPred(1); + CHECK_FATAL(!loop.latch->GetAttributes(kBBAttrIsTry), "must not be kBBAttrIsTry"); + return true; + } else { + loop.latch = loop.head->GetPred(0); + CHECK_FATAL(!loop.latch->GetAttributes(kBBAttrIsTry), "must not be kBBAttrIsTry"); + CHECK_FATAL(!loop.Has(*loop.head->GetPred(1)), "must be latch preheader bb"); + loop.preheader = loop.head->GetPred(1); + CHECK_FATAL(loop.preheader->GetKind() == kBBFallthru, "must be kBBFallthru"); + return true; + } +} + AnalysisResult *MeDoMeLoop::Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr*) { auto *dom = static_cast(m->GetAnalysisResult(MeFuncPhase_DOMINANCE, func)); ASSERT(dom != nullptr, "dominance phase has problem"); MemPool *meLoopMp = NewMemPool(); IdentifyLoops *identLoops = meLoopMp->New(meLoopMp, *func, dom); identLoops->ProcessBB(func->GetCommonEntryBB()); + identLoops->SetTryBB(); + for (auto loop : identLoops->GetMeLoops()) { + if (loop->HasTryBB()) { + continue; + } + if (!identLoops->ProcessPreheaderAndLatch(*loop)) { + continue; + } + identLoops->InsertExitBB(*loop); + loop->SetIsCanonicalLoop(loop->inloopBB2exitBBs.size() == 0 ? false : true); + } if (DEBUGFUNC(func)) { identLoops->Dump(); } diff --git a/src/maple_me/src/me_loop_canon.cpp b/src/maple_me/src/me_loop_canon.cpp index a75d378f4b96bc090956d026685d5a5f7f26a1c5..7f3ceafea18d1a26806d395b35033bb04885627f 100644 --- a/src/maple_me/src/me_loop_canon.cpp +++ b/src/maple_me/src/me_loop_canon.cpp @@ -179,14 +179,12 @@ void MeDoLoopCanon::Convert(MeFunction &func, BB &bb, BB &pred, MapleMap(m->GetAnalysisResult(MeFuncPhase_DOMINANCE, func)); - ASSERT(dom != nullptr, "dom is null in MeDoLoopCanon::Run"); +void MeDoLoopCanon::ExecuteLoopCanon(MeFunction &func, MeFuncResultMgr &m, Dominance &dom) { // set MeCFG's has_do_while flag - MeCFG *cfg = func->GetTheCfg(); - auto eIt = func->valid_end(); - for (auto bIt = func->valid_begin(); bIt != eIt; ++bIt) { - if (bIt == func->common_entry() || bIt == func->common_exit()) { + MeCFG *cfg = func.GetTheCfg(); + auto eIt = func.valid_end(); + for (auto bIt = func.valid_begin(); bIt != eIt; ++bIt) { + if (bIt == func.common_entry() || bIt == func.common_exit()) { continue; } auto *bb = *bIt; @@ -202,7 +200,7 @@ AnalysisResult *MeDoLoopCanon::Run(MeFunction *func, MeFuncResultMgr *m, ModuleR continue; } BB *brTargetbb = bb->GetSucc(1); - if (dom->Dominate(*brTargetbb, *bb)) { + if (dom.Dominate(*brTargetbb, *bb)) { cfg->SetHasDoWhile(true); break; } @@ -211,20 +209,20 @@ AnalysisResult *MeDoLoopCanon::Run(MeFunction *func, MeFuncResultMgr *m, ModuleR MapleVector> backEdges(localAlloc.Adapter()); MapleMap swapSuccs(std::less(), localAlloc.Adapter()); // collect backedge first: if bb dominator its pred, then the edge pred->bb is a backedge - eIt = func->valid_end(); - for (auto bIt = func->valid_begin(); bIt != eIt; ++bIt) { - if (bIt == func->common_entry() || bIt == func->common_exit()) { + eIt = func.valid_end(); + for (auto bIt = func.valid_begin(); bIt != eIt; ++bIt) { + if (bIt == func.common_entry() || bIt == func.common_exit()) { continue; } auto *bb = *bIt; const MapleVector &preds = bb->GetPred(); for (BB *pred : preds) { - ASSERT(func->GetCommonEntryBB() != nullptr, "impossible"); + ASSERT(func.GetCommonEntryBB() != nullptr, "impossible"); ASSERT_NOT_NULL(pred); // bb is reachable from entry && bb dominator pred - if (dom->Dominate(*func->GetCommonEntryBB(), *bb) && dom->Dominate(*bb, *pred) && + if (dom.Dominate(*func.GetCommonEntryBB(), *bb) && dom.Dominate(*bb, *pred) && !pred->GetAttributes(kBBAttrWontExit) && (NeedConvert(*bb, *pred, localAlloc, swapSuccs))) { - if (DEBUGFUNC(func)) { + if (DEBUGFUNC(&func)) { LogInfo::MapleLogger() << "find backedge " << bb->GetBBId() << " <-- " << pred->GetBBId() << '\n'; } backEdges.push_back(std::make_pair(bb, pred)); @@ -244,23 +242,347 @@ AnalysisResult *MeDoLoopCanon::Run(MeFunction *func, MeFuncResultMgr *m, ModuleR // sort(backEdges.begin(), backEdges.end(), CompareBackedge); if (!backEdges.empty()) { - if (DEBUGFUNC(func)) { + if (DEBUGFUNC(&func)) { LogInfo::MapleLogger() << "-----------------Dump mefunction before loop convert----------\n"; - func->Dump(true); + func.Dump(true); } for (auto it = backEdges.begin(); it != backEdges.end(); ++it) { BB *bb = it->first; BB *pred = it->second; ASSERT(bb != nullptr, "bb should not be nullptr"); ASSERT(pred != nullptr, "pred should not be nullptr"); - Convert(*func, *bb, *pred, swapSuccs); - if (DEBUGFUNC(func)) { + Convert(func, *bb, *pred, swapSuccs); + if (DEBUGFUNC(&func)) { LogInfo::MapleLogger() << "-----------------Dump mefunction after loop convert-----------\n"; - func->Dump(true); + func.Dump(true); } } - m->InvalidAnalysisResult(MeFuncPhase_DOMINANCE, func); + m.InvalidAnalysisResult(MeFuncPhase_DOMINANCE, &func); + } +} + +// Only when backege or preheader is not try bb, update head map. +void MeDoLoopCanon::FindHeadBBs(MeFunction &func, Dominance &dom, BB *bb) { + if (bb == nullptr || bb == func.GetCommonExitBB()) { + return; + } + bool hasTry = false; + for (BB *pred : bb->GetPred()) { + // backege or preheader is try bb + if (pred->GetAttributes(kBBAttrIsTry)) { + hasTry = true; + } + } + if (!hasTry) { + for (BB *pred : bb->GetPred()) { + // add backege bb + if (dom.Dominate(*bb, *pred)) { + if (heads.find(bb) != heads.end()) { + heads[bb].push_back(pred); + } else { + std::vector tails; + tails.push_back(pred); + heads[bb] = tails; + } + } + } + } + const MapleSet &domChildren = dom.GetDomChildren(bb->GetBBId()); + for (auto bbit = domChildren.begin(); bbit != domChildren.end(); ++bbit) { + FindHeadBBs(func, dom, func.GetAllBBs().at(*bbit)); } +} + +// merge backedges with the same headBB +void MeDoLoopCanon::Merge(MeFunction &func) { + for (auto iter = heads.begin(); iter != heads.end(); ++iter) { + BB *head = iter->first; + auto *latchBB = func.NewBasicBlock(); + latchBB->SetAttributes(kBBAttrArtificial); + latchBB->SetKind(kBBFallthru); + for (BB *tail : iter->second) { + tail->ReplaceSucc(head, latchBB); + if (tail->GetStmtNodes().empty()) { + continue; + } + if (tail->GetKind() == kBBCondGoto) { + CondGotoNode &condGotoNode = static_cast(tail->GetStmtNodes().back()); + LabelIdx oldlabIdx = condGotoNode.GetOffset(); + if (oldlabIdx == head->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*latchBB); + condGotoNode.SetOffset(label); + } + } else if (tail->GetKind() == kBBGoto) { + GotoNode &gotoStmt = static_cast(tail->GetStmtNodes().back()); + LabelIdx oldlabIdx = gotoStmt.GetOffset(); + if (oldlabIdx == head->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*latchBB); + gotoStmt.SetOffset(label); + } + } else if (tail->GetKind() == kBBSwitch) { + SwitchNode &switchNode = static_cast(tail->GetStmtNodes().back()); + if (switchNode.GetDefaultLabel() == head->GetBBLabel()) { + switchNode.SetDefaultLabel(func.GetOrCreateBBLabel(*latchBB)); + } + for (size_t i = 0; i < switchNode.GetSwitchTable().size(); ++i) { + LabelIdx labelIdx = switchNode.GetCasePair(i).second; + if (labelIdx == head->GetBBLabel()) { + switchNode.UpdateCaseLabelAt(i, func.GetOrCreateBBLabel(*latchBB)); + } + } + } else if (tail->GetKind() != kBBFallthru) { + CHECK_FATAL(false, "can not support"); + } + } + head->AddPred(*latchBB); + } +} + +void MeDoLoopCanon::AddPreheader(MeFunction &func) { + for (auto iter = heads.begin(); iter != heads.end(); ++iter) { + BB *head = iter->first; + std::vector preds; + for (BB *pred : head->GetPred()) { + // FindHeadBBs has filtered out this possibility. + CHECK_FATAL(!pred->GetAttributes(kBBAttrIsTry), "can not support kBBAttrIsTry"); + if (std::find(iter->second.begin(), iter->second.end(), pred) == iter->second.end()) { + preds.push_back(pred); + } + } + // If the num of backages is zero or one and bb kind is kBBFallthru, Preheader is already canonical. + if (preds.empty()) { + continue; + } + if (preds.size() == 1 && preds.front()->GetKind() == kBBFallthru) { + continue; + } + // add preheader + auto *preheader = func.NewBasicBlock(); + preheader->SetAttributes(kBBAttrArtificial); + preheader->SetKind(kBBFallthru); + for (BB *pred : preds) { + pred->ReplaceSucc(head, preheader); + if (pred->GetStmtNodes().empty()) { + continue; + } + if (pred->GetKind() == kBBCondGoto) { + CondGotoNode &condGotoNode = static_cast(pred->GetStmtNodes().back()); + LabelIdx oldlabIdx = condGotoNode.GetOffset(); + if (oldlabIdx == head->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*preheader); + condGotoNode.SetOffset(label); + } + } else if (pred->GetKind() == kBBGoto) { + GotoNode &gotoStmt = static_cast(pred->GetStmtNodes().back()); + LabelIdx oldlabIdx = gotoStmt.GetOffset(); + if (oldlabIdx == head->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*preheader); + gotoStmt.SetOffset(label); + } + } else if (pred->GetKind() == kBBSwitch) { + SwitchNode &switchNode = static_cast(pred->GetStmtNodes().back()); + if (switchNode.GetDefaultLabel() == head->GetBBLabel()) { + switchNode.SetDefaultLabel(func.GetOrCreateBBLabel(*preheader)); + } + for (size_t i = 0; i < switchNode.GetSwitchTable().size(); ++i) { + LabelIdx labelIdx = switchNode.GetCasePair(i).second; + if (labelIdx == head->GetBBLabel()) { + switchNode.UpdateCaseLabelAt(i, func.GetOrCreateBBLabel(*preheader)); + } + } + } else if (pred->GetKind() != kBBFallthru) { + CHECK_FATAL(false, "can not support"); + } + } + head->AddPred(*preheader); + } +} + +void MeDoLoopCanon::InsertNewExitBB(MeFunction &func, LoopDesc &loop) { + for (auto pair : loop.inloopBB2exitBBs) { + BB *curBB = pair.first; + for (auto succBB : *pair.second) { + bool needNewExitBB = false; + for (auto pred : succBB->GetPred()) { + if (!loop.Has(*pred)) { + needNewExitBB = true; + } + } + if (!needNewExitBB) { + continue; + } else { + BB *newExitBB = func.NewBasicBlock(); + newExitBB->SetKind(kBBFallthru); + size_t index = succBB->GetPred().size(); + while (index > 0) { + if (succBB->GetPred(index - 1) == curBB) { + break; + } + --index; + } + curBB->ReplaceSucc(succBB, newExitBB); + --index; + succBB->AddPred(*newExitBB, index); + + loop.ReplaceInloopBB2exitBBs(*curBB, *succBB, *newExitBB); + if (curBB->GetStmtNodes().empty()) { + continue; + } + StmtNode *lastStmt = &(curBB->GetStmtNodes().back()); + if ((lastStmt->GetOpCode() == OP_brtrue || lastStmt->GetOpCode() == OP_brfalse) && + static_cast(lastStmt)->GetOffset() == succBB->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*newExitBB); + static_cast(lastStmt)->SetOffset(label); + } else if (lastStmt->GetOpCode() == OP_goto && + static_cast(lastStmt)->GetOffset() == succBB->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*newExitBB); + static_cast(lastStmt)->SetOffset(label); + } + } + } + } +} + +void MeDoLoopCanon::InsertExitBB(MeFunction &func, LoopDesc &loop) { + std::set traveledBBs; + std::queue inLoopBBs; + inLoopBBs.push(loop.head); + CHECK_FATAL(loop.inloopBB2exitBBs.empty(), "inloopBB2exitBBs must be empty"); + while (!inLoopBBs.empty()) { + BB *curBB = inLoopBBs.front(); + inLoopBBs.pop(); + for (BB *succ : curBB->GetSucc()) { + if (traveledBBs.count(succ) != 0) { + continue; + } + if (loop.Has(*succ)) { + inLoopBBs.push(succ); + traveledBBs.insert(succ); + } else { + loop.InsertInloopBB2exitBBs(*curBB, *succ); + } + if (curBB->GetKind() == kBBCondGoto) { + if (curBB->GetSucc().size() == 1) { + CHECK_FATAL(false, "return bb"); + loop.InsertInloopBB2exitBBs(*curBB, *func.GetCommonExitBB()); + } + } else if (!curBB->GetStmtNodes().empty() && curBB->GetLast().GetOpCode() == OP_return) { + CHECK_FATAL(false, "return bb"); + loop.InsertInloopBB2exitBBs(*curBB, *func.GetCommonExitBB()); + } + } + } + InsertNewExitBB(func, loop); +} + +void MeDoLoopCanon::SplitCondGotBB(MeFunction &func, LoopDesc &loop) { + auto exitBB = loop.inloopBB2exitBBs.begin()->first; + StmtNode *lastStmt = &(exitBB->GetStmtNodes().back()); + if (lastStmt->GetOpCode() != OP_brfalse && lastStmt->GetOpCode() != OP_brtrue && lastStmt->GetOpCode() != OP_switch) { + CHECK_FATAL(false, "must be OP_brfalse, OP_brtrue or OP_switch"); + } + bool notOnlyHasBrStmt = true; + for (auto &stmt : exitBB->GetStmtNodes()) { + if (&stmt != &exitBB->GetLast()) { + notOnlyHasBrStmt = false; + break; + } + } + if (notOnlyHasBrStmt) { + return; + } + BB *newFallthru = func.NewBasicBlock(); + newFallthru->SetKind(kBBFallthru); + newFallthru->SetAttributes(kBBAttrIsInLoop); + func.CloneBasicBlock(*newFallthru, *exitBB); + newFallthru->RemoveLastStmt(); + for (auto &stmt : exitBB->GetStmtNodes()) { + if (&stmt != &exitBB->GetLast()) { + exitBB->RemoveStmtNode(&stmt); + } + } + while (exitBB->GetPred().size() > 0) { + auto *pred = exitBB->GetPred(0); + pred->ReplaceSucc(exitBB, newFallthru); + if (pred->GetStmtNodes().empty()) { + continue; + } + StmtNode *lastStmt = &(pred->GetStmtNodes().back()); + if ((lastStmt->GetOpCode() == OP_brtrue || lastStmt->GetOpCode() == OP_brfalse) && + static_cast(lastStmt)->GetOffset() == exitBB->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*newFallthru); + static_cast(lastStmt)->SetOffset(label); + } else if (lastStmt->GetOpCode() == OP_goto && + static_cast(lastStmt)->GetOffset() == exitBB->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*newFallthru); + static_cast(lastStmt)->SetOffset(label); + } + } + exitBB->RemoveAllPred(); + newFallthru->AddSucc(*exitBB); +} + +bool MeDoLoopCanon::IsDoWhileLoop(const LoopDesc &loop) const { + for (auto succ : loop.head->GetSucc()) { + if (!loop.Has(*succ)) { + return false; + } + } + auto exitBB = loop.inloopBB2exitBBs.begin()->first; + for (auto pred : exitBB->GetPred()) { + if (!loop.Has(*pred)) { + return false; + } + } + return true; +} + +void MeDoLoopCanon::ExecuteLoopNormalization(MeFunction &func, MeFuncResultMgr *m, Dominance &dom) { + if (DEBUGFUNC(&func)) { + LogInfo::MapleLogger() << "-----------------Dump mefunction before loop normalization----------\n"; + func.Dump(true); + func.GetTheCfg()->DumpToFile("cfgbeforLoopNormalization"); + } + heads.clear(); + FindHeadBBs(func, dom, func.GetCommonEntryBB()); + AddPreheader(func); + Merge(func); + m->InvalidAnalysisResult(MeFuncPhase_DOMINANCE, &func); + m->InvalidAnalysisResult(MeFuncPhase_MELOOP, &func); + IdentifyLoops *meLoop = static_cast(m->GetAnalysisResult(MeFuncPhase_MELOOP, &func)); + if (meLoop == nullptr) { + return; + } + for (auto loop : meLoop->GetMeLoops()) { + if (loop->HasTryBB()) { + continue; + } + + if (!loop->IsCanonicalLoop()) { + CHECK_FATAL(loop->inloopBB2exitBBs.size() == 0, "must be zero"); + InsertExitBB(func, *loop); + loop->SetIsCanonicalLoop(true); + } + if (loop->inloopBB2exitBBs.size() == 1 && loop->inloopBB2exitBBs.begin()->second->size() == 1 && + IsDoWhileLoop(*loop)) { + SplitCondGotBB(func, *loop); + } + } + if (DEBUGFUNC(&func)) { + LogInfo::MapleLogger() << "-----------------Dump mefunction after loop normalization-----------\n"; + func.Dump(true); + func.GetTheCfg()->DumpToFile("cfgafterLoopNormalization"); + } + m->InvalidAnalysisResult(MeFuncPhase_DOMINANCE, &func); + m->InvalidAnalysisResult(MeFuncPhase_MELOOP, &func); +} + +AnalysisResult *MeDoLoopCanon::Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr*) { + auto *dom = static_cast(m->GetAnalysisResult(MeFuncPhase_DOMINANCE, func)); + ASSERT(dom != nullptr, "dom is null in MeDoLoopCanon::Run"); + ExecuteLoopCanon(*func, *m, *dom); + dom = static_cast(m->GetAnalysisResult(MeFuncPhase_DOMINANCE, func)); + ExecuteLoopNormalization(*func, m, *dom); return nullptr; } } // namespace maple diff --git a/src/maple_util/include/profile.h b/src/maple_util/include/profile.h index bd570830cf6e2f96945ae0b0b9e0e3170ec52676..910986fd1d2037e0e610a33b32de45e5b348ec68 100644 --- a/src/maple_util/include/profile.h +++ b/src/maple_util/include/profile.h @@ -75,6 +75,10 @@ class Profile { Profile(); ~Profile() = default; + bool IsValid() const { + return valid; + } + private: bool valid = false; bool initialized = false;