From aaf1d2e170390b9f64d08ce5ad1d5d311dbe657d Mon Sep 17 00:00:00 2001 From: Roman Rusyaev Date: Wed, 16 Feb 2022 17:10:13 +0300 Subject: [PATCH] [me][big_endian] Fix bug related to big-endian in merge statements optimization * add --Be option to 'me' component * combine constants for iassign and dassign statements depending on endianness --- src/mapleall/maple_me/include/me_option.h | 5 ++ src/mapleall/maple_me/src/me_merge_stmts.cpp | 61 +++++++++++++++----- src/mapleall/maple_me/src/me_option.cpp | 4 ++ 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/mapleall/maple_me/include/me_option.h b/src/mapleall/maple_me/include/me_option.h index 198328d4f6..6e8b6ae46a 100644 --- a/src/mapleall/maple_me/include/me_option.h +++ b/src/mapleall/maple_me/include/me_option.h @@ -74,11 +74,16 @@ class MeOption : public MapleDriverOptionBase { return !(skipPhases.find(phaseName) == skipPhases.end()); } + static bool IsBigEndian() { + return isBigEndian; + } + static bool DumpPhase(const std::string &phase); static bool DumpFunc(const std::string &func); static std::unordered_set dumpPhases; static std::unordered_set skipPhases; + static bool isBigEndian; static bool dumpBefore; static bool dumpAfter; static constexpr int kRangeArrayLen = 2; diff --git a/src/mapleall/maple_me/src/me_merge_stmts.cpp b/src/mapleall/maple_me/src/me_merge_stmts.cpp index e3421efb92..d19a0c4a7e 100644 --- a/src/mapleall/maple_me/src/me_merge_stmts.cpp +++ b/src/mapleall/maple_me/src/me_merge_stmts.cpp @@ -102,19 +102,23 @@ void MergeStmts::mergeIassigns(vOffsetStmt& iassignCandidates) { if (found) { // Concatenate constants - FieldID fieldID = static_cast(iassignCandidates[endIdx].second)->GetLHSVal()->GetFieldID(); + bool isBigEndian = MeOption::IsBigEndian(); + size_t firstIdx = isBigEndian ? startCandidate : endIdx; + + FieldID fieldID = static_cast(iassignCandidates[firstIdx].second)->GetLHSVal()->GetFieldID(); int32 fieldBitSize; if (fieldID == 0) { - TyIdx lhsPtrTypeIdx = static_cast(iassignCandidates[endIdx].second)->GetLHSVal()->GetTyIdx(); + TyIdx lhsPtrTypeIdx = static_cast(iassignCandidates[firstIdx].second)->GetLHSVal()->GetTyIdx(); fieldBitSize = GetPointedTypeBitSize(lhsPtrTypeIdx); } else { fieldBitSize = GetStructFieldBitSize(lhsStructType, fieldID); } - IassignMeStmt *lastIassignMeStmt = static_cast(iassignCandidates[endIdx].second); + IassignMeStmt *lastIassignMeStmt = static_cast(iassignCandidates[firstIdx].second); ConstMeExpr *rhsLastIassignMeStmt = static_cast(lastIassignMeStmt->GetOpnd(1)); uint64 fieldVal = static_cast(rhsLastIassignMeStmt->GetIntValue()); uint64 combinedVal = (fieldVal << (64 - fieldBitSize)) >> (64 - fieldBitSize); - for (int stmtIdx = static_cast(endIdx) - 1; stmtIdx >= static_cast(startCandidate); stmtIdx--) { + + auto combineValue = [&](int stmtIdx) { fieldID = static_cast(iassignCandidates[stmtIdx].second)->GetLHSVal()->GetFieldID(); if (fieldID == 0) { TyIdx lhsPtrTypeIdx = static_cast(iassignCandidates[stmtIdx].second)->GetLHSVal()->GetTyIdx(); @@ -126,7 +130,18 @@ void MergeStmts::mergeIassigns(vOffsetStmt& iassignCandidates) { static_cast(iassignCandidates[stmtIdx].second)->GetOpnd(1))->GetIntValue()); fieldVal = (fieldVal << (64 - fieldBitSize)) >> (64 - fieldBitSize); combinedVal = combinedVal << fieldBitSize | fieldVal; + }; + + if (isBigEndian) { + for (int stmtIdx = static_cast(startCandidate) + 1; stmtIdx <= static_cast(endIdx); ++stmtIdx) { + combineValue(stmtIdx); + } + } else { + for (int stmtIdx = static_cast(endIdx) - 1; stmtIdx >= static_cast(startCandidate); --stmtIdx) { + combineValue(stmtIdx); + } } + // Iassignoff is NOT part of MeStmt yet IassignMeStmt *firstIassignStmt = static_cast(iassignCandidates[startCandidate].second); PrimType newValType = (targetBitSize == 16) ? PTY_u16 : ((targetBitSize == 32) ? PTY_u32 : PTY_u64); @@ -203,24 +218,38 @@ void MergeStmts::mergeDassigns(vOffsetStmt& dassignCandidates) { if (found) { // Concatenate constants - OriginalSt *lhsOrigStEndIdx = static_cast(dassignCandidates[endIdx].second)->GetLHS()->GetOst(); - FieldID fieldIDEndIdx = lhsOrigStEndIdx->GetFieldID(); + bool isBigEndian = MeOption::IsBigEndian(); + size_t firstIdx = isBigEndian ? startCandidate : endIdx; + + OriginalSt *lhsOrigStFirstIdx = static_cast(dassignCandidates[firstIdx].second)->GetLHS()->GetOst(); + FieldID fieldIDEndIdx = lhsOrigStFirstIdx->GetFieldID(); int32 fieldBitSizeEndIdx = GetStructFieldBitSize(lhsStructTypeStart, fieldIDEndIdx); - uint64 fieldValEndIdx = static_cast(static_cast(static_cast( - dassignCandidates[endIdx].second)->GetRHS())->GetIntValue()); - uint64 combinedVal = (fieldValEndIdx << (64 - fieldBitSizeEndIdx)) >> (64 - fieldBitSizeEndIdx); - for (int stmtIdx = static_cast(endIdx) - 1; stmtIdx >= static_cast(startCandidate); stmtIdx--) { - OriginalSt *lhsOrigStStmtIdx = static_cast( - dassignCandidates[stmtIdx].second)->GetVarLHS()->GetOst(); + + uint64 fieldValIdx = static_cast(static_cast(static_cast( + dassignCandidates[firstIdx].second)->GetRHS())->GetIntValue()); + + uint64 combinedVal = (fieldValIdx << (64 - fieldBitSizeEndIdx)) >> (64 - fieldBitSizeEndIdx); + + auto combineValue = [&](int stmtIdx) { + OriginalSt *lhsOrigStStmtIdx = static_cast(dassignCandidates[stmtIdx].second)->GetVarLHS()->GetOst(); FieldID fieldIDStmtIdx = lhsOrigStStmtIdx->GetFieldID(); int32 fieldBitSizeStmtIdx = GetStructFieldBitSize(lhsStructTypeStart, fieldIDStmtIdx); - uint64 fieldValStmtIdx = static_cast(static_cast(static_cast( - dassignCandidates[endIdx].second)->GetRHS())->GetIntValue()); - fieldValStmtIdx = static_cast(static_cast(static_cast( - dassignCandidates[stmtIdx].second)->GetRHS())->GetIntValue()); + uint64 fieldValStmtIdx = static_cast(static_cast( + static_cast(dassignCandidates[stmtIdx].second)->GetRHS())->GetIntValue()); fieldValStmtIdx = (fieldValStmtIdx << (64 - fieldBitSizeStmtIdx)) >> (64 - fieldBitSizeStmtIdx); combinedVal = (combinedVal << fieldBitSizeStmtIdx) | fieldValStmtIdx; + }; + + if (isBigEndian) { + for (size_t stmtIdx = startCandidate + 1; stmtIdx <= endIdx; ++stmtIdx) { + combineValue(stmtIdx); + } + } else { + for (int stmtIdx = static_cast(endIdx) - 1; stmtIdx >= static_cast(startCandidate); --stmtIdx) { + combineValue(stmtIdx); + } } + // Dassignoff is NOT part of MeStmt yet DassignMeStmt *firstDassignStmt = static_cast(dassignCandidates[startCandidate].second); PrimType newValType = (targetBitSize == 16) ? PTY_u16 : ((targetBitSize == 32) ? PTY_u32 : PTY_u64) ; diff --git a/src/mapleall/maple_me/src/me_option.cpp b/src/mapleall/maple_me/src/me_option.cpp index 65f99d24f0..6947901c94 100644 --- a/src/mapleall/maple_me/src/me_option.cpp +++ b/src/mapleall/maple_me/src/me_option.cpp @@ -24,6 +24,7 @@ using namespace mapleOption; std::unordered_set MeOption::dumpPhases = {}; std::unordered_set MeOption::skipPhases = {}; +bool MeOption::isBigEndian = false; bool MeOption::dumpAfter = false; std::string MeOption::dumpFunc = "*"; unsigned long MeOption::range[kRangeArrayLen] = { 0, 0 }; @@ -1398,6 +1399,9 @@ bool MeOption::SolveOptions(const std::deque &opts, bool is case kMeDumpAfter: dumpAfter = (opt.Type() == kEnable); break; + case kBigEndian: + isBigEndian = (opt.Type() == kEnable); + break; case kMeDumpFunc: dumpFunc = opt.Args(); break; -- Gitee