diff --git a/src/mapleall/maple_ir/include/mir_type.h b/src/mapleall/maple_ir/include/mir_type.h index d852a46893a1552d5a1483697f8d32e947f05b38..fd8e62bd246b9ef1c788f1c34d23ec5f20126d50 100644 --- a/src/mapleall/maple_ir/include/mir_type.h +++ b/src/mapleall/maple_ir/include/mir_type.h @@ -431,6 +431,9 @@ struct OffsetType { } OffsetType operator+(int64 offset) const { + if (this->IsInvalid()) { + return *this; + } int64 sum = this->val + offset; if (sum >= kOffsetMin && sum <= kOffsetMax) { return OffsetType(static_cast(sum)); diff --git a/src/mapleall/maple_me/include/me_ir.h b/src/mapleall/maple_me/include/me_ir.h index 0793a28f5f5f99bc813314399d6b966540221c9a..56a6a6b255045d0890ae45ee2161cbf70d6ae59b 100644 --- a/src/mapleall/maple_me/include/me_ir.h +++ b/src/mapleall/maple_me/include/me_ir.h @@ -881,15 +881,19 @@ class OpMeExpr : public MeExpr { class IvarMeExpr : public MeExpr { public: + IvarMeExpr(int32 exprid, PrimType t, TyIdx tidx, FieldID fid, Opcode op) + : MeExpr(exprid, kMeOpIvar, op, t, 1), tyIdx(tidx), fieldID(fid) {} + IvarMeExpr(int32 exprid, PrimType t, TyIdx tidx, FieldID fid) - : MeExpr(exprid, kMeOpIvar, OP_iread, t, 1), tyIdx(tidx), fieldID(fid) {} + : IvarMeExpr(exprid, t, tidx, fid, OP_iread) {} IvarMeExpr(int32 exprid, const IvarMeExpr &ivarme) - : MeExpr(exprid, kMeOpIvar, OP_iread, ivarme.GetPrimType(), 1), + : MeExpr(exprid, kMeOpIvar, ivarme.op, ivarme.GetPrimType(), 1), defStmt(ivarme.defStmt), base(ivarme.base), tyIdx(ivarme.tyIdx), fieldID(ivarme.fieldID), + offset(ivarme.offset), volatileFromBaseSymbol(ivarme.volatileFromBaseSymbol) { mu = ivarme.mu; } @@ -955,6 +959,14 @@ class IvarMeExpr : public MeExpr { fieldID = fieldIDVal; } + int32 GetOffset() const { + return offset; + } + + void SetOffset(int32 val) { + offset = val; + } + bool GetMaybeNull() const { return maybeNull; } @@ -983,7 +995,7 @@ class IvarMeExpr : public MeExpr { uint32 GetHashIndex() const override { constexpr uint32 kIvarHashShift = 4; - return static_cast(OP_iread) + fieldID + (static_cast(base->GetExprID()) << kIvarHashShift); + return static_cast(op) + fieldID + offset + (static_cast(base->GetExprID()) << kIvarHashShift); } MIRType *GetType() const override { @@ -1000,6 +1012,7 @@ class IvarMeExpr : public MeExpr { TyIdx tyIdx{ 0 }; TyIdx inferredTyIdx{ 0 }; // may be a subclass of above tyIdx FieldID fieldID = 0; + int32 offset = 0; bool maybeNull = true; // false if definitely not null bool volatileFromBaseSymbol = false; // volatile due to its base symbol being volatile ScalarMeExpr *mu = nullptr; // use of mu, only one for IvarMeExpr diff --git a/src/mapleall/maple_me/src/irmap_build.cpp b/src/mapleall/maple_me/src/irmap_build.cpp index 15cb82e7fd055d9ef0068b73b441b9eb25cd8648..3819e388cac08013e103f350d56346012fca4976 100644 --- a/src/mapleall/maple_me/src/irmap_build.cpp +++ b/src/mapleall/maple_me/src/irmap_build.cpp @@ -310,6 +310,30 @@ MeExpr *IRMapBuild::BuildNaryMeExprForIntrinsicWithType(const BaseNode &mirNode) return meExpr; } +static std::pair SimplifyBaseAddressOfIvar(BaseNode *base) { + if (base->GetOpCode() == OP_add || base->GetOpCode() == OP_sub) { + auto offsetNode = base->Opnd(1); + if (offsetNode->IsConstval()) { + // get offset value + auto *mirConst = static_cast(offsetNode)->GetConstVal(); + auto offsetInByte = static_cast(mirConst)->GetValue(); + OffsetType offset(kOffsetUnknown); + offset.Set(base->GetOpCode() == OP_add ? offsetInByte : -offsetInByte); + if (offset.IsInvalid()) { + return std::make_pair(base, offset); + } + + const auto &baseNodeAndOffset = SimplifyBaseAddressOfIvar(base->Opnd(0)); + auto newOffset = offset + baseNodeAndOffset.second; + if (newOffset.IsInvalid()) { + return std::make_pair(base->Opnd(0), offset); + } + return std::make_pair(baseNodeAndOffset.first, newOffset); + } + } + return std::make_pair(base, OffsetType::InvalidOffset()); +} + MeExpr *IRMapBuild::BuildExpr(BaseNode &mirNode, bool atParm, bool noProp) { Opcode op = mirNode.GetOpCode(); if (op == OP_dread) { @@ -362,7 +386,12 @@ MeExpr *IRMapBuild::BuildExpr(BaseNode &mirNode, bool atParm, bool noProp) { if (op == OP_iread) { IvarMeExpr *ivarMeExpr = static_cast(meExpr); IreadSSANode &iReadSSANode = static_cast(mirNode); - ivarMeExpr->SetBase(BuildExpr(*iReadSSANode.Opnd(0), atParm, true)); + const auto &newBaseAndOffset = SimplifyBaseAddressOfIvar(iReadSSANode.Opnd(0)); + ivarMeExpr->SetBase(BuildExpr(*newBaseAndOffset.first, atParm, true)); + if (!newBaseAndOffset.second.IsInvalid() && newBaseAndOffset.second.val != 0) { + ivarMeExpr->SetOffset(newBaseAndOffset.second.val); + ivarMeExpr->SetOp(OP_ireadoff); + } VersionSt *verSt = iReadSSANode.GetSSAVar(); if (verSt != nullptr) { VarMeExpr *varMeExpr = GetOrCreateVarFromVerSt(*verSt); @@ -578,7 +607,12 @@ MeStmt *IRMapBuild::BuildIassignMeStmt(StmtNode &stmt, AccessSSANodes &ssaPart) IassignMeStmt *meStmt = irMap->NewInPool(&stmt); meStmt->SetTyIdx(iasNode.GetTyIdx()); meStmt->SetRHS(BuildExpr(*iasNode.GetRHS(), false, false)); - meStmt->SetLHSVal(irMap->BuildLHSIvar(*BuildExpr(*iasNode.Opnd(0), false, false), *meStmt, iasNode.GetFieldID())); + const auto &newBaseAddrAndOffset = SimplifyBaseAddressOfIvar(iasNode.Opnd(0)); + meStmt->SetLHSVal(irMap->BuildLHSIvar(*BuildExpr(*newBaseAddrAndOffset.first, false, false), *meStmt, iasNode.GetFieldID())); + if (!newBaseAddrAndOffset.second.IsInvalid() && newBaseAddrAndOffset.second.val != 0) { + meStmt->SetOp(OP_iassignoff); + meStmt->GetLHSVal()->SetOffset(newBaseAddrAndOffset.second.val); + } if (mirModule.IsCModule()) { bool isVolt = false; for (MayDefNode maydef : ssaPart.GetMayDefNodes()) { diff --git a/src/mapleall/maple_me/src/irmap_emit.cpp b/src/mapleall/maple_me/src/irmap_emit.cpp index c03282e655a4f2517f880136671d5bdfcfa263ed..ac2b08319b4c18dbb5ac79058c9c703ea5989bd4 100644 --- a/src/mapleall/maple_me/src/irmap_emit.cpp +++ b/src/mapleall/maple_me/src/irmap_emit.cpp @@ -265,7 +265,17 @@ BaseNode &IvarMeExpr::EmitExpr(SSATab &ssaTab) { CHECK_NULL_FATAL(base); auto *ireadNode = ssaTab.GetModule().CurFunction()->GetCodeMempool()->New(OP_iread, PrimType(GetPrimType())); - ireadNode->SetOpnd(&base->EmitExpr(ssaTab), 0); + if (offset == 0) { + ireadNode->SetOpnd(&base->EmitExpr(ssaTab), 0); + } else { + auto *mirType = GlobalTables::GetTypeTable().GetInt32(); + auto *mirConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(offset, *mirType); + auto *codeMemPool = ssaTab.GetModule().CurFunction()->GetCodeMempool(); + auto *constValNode = codeMemPool->New(mirConst); + auto *newAddrNode = + codeMemPool->New(OP_add, base->GetPrimType(), &(base->EmitExpr(ssaTab)), constValNode); + ireadNode->SetOpnd(newAddrNode, 0); + } ireadNode->SetFieldID(fieldID); ireadNode->SetTyIdx(tyIdx); ASSERT(ireadNode->GetPrimType() != kPtyInvalid, ""); @@ -337,7 +347,17 @@ StmtNode &IassignMeStmt::EmitStmt(SSATab &ssaTab) { auto *iassignNode = ssaTab.GetModule().CurFunction()->GetCodeMempool()->New(); iassignNode->SetTyIdx(tyIdx); iassignNode->SetFieldID(lhsVar->GetFieldID()); - iassignNode->SetAddrExpr(&lhsVar->GetBase()->EmitExpr(ssaTab)); + if (lhsVar->GetOffset() == 0) { + iassignNode->SetAddrExpr(&lhsVar->GetBase()->EmitExpr(ssaTab)); + } else { + auto *mirType = GlobalTables::GetTypeTable().GetInt32(); + auto *mirConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(lhsVar->GetOffset(), *mirType); + auto *codeMemPool = ssaTab.GetModule().CurFunction()->GetCodeMempool(); + auto *constValNode = codeMemPool->New(mirConst); + auto *newAddrNode = codeMemPool->New( + OP_add, lhsVar->GetBase()->GetPrimType(), &(lhsVar->GetBase()->EmitExpr(ssaTab)), constValNode); + iassignNode->SetAddrExpr(newAddrNode); + } iassignNode->SetRHS(&rhs->EmitExpr(ssaTab)); iassignNode->SetSrcPos(GetSrcPosition()); return *iassignNode; diff --git a/src/mapleall/maple_me/src/me_ir.cpp b/src/mapleall/maple_me/src/me_ir.cpp index 9c7209b8a03dab3ab8f7c0da3d7c0785e1a98fde..45eb7eb9536739e92ff876bd86efc00ecf9af1f4 100644 --- a/src/mapleall/maple_me/src/me_ir.cpp +++ b/src/mapleall/maple_me/src/me_ir.cpp @@ -390,7 +390,8 @@ bool IvarMeExpr::IsRCWeak() const { // (argument expr), then update its mu: expr->mu = this->mu. bool IvarMeExpr::IsIdentical(IvarMeExpr &expr, bool inConstructor) const { CHECK_FATAL(expr.base != nullptr, "null ptr check"); - if (base->GetExprID() != expr.base->GetExprID() || fieldID != expr.fieldID || tyIdx != expr.tyIdx) { + if (base->GetExprID() != expr.base->GetExprID() || fieldID != expr.fieldID || + offset != expr.offset || tyIdx != expr.tyIdx) { return false; } @@ -911,9 +912,15 @@ void IvarMeExpr::Dump(const IRMap *irMap, int32 indent) const { mirType->Dump(0); LogInfo::MapleLogger() << " (field)" << fieldID << '\n'; PrintIndentation(indent + 1); + if (op == OP_ireadoff) { + LogInfo::MapleLogger() << " (offset)" << offset << '\n'; + } LogInfo::MapleLogger() << "base = "; CHECK_FATAL(base != nullptr, "base is null"); base->Dump(irMap, indent + 1); + if (op == OP_ireadoff) { + LogInfo::MapleLogger() << " (offset)" << offset; + } LogInfo::MapleLogger() << '\n'; PrintIndentation(indent + 1); LogInfo::MapleLogger() << "- MU: {"; diff --git a/src/mapleall/maple_me/src/ssa_pre.cpp b/src/mapleall/maple_me/src/ssa_pre.cpp index 855af1e8ce28c3c89d730fe26c3adf7b87514404..8fb85a44b49556b0ddcd80109238620b20afd13c 100644 --- a/src/mapleall/maple_me/src/ssa_pre.cpp +++ b/src/mapleall/maple_me/src/ssa_pre.cpp @@ -1395,7 +1395,8 @@ void SSAPre::BuildWorkListStmt(MeStmt &stmt, uint32 seqStmt, bool isRebuilt, MeE BuildWorkListExpr(*meStmt, static_cast(seqStmt), *thrMeStmt->GetOpnd(), isRebuilt, tempVar, true); break; } - case OP_iassign: { + case OP_iassign: + case OP_iassignoff: { auto *ivarStmt = static_cast(meStmt); BuildWorkListExpr(*meStmt, static_cast(seqStmt), *ivarStmt->GetRHS(), isRebuilt, tempVar, true); BuildWorkListExpr(*meStmt, static_cast(seqStmt),