diff --git a/src/mapleall/maple_ir/include/mir_lower.h b/src/mapleall/maple_ir/include/mir_lower.h index e87659da2352c501f7eecb1336620744624eb4ae..ccf539e09c202d7740e058c5c5ac6f25821e13ef 100644 --- a/src/mapleall/maple_ir/include/mir_lower.h +++ b/src/mapleall/maple_ir/include/mir_lower.h @@ -102,6 +102,14 @@ class MIRLower { lowerPhase |= kShiftLowerCG; } + uint8 GetOptLevel() { + return optLevel; + } + + void SetOptLevel(uint8 optlvl) { + optLevel = optlvl; + } + bool IsLowerME() const { return lowerPhase & kShiftLowerMe; } @@ -132,6 +140,7 @@ class MIRLower { MIRFunction *mirFunc; MIRBuilder *mirBuilder = nullptr; uint32 lowerPhase = 0; + uint8 optLevel = 0; LabelIdx CreateCondGotoStmt(Opcode op, BlockNode &blk, const IfStmtNode &ifStmt); void CreateBrFalseStmt(BlockNode &blk, const IfStmtNode &ifStmt); void CreateBrTrueStmt(BlockNode &blk, const IfStmtNode &ifStmt); diff --git a/src/mapleall/maple_ir/include/mir_nodes.h b/src/mapleall/maple_ir/include/mir_nodes.h index 3ed37aea5094f4e41f8653dd1e5e4e6c5cde70dc..a242e39288a514dd7cb33886a418a5f8285253e3 100644 --- a/src/mapleall/maple_ir/include/mir_nodes.h +++ b/src/mapleall/maple_ir/include/mir_nodes.h @@ -201,6 +201,10 @@ class BaseNode : public BaseNodeT { virtual bool IsSSANode() const { return false; } + + virtual bool IsSameContent(BaseNode* node) const { + return false; + } }; class UnaryNode : public BaseNode { @@ -248,6 +252,8 @@ class UnaryNode : public BaseNode { return true; } + bool IsSameContent(BaseNode* node) const override; + private: BaseNode *uOpnd = nullptr; }; @@ -284,6 +290,8 @@ class TypeCvtNode : public UnaryNode { fromPrimType = from; } + bool IsSameContent(BaseNode* node) const override; + private: PrimType fromPrimType = kPtyInvalid; }; @@ -489,6 +497,8 @@ class IreadNode : public UnaryNode { fieldID = fieldIDVal; } + bool IsSameContent(BaseNode* node) const override; + // the base of an address expr is either a leaf or an iread BaseNode &GetAddrExprBase() const { BaseNode *base = Opnd(0); @@ -537,6 +547,8 @@ class IreadoffNode : public UnaryNode { offset = offsetValue; } + bool IsSameContent(BaseNode* node) const override; + private: int32 offset = 0; }; @@ -565,6 +577,8 @@ class IreadFPoffNode : public BaseNode { offset = offsetValue; } + bool IsSameContent(BaseNode* node) const override; + private: int32 offset = 0; }; @@ -598,6 +612,8 @@ class BinaryOpnds { bOpnd[i] = node; } + bool IsSameContent(BaseNode* node) const; + private: BaseNode *bOpnd[kOperandNumBinary]; }; @@ -662,6 +678,7 @@ class BinaryNode : public BaseNode, public BinaryOpnds { bool IsBinaryNode() const override { return true; } + bool IsSameContent(BaseNode* node) const override; }; class CompareNode : public BinaryNode { @@ -1024,6 +1041,7 @@ class ConstvalNode : public BaseNode { constVal = val; } + bool IsSameContent(BaseNode* node) const override; private: MIRConst *constVal = nullptr; }; @@ -1279,6 +1297,8 @@ class AddrofNode : public BaseNode { } bool IsVolatile(const MIRModule &mod) const; + + bool IsSameContent(BaseNode* node) const override; private: StIdx stIdx; FieldID fieldID = 0; @@ -1302,6 +1322,9 @@ class DreadoffNode : public BaseNode { } bool IsVolatile(const MIRModule &mod) const; + + bool IsSameContent(BaseNode* node) const override; + public: StIdx stIdx; int32 offset = 0; @@ -1336,6 +1359,7 @@ class RegreadNode : public BaseNode { regIdx = reg; } + bool IsSameContent(BaseNode* node) const override; private: PregIdx regIdx = 0; // 32bit, negative if special register }; @@ -1363,6 +1387,7 @@ class AddroffuncNode : public BaseNode { puIdx = puIdxValue; } + bool IsSameContent(BaseNode* node) const override; private: PUIdx puIdx = 0; // 32bit now }; @@ -1390,6 +1415,7 @@ class AddroflabelNode : public BaseNode { offset = offsetValue; } + bool IsSameContent(BaseNode* node) const override; private: LabelIdx offset = 0; }; diff --git a/src/mapleall/maple_ir/src/mir_lower.cpp b/src/mapleall/maple_ir/src/mir_lower.cpp index 161c6039c285460e73287026bd6cc929ca659b9a..fbecc04b6fd5ecc2447a50c7464b56f56e96f82f 100644 --- a/src/mapleall/maple_ir/src/mir_lower.cpp +++ b/src/mapleall/maple_ir/src/mir_lower.cpp @@ -14,6 +14,7 @@ */ #include "mir_lower.h" #include "constantfold.h" +#include "ext_constantfold.h" #define DO_LT_0_CHECK 1 @@ -560,6 +561,11 @@ do { } void MIRLower::LowerFunc(MIRFunction &func) { + if (GetOptLevel() > 0) { + ExtConstantFold ecf(func.GetModule()); + (void)ecf.ExtSimplify(func.GetBody());; + } + mirModule.SetCurFunction(&func); if (IsLowerExpandArray()) { ExpandArrayMrt(func); diff --git a/src/mapleall/maple_ir/src/mir_nodes.cpp b/src/mapleall/maple_ir/src/mir_nodes.cpp index 7c23235f6872b04d7a780ece8cc98e522ecda26f..86e4686a2b55f6a887f0307857bb6496ed17385f 100644 --- a/src/mapleall/maple_ir/src/mir_nodes.cpp +++ b/src/mapleall/maple_ir/src/mir_nodes.cpp @@ -2341,4 +2341,165 @@ SafetyCallCheckStmtNode::SafetyCallCheckStmtNode(const std::string &funcName, si std::string SafetyCallCheckStmtNode::GetFuncName() const { return GlobalTables::GetStrTable().GetStringFromStrIdx(funcNameIdx); } + +bool UnaryNode::IsSameContent(BaseNode* node) const { + UnaryNode *unaryNode = dynamic_cast(node); + if ((this == unaryNode) || + (unaryNode && (GetOpCode() == unaryNode->GetOpCode()) && + (GetPrimType() == unaryNode->GetPrimType()) && + (uOpnd && unaryNode->Opnd(0) && uOpnd->IsSameContent(unaryNode->Opnd(0))))) { + return true; + } else { + return false; + } +} + +bool TypeCvtNode::IsSameContent(BaseNode* node) const { + TypeCvtNode *tyCvtNode = dynamic_cast(node); + if ((this == tyCvtNode) || + (tyCvtNode && (fromPrimType == tyCvtNode->FromType()) && + UnaryNode::IsSameContent(tyCvtNode))) { + return true; + } else { + return false; + } +} + +bool IreadNode::IsSameContent(BaseNode* node) const { + IreadNode *ireadNode = dynamic_cast(node); + if ((this == ireadNode) || + (ireadNode && (tyIdx == ireadNode->GetTyIdx()) && + (fieldID == ireadNode->GetFieldID()) && + UnaryNode::IsSameContent(ireadNode))) { + return true; + } else { + return false; + } +} + +bool IreadoffNode::IsSameContent(BaseNode* node) const { + IreadoffNode *ireadoffNode = dynamic_cast(node); + if ((this == ireadoffNode) || + (ireadoffNode && (GetOffset() == ireadoffNode->GetOffset()) && + UnaryNode::IsSameContent(ireadoffNode))) { + return true; + } else { + return false; + } +} + +bool IreadFPoffNode::IsSameContent(BaseNode* node) const { + IreadFPoffNode *ireadFPoffNode = dynamic_cast(node); + if ((this == ireadFPoffNode) || + (ireadFPoffNode && (GetOpCode() == ireadFPoffNode->GetOpCode()) && + (GetPrimType() == ireadFPoffNode->GetPrimType()) && + (GetOffset() == ireadFPoffNode->GetOffset()))) { + return true; + } else { + return false; + } +} + +bool BinaryOpnds::IsSameContent(BaseNode* node) const { + BinaryOpnds *binaryOpnds = dynamic_cast(node); + if ((this == binaryOpnds) || + (binaryOpnds && + GetBOpnd(0)->IsSameContent(binaryOpnds->GetBOpnd(0)) && + GetBOpnd(1)->IsSameContent(binaryOpnds->GetBOpnd(1)))) { + return true; + } else { + return false; + } +} + +bool BinaryNode::IsSameContent(BaseNode* node) const { + BinaryNode *binaryNode = dynamic_cast(node); + if ((this == binaryNode) || + (binaryNode && + (GetOpCode() == binaryNode->GetOpCode()) && + (GetPrimType() == binaryNode->GetPrimType()) && + BinaryOpnds::IsSameContent(binaryNode))) { + return true; + } else { + return false; + } +} + +bool ConstvalNode::IsSameContent(BaseNode* node) const { + ConstvalNode *constvalNode = dynamic_cast(node); + if ((this == constvalNode) || + (constvalNode && + //(GetOpCode() == constvalNode->GetOpCode()) && + //(GetPrimType() == constvalNode->GetPrimType()) && + GetConstVal()->GetKind() == kConstInt && + constvalNode->GetConstVal()->GetKind() == kConstInt && + static_cast(const_cast(GetConstVal()))->GetValue() == + static_cast(const_cast(constvalNode->GetConstVal()))->GetValue())) { + return true; + } else { + // make it false for now on kinds other than kConstInt + return false; + } +} + +bool AddrofNode::IsSameContent(BaseNode* node) const { + AddrofNode *addrofNode = dynamic_cast(node); + if ((this == addrofNode) || + (addrofNode && (GetOpCode() == addrofNode->GetOpCode()) && + (GetPrimType() == addrofNode->GetPrimType()) && + (GetNumOpnds() == addrofNode->GetNumOpnds()) && + (stIdx.FullIdx() == addrofNode->GetStIdx().FullIdx()) && + (fieldID == addrofNode->GetFieldID()))) { + return true; + } else { + return false; + } +} + +bool DreadoffNode::IsSameContent(BaseNode* node) const { + DreadoffNode *dreaddoffNode = dynamic_cast(node); + if ((this == dreaddoffNode) || + (dreaddoffNode && (GetOpCode() == dreaddoffNode->GetOpCode()) && + (GetPrimType() == dreaddoffNode->GetPrimType()) && (stIdx == dreaddoffNode->stIdx) && + (offset == dreaddoffNode->offset))) { + return true; + } else { + return false; + } +} + +bool RegreadNode::IsSameContent(BaseNode* node) const { + RegreadNode *regreadNode = dynamic_cast(node); + if ((this == regreadNode) || + (regreadNode && (GetOpCode() == regreadNode->GetOpCode()) && + (GetPrimType() == regreadNode->GetPrimType()) && (regIdx == regreadNode->GetRegIdx()))) { + return true; + } else { + return false; + } +} + +bool AddroffuncNode::IsSameContent(BaseNode* node) const { + AddroffuncNode *addroffuncNode = dynamic_cast(node); + if ((this == addroffuncNode) || + (addroffuncNode && (GetOpCode() == addroffuncNode->GetOpCode()) && + (GetPrimType() == addroffuncNode->GetPrimType()) && + (puIdx == addroffuncNode->GetPUIdx()))) { + return true; + } else { + return false; + } +} + +bool AddroflabelNode::IsSameContent(BaseNode* node) const { + AddroflabelNode *addroflabelNode = dynamic_cast(node); + if ((this == addroflabelNode) || + (addroflabelNode && (GetOpCode() == addroflabelNode->GetOpCode()) && + (GetPrimType() == addroflabelNode->GetPrimType()) && + (offset == addroflabelNode->GetOffset()))) { + return true; + } else { + return false; + } +} } // namespace maple diff --git a/src/mapleall/maple_me/src/me_function.cpp b/src/mapleall/maple_me/src/me_function.cpp index 15d319a6adc11b66b6f0b8dc2cb39416ab3a42ec..224b6afd4fa7ab8c070267f1e1b4669b32e94ffc 100644 --- a/src/mapleall/maple_me/src/me_function.cpp +++ b/src/mapleall/maple_me/src/me_function.cpp @@ -140,6 +140,7 @@ void MeFunction::Prepare() { MIRLower mirLowerer(mirModule, CurFunction()); mirLowerer.Init(); mirLowerer.SetLowerME(); + mirLowerer.SetOptLevel(MeOption::optLevel); if (mirModule.IsJavaModule()) { mirLowerer.SetLowerExpandArray(); } diff --git a/src/mapleall/mpl2mpl/BUILD.gn b/src/mapleall/mpl2mpl/BUILD.gn index 27a83fcb8c0ee307d4f490c2bbafb5cb30f5f416..8ade758e9f51d98a614f2ee0583a943f9d8c73ee 100755 --- a/src/mapleall/mpl2mpl/BUILD.gn +++ b/src/mapleall/mpl2mpl/BUILD.gn @@ -41,6 +41,7 @@ src_libmpl2mpl = [ "src/class_hierarchy.cpp", "src/class_hierarchy_phase.cpp", "src/constantfold.cpp", + "src/ext_constantfold.cpp", "src/coderelayout.cpp", "src/annotation_analysis.cpp", "src/preme.cpp", diff --git a/src/mapleall/mpl2mpl/include/ext_constantfold.h b/src/mapleall/mpl2mpl/include/ext_constantfold.h new file mode 100644 index 0000000000000000000000000000000000000000..ac1d8e55b2af3c73106d0bf8846f2d20182523bc --- /dev/null +++ b/src/mapleall/mpl2mpl/include/ext_constantfold.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) [2021] Futurewei Technologies Co., Ltd. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 Mulan PSL v2 for more details. + */ +#ifndef MPL2MPL_INCLUDE_EXTCONSTANTFOLD_H +#define MPL2MPL_INCLUDE_EXTCONSTANTFOLD_H +#include "mir_nodes.h" +#include "phase_impl.h" + +namespace maple { +class ExtConstantFold { + public: + explicit ExtConstantFold(MIRModule *mod) : mirModule(mod) {} + StmtNode *ExtSimplify(StmtNode *node); + BaseNode *Fold(BaseNode *node); + BaseNode *FoldIor(BinaryNode *node); + StmtNode *ExtSimplifyBlock(BlockNode *node); + StmtNode *ExtSimplifyIf(IfStmtNode *node); + StmtNode *ExtSimplifyDassign(DassignNode *node); + StmtNode *ExtSimplifyIassign(IassignNode *node); + StmtNode *ExtSimplifyWhile(WhileStmtNode *node); + BaseNode* DispatchFold(BaseNode *node); + + MIRModule *mirModule; +}; +} // namespace maple +#endif // MPL2MPL_INCLUDE_EXTCONSTANTFOLD_H diff --git a/src/mapleall/mpl2mpl/src/ext_constantfold.cpp b/src/mapleall/mpl2mpl/src/ext_constantfold.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c08391fee7efb23d38a608a4910e6dda37f36fb9 --- /dev/null +++ b/src/mapleall/mpl2mpl/src/ext_constantfold.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) [2021] Futurewei Technologies Co., Ltd. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 Mulan PSL v2 for more details. + */ +#include "ext_constantfold.h" +#include + +namespace maple { +// This class is designed to further identify simplification +// patterns that have not been covered in ConstantFold. + +StmtNode *ExtConstantFold::ExtSimplify(StmtNode *node) { + CHECK_NULL_FATAL(node); + switch (node->GetOpCode()) { + case OP_block: + return ExtSimplifyBlock(static_cast(node)); + case OP_if: + return ExtSimplifyIf(static_cast(node)); + case OP_dassign: + return ExtSimplifyDassign(static_cast(node)); + case OP_iassign: + return ExtSimplifyIassign(static_cast(node)); + case OP_dowhile: + case OP_while: + return ExtSimplifyWhile(static_cast(node)); + default: + return node; + } +} + +BaseNode* ExtConstantFold::DispatchFold(BaseNode *node) { + CHECK_NULL_FATAL(node); + + switch (node->GetOpCode()) { + case OP_cior: + case OP_lior: + return FoldIor(static_cast(node)); + default: + return node; + } +} + +BaseNode *ExtConstantFold::Fold(BaseNode *node) { + if (node == nullptr || kOpcodeInfo.IsStmt(node->GetOpCode())) { + return nullptr; + } + return DispatchFold(node); +} + +BaseNode *ExtConstantFold::FoldIor(BinaryNode *node) { + CHECK_NULL_FATAL(node); + // The target pattern (Cior, Lior): + // x == c || x == c+1 || ... || x == c+k + // ==> le (x - c), k + // where c is int. i + // Leave other cases for future including extended simplification of partial expressions + std::queue operands; + std::vector uniqOperands; + operands.push(node); + int64 minVal = LLONG_MAX; + bool isWorkable = true; + BaseNode* lNode = nullptr; + + while (!operands.empty()) { + BaseNode *operand = operands.front(); + operands.pop(); + Opcode op = operand->GetOpCode(); + if (op == OP_cior || op == OP_lior) { + operands.push(static_cast(operand)->GetBOpnd(0)); + operands.push(static_cast(operand)->GetBOpnd(1)); + } else if (op == OP_eq) { + BinaryNode *bNode = static_cast(operand); + if (lNode == nullptr) { + if (bNode->Opnd(0)->GetOpCode() == OP_dread || + bNode->Opnd(0)->GetOpCode() == OP_iread) { + lNode = bNode->Opnd(0); + } else { + // Consider other cases in future + isWorkable = false; + break; + } + } + + if ((lNode->IsSameContent(bNode->Opnd(0))) && + (bNode->Opnd(1)->GetOpCode() == OP_constval) && + (IsPrimitiveInteger(bNode->Opnd(1)->GetPrimType()))) { + MIRConst *rConstVal = safe_cast(bNode->Opnd(1))->GetConstVal(); + int64 rVal = static_cast(rConstVal)->GetValue(); + minVal = std::min(minVal, rVal); + uniqOperands.push_back(rVal); + } else { + isWorkable = false; + break; + } + } else { + isWorkable = false; + break; + } + } + + if (isWorkable) { + std::sort(uniqOperands.begin(), uniqOperands.end()); + uniqOperands.erase(std::unique(uniqOperands.begin(), uniqOperands.end()), uniqOperands.end()); + if ((uniqOperands.size() >= 2) && + (uniqOperands[uniqOperands.size() - 1] == uniqOperands[0] + uniqOperands.size() - 1)) { + PrimType nPrimType = node->GetPrimType(); + BaseNode* diffVal; + ConstvalNode *lowVal = mirModule->GetMIRBuilder()->CreateIntConst(minVal, nPrimType); + diffVal = mirModule->CurFuncCodeMemPool()->New(OP_sub, nPrimType, lNode, lowVal); + PrimType cmpPrimType = (nPrimType == PTY_i64 || nPrimType == PTY_u64) ? PTY_u64 : PTY_u32; + MIRType *cmpMirType = (nPrimType == PTY_i64 || nPrimType == PTY_u64) ? + GlobalTables::GetTypeTable().GetUInt64() : + GlobalTables::GetTypeTable().GetUInt32(); + ConstvalNode *deltaVal = mirModule->GetMIRBuilder()->CreateIntConst(uniqOperands.size() - 1, cmpPrimType); + CompareNode *result; + result = mirModule->GetMIRBuilder()->CreateExprCompare(OP_le, *cmpMirType, *cmpMirType, diffVal, deltaVal); + return result; + } else { + return node; + } + } else { + return node; + } +} + +StmtNode *ExtConstantFold::ExtSimplifyBlock(BlockNode *node) { + CHECK_NULL_FATAL(node); + if (node->GetFirst() == nullptr) { + return node; + } + StmtNode *s = node->GetFirst(); + do { + (void)ExtSimplify(s); + s = s->GetNext();; + } while (s != nullptr); + return node; +} + +StmtNode *ExtConstantFold::ExtSimplifyIf(IfStmtNode *node) { + CHECK_NULL_FATAL(node); + (void)ExtSimplify(node->GetThenPart()); + if (node->GetElsePart()) { + (void)ExtSimplify(node->GetElsePart()); + } + BaseNode *origTest = node->Opnd(); + BaseNode *returnValue = Fold(node->Opnd()); + if (returnValue != origTest) { + node->SetOpnd(returnValue, 0); + } + return node; +} + +StmtNode *ExtConstantFold::ExtSimplifyDassign(DassignNode *node) { + CHECK_NULL_FATAL(node); + BaseNode *returnValue; + returnValue = Fold(node->GetRHS()); + if (returnValue != node->GetRHS()) { + node->SetRHS(returnValue); + } + return node; +} + +StmtNode *ExtConstantFold::ExtSimplifyIassign(IassignNode *node) { + CHECK_NULL_FATAL(node); + BaseNode *returnValue; + returnValue = Fold(node->GetRHS()); + if (returnValue != node->GetRHS()) { + node->SetRHS(returnValue); + } + return node; +} + +StmtNode *ExtConstantFold::ExtSimplifyWhile(WhileStmtNode *node) { + CHECK_NULL_FATAL(node); + BaseNode *returnValue; + if (node->Opnd(0) == nullptr) { + return node; + } + returnValue = Fold(node->Opnd(0)); + if (returnValue != node->Opnd(0)) { + node->SetOpnd(returnValue, 0); + } + return node; +} +} // namespace maple