From 1e9a78db0c3ed2e42d9880070b58cdf8140e4d7c Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Wed, 15 Jun 2022 23:00:57 -0700 Subject: [PATCH 1/3] Implemented removal of sext/zext that is redundant due to its operand being a dread or iread having the same effect Folded shr followed by band to bitsextract. --- src/mapleall/maple_me/src/me_rename2preg.cpp | 8 ++ src/mapleall/maple_me/src/pme_emit.cpp | 2 +- src/mapleall/mpl2mpl/src/constantfold.cpp | 87 ++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/mapleall/maple_me/src/me_rename2preg.cpp b/src/mapleall/maple_me/src/me_rename2preg.cpp index 9549dff004..d7cc818212 100644 --- a/src/mapleall/maple_me/src/me_rename2preg.cpp +++ b/src/mapleall/maple_me/src/me_rename2preg.cpp @@ -105,6 +105,9 @@ RegMeExpr *SSARename2Preg::RenameVar(const VarMeExpr *varmeexpr) { curtemp = meirmap->CreateRegMeExpr(*varmeexpr->GetType()); } OriginalSt *pregOst = curtemp->GetOst(); + if (varmeexpr->IsZeroVersion()) { + pregOst->SetZeroVersionIndex(curtemp->GetVstIdx()); + } pregOst->SetIsFormal(ost->IsFormal()); sym2reg_map[ost->GetIndex()] = pregOst; (void)vstidx2reg_map.insert(std::make_pair(varmeexpr->GetExprID(), curtemp)); @@ -190,6 +193,11 @@ void SSARename2Preg::Rename2PregLeafRHS(MeStmt *mestmt, const VarMeExpr *varmeex if (varreg != nullptr) { if (varreg->GetPrimType() != varmeexpr->GetPrimType()) { varreg = meirmap->CreateMeExprTypeCvt(varmeexpr->GetPrimType(), varreg->GetPrimType(), *varreg); + } else if (static_cast(varreg)->IsZeroVersion() && GetPrimTypeSize(varreg->GetPrimType()) < 4) { + // if reading garbage, need to truncate the garbage value + Opcode extOp = IsSignedInteger(varreg->GetPrimType()) ? OP_sext : OP_zext; + varreg = meirmap->CreateMeExprUnary(extOp, GetRegPrimType(varreg->GetPrimType()), *varreg); + static_cast(varreg)->SetBitsSize(GetPrimTypeSize(varmeexpr->GetPrimType()) * 8); } (void)meirmap->ReplaceMeExprStmt(*mestmt, *varmeexpr, *varreg); } diff --git a/src/mapleall/maple_me/src/pme_emit.cpp b/src/mapleall/maple_me/src/pme_emit.cpp index 227cb6a761..66c1df57af 100755 --- a/src/mapleall/maple_me/src/pme_emit.cpp +++ b/src/mapleall/maple_me/src/pme_emit.cpp @@ -94,7 +94,7 @@ BaseNode *PreMeEmitter::EmitPreMeExpr(MeExpr *meexpr, BaseNode *parent) { if (sym->IsLocal()) { sym->ResetIsDeleted(); } - AddrofNode *dreadnode = codeMP->New(OP_dread, varmeexpr->GetPrimType(), sym->GetStIdx(), + AddrofNode *dreadnode = codeMP->New(OP_dread, GetRegPrimType(varmeexpr->GetPrimType()), sym->GetStIdx(), varmeexpr->GetOst()->GetFieldID()); PreMeExprExtensionMap[dreadnode] = pmeExt; return dreadnode; diff --git a/src/mapleall/mpl2mpl/src/constantfold.cpp b/src/mapleall/mpl2mpl/src/constantfold.cpp index f84c351bd8..1ba1aea93b 100644 --- a/src/mapleall/mpl2mpl/src/constantfold.cpp +++ b/src/mapleall/mpl2mpl/src/constantfold.cpp @@ -47,6 +47,23 @@ namespace maple { // A. Analyze expression type // B. Analysis operator type // C. Replace the expression with the result of the operation + +// true if the constant's bits are made of only one group of contiguous 1's +// starting at bit 0 +static bool ContiguousBitsOf1(uint64 x) { + if (x == 0) { + return false; + } + return (~x & (x+1)) == (x+1); +} + +inline bool IsPowerOf2(uint64 num) { + if (num == 0) { + return false; + } + return (~(num - 1) & num) == num; +} + BinaryNode *ConstantFold::NewBinaryNode(BinaryNode *old, Opcode op, PrimType primType, BaseNode *lhs, BaseNode *rhs) const { CHECK_NULL_FATAL(old); @@ -1665,6 +1682,46 @@ ConstvalNode *ConstantFold::FoldSignExtend(Opcode opcode, PrimType resultType, u return resultConst; } +// check if truncation is redundant due to dread or iread having same effect +static bool ExtractbitsRedundant(ExtractbitsNode *x, MIRFunction *f) { + if (GetPrimTypeSize(x->GetPrimType()) == 8) { + return false; // this is trying to be conservative + } + BaseNode *opnd = x->Opnd(0); + MIRType *mirType = nullptr; + if (opnd->GetOpCode() == OP_dread) { + DreadNode *dread = static_cast(opnd); + MIRSymbol *sym = f->GetLocalOrGlobalSymbol(dread->GetStIdx()); + mirType = sym->GetType(); + if (dread->GetFieldID() != 0) { + MIRStructType *structType = dynamic_cast(mirType); + if (structType == nullptr) { + return false; + } + mirType = structType->GetFieldType(dread->GetFieldID()); + } + } else if (opnd->GetOpCode() == OP_iread) { + IreadNode *iread = static_cast(opnd); + MIRPtrType *ptrType = dynamic_cast(GlobalTables::GetTypeTable().GetTypeFromTyIdx(iread->GetTyIdx())); + if (ptrType == nullptr) { + return false; + } + mirType = ptrType->GetPointedType(); + if (iread->GetFieldID() != 0) { + MIRStructType *structType = dynamic_cast(mirType); + if (structType == nullptr) { + return false; + } + mirType = structType->GetFieldType(iread->GetFieldID()); + } + } else { + return false; + } + return IsPrimitiveInteger(mirType->GetPrimType()) && + mirType->GetSize() * 8 == x->GetBitsSize() && + IsSignedInteger(mirType->GetPrimType()) == IsSignedInteger(x->GetPrimType()); +} + // sext and zext also handled automatically std::pair ConstantFold::FoldExtractbits(ExtractbitsNode *node) { CHECK_NULL_FATAL(node); @@ -1695,6 +1752,11 @@ std::pair ConstantFold::FoldExtractbits(ExtractbitsNode *node) result->SetOpnd(opnd->Opnd(0), 0); // delete the redundant extraction } } + if (offset == 0 && size >= 8 && IsPowerOf2(size)) { + if (ExtractbitsRedundant(static_cast(result), mirModule->CurFunction())) { + return std::make_pair(result->Opnd(0), 0); + } + } return std::make_pair(result, 0); } @@ -1915,6 +1977,31 @@ std::pair ConstantFold::FoldBinary(BinaryNode *node) { // X & (-1) -> X sum = lp.second; result = l; + } else if (op == OP_band && ContiguousBitsOf1(cst) && lp.second == 0) { + bool fold2extractbits = false; + if (l->GetOpCode() == OP_ashr || l->GetOpCode() == OP_lshr) { + BinaryNode *shrNode = static_cast(l); + if (shrNode->Opnd(1)->GetOpCode() == OP_constval) { + ConstvalNode *shrOpnd = static_cast(shrNode->Opnd(1)); + int64 shrAmt = static_cast(shrOpnd->GetConstVal())->GetValue(); + uint64 ucst = cst; + uint64 bsize = 0; + do { + bsize++; + ucst >>= 1; + } while (ucst != 0); + if (shrAmt + bsize <= GetPrimTypeSize(primType) * 8) { + fold2extractbits = true; + // change to use extractbits + result = mirModule->GetMIRBuilder()->CreateExprExtractbits(OP_extractbits, GetUnsignedPrimType(primType), shrAmt, bsize, shrNode->Opnd(0)); + sum = 0; + } + } + } + if (!fold2extractbits) { + result = NewBinaryNode(node, op, primType, PairToExpr(lPrimTypes, lp), r); + sum = 0; + } } else if (op == OP_bior && cst == -1) { // X | (-1) -> -1 sum = 0; -- Gitee From bbc376912a737e54584cd86a0f5bb796b5091f2b Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Wed, 15 Jun 2022 23:00:57 -0700 Subject: [PATCH 2/3] Implemented removal of sext/zext that is redundant due to its operand being a dread or iread having the same effect Folded shr followed by band to bitsextract. --- src/mapleall/maple_me/src/me_rename2preg.cpp | 8 ++ src/mapleall/maple_me/src/pme_emit.cpp | 2 +- src/mapleall/mpl2mpl/src/constantfold.cpp | 87 ++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/mapleall/maple_me/src/me_rename2preg.cpp b/src/mapleall/maple_me/src/me_rename2preg.cpp index 9549dff004..d7cc818212 100644 --- a/src/mapleall/maple_me/src/me_rename2preg.cpp +++ b/src/mapleall/maple_me/src/me_rename2preg.cpp @@ -105,6 +105,9 @@ RegMeExpr *SSARename2Preg::RenameVar(const VarMeExpr *varmeexpr) { curtemp = meirmap->CreateRegMeExpr(*varmeexpr->GetType()); } OriginalSt *pregOst = curtemp->GetOst(); + if (varmeexpr->IsZeroVersion()) { + pregOst->SetZeroVersionIndex(curtemp->GetVstIdx()); + } pregOst->SetIsFormal(ost->IsFormal()); sym2reg_map[ost->GetIndex()] = pregOst; (void)vstidx2reg_map.insert(std::make_pair(varmeexpr->GetExprID(), curtemp)); @@ -190,6 +193,11 @@ void SSARename2Preg::Rename2PregLeafRHS(MeStmt *mestmt, const VarMeExpr *varmeex if (varreg != nullptr) { if (varreg->GetPrimType() != varmeexpr->GetPrimType()) { varreg = meirmap->CreateMeExprTypeCvt(varmeexpr->GetPrimType(), varreg->GetPrimType(), *varreg); + } else if (static_cast(varreg)->IsZeroVersion() && GetPrimTypeSize(varreg->GetPrimType()) < 4) { + // if reading garbage, need to truncate the garbage value + Opcode extOp = IsSignedInteger(varreg->GetPrimType()) ? OP_sext : OP_zext; + varreg = meirmap->CreateMeExprUnary(extOp, GetRegPrimType(varreg->GetPrimType()), *varreg); + static_cast(varreg)->SetBitsSize(GetPrimTypeSize(varmeexpr->GetPrimType()) * 8); } (void)meirmap->ReplaceMeExprStmt(*mestmt, *varmeexpr, *varreg); } diff --git a/src/mapleall/maple_me/src/pme_emit.cpp b/src/mapleall/maple_me/src/pme_emit.cpp index 227cb6a761..66c1df57af 100755 --- a/src/mapleall/maple_me/src/pme_emit.cpp +++ b/src/mapleall/maple_me/src/pme_emit.cpp @@ -94,7 +94,7 @@ BaseNode *PreMeEmitter::EmitPreMeExpr(MeExpr *meexpr, BaseNode *parent) { if (sym->IsLocal()) { sym->ResetIsDeleted(); } - AddrofNode *dreadnode = codeMP->New(OP_dread, varmeexpr->GetPrimType(), sym->GetStIdx(), + AddrofNode *dreadnode = codeMP->New(OP_dread, GetRegPrimType(varmeexpr->GetPrimType()), sym->GetStIdx(), varmeexpr->GetOst()->GetFieldID()); PreMeExprExtensionMap[dreadnode] = pmeExt; return dreadnode; diff --git a/src/mapleall/mpl2mpl/src/constantfold.cpp b/src/mapleall/mpl2mpl/src/constantfold.cpp index f84c351bd8..1ba1aea93b 100644 --- a/src/mapleall/mpl2mpl/src/constantfold.cpp +++ b/src/mapleall/mpl2mpl/src/constantfold.cpp @@ -47,6 +47,23 @@ namespace maple { // A. Analyze expression type // B. Analysis operator type // C. Replace the expression with the result of the operation + +// true if the constant's bits are made of only one group of contiguous 1's +// starting at bit 0 +static bool ContiguousBitsOf1(uint64 x) { + if (x == 0) { + return false; + } + return (~x & (x+1)) == (x+1); +} + +inline bool IsPowerOf2(uint64 num) { + if (num == 0) { + return false; + } + return (~(num - 1) & num) == num; +} + BinaryNode *ConstantFold::NewBinaryNode(BinaryNode *old, Opcode op, PrimType primType, BaseNode *lhs, BaseNode *rhs) const { CHECK_NULL_FATAL(old); @@ -1665,6 +1682,46 @@ ConstvalNode *ConstantFold::FoldSignExtend(Opcode opcode, PrimType resultType, u return resultConst; } +// check if truncation is redundant due to dread or iread having same effect +static bool ExtractbitsRedundant(ExtractbitsNode *x, MIRFunction *f) { + if (GetPrimTypeSize(x->GetPrimType()) == 8) { + return false; // this is trying to be conservative + } + BaseNode *opnd = x->Opnd(0); + MIRType *mirType = nullptr; + if (opnd->GetOpCode() == OP_dread) { + DreadNode *dread = static_cast(opnd); + MIRSymbol *sym = f->GetLocalOrGlobalSymbol(dread->GetStIdx()); + mirType = sym->GetType(); + if (dread->GetFieldID() != 0) { + MIRStructType *structType = dynamic_cast(mirType); + if (structType == nullptr) { + return false; + } + mirType = structType->GetFieldType(dread->GetFieldID()); + } + } else if (opnd->GetOpCode() == OP_iread) { + IreadNode *iread = static_cast(opnd); + MIRPtrType *ptrType = dynamic_cast(GlobalTables::GetTypeTable().GetTypeFromTyIdx(iread->GetTyIdx())); + if (ptrType == nullptr) { + return false; + } + mirType = ptrType->GetPointedType(); + if (iread->GetFieldID() != 0) { + MIRStructType *structType = dynamic_cast(mirType); + if (structType == nullptr) { + return false; + } + mirType = structType->GetFieldType(iread->GetFieldID()); + } + } else { + return false; + } + return IsPrimitiveInteger(mirType->GetPrimType()) && + mirType->GetSize() * 8 == x->GetBitsSize() && + IsSignedInteger(mirType->GetPrimType()) == IsSignedInteger(x->GetPrimType()); +} + // sext and zext also handled automatically std::pair ConstantFold::FoldExtractbits(ExtractbitsNode *node) { CHECK_NULL_FATAL(node); @@ -1695,6 +1752,11 @@ std::pair ConstantFold::FoldExtractbits(ExtractbitsNode *node) result->SetOpnd(opnd->Opnd(0), 0); // delete the redundant extraction } } + if (offset == 0 && size >= 8 && IsPowerOf2(size)) { + if (ExtractbitsRedundant(static_cast(result), mirModule->CurFunction())) { + return std::make_pair(result->Opnd(0), 0); + } + } return std::make_pair(result, 0); } @@ -1915,6 +1977,31 @@ std::pair ConstantFold::FoldBinary(BinaryNode *node) { // X & (-1) -> X sum = lp.second; result = l; + } else if (op == OP_band && ContiguousBitsOf1(cst) && lp.second == 0) { + bool fold2extractbits = false; + if (l->GetOpCode() == OP_ashr || l->GetOpCode() == OP_lshr) { + BinaryNode *shrNode = static_cast(l); + if (shrNode->Opnd(1)->GetOpCode() == OP_constval) { + ConstvalNode *shrOpnd = static_cast(shrNode->Opnd(1)); + int64 shrAmt = static_cast(shrOpnd->GetConstVal())->GetValue(); + uint64 ucst = cst; + uint64 bsize = 0; + do { + bsize++; + ucst >>= 1; + } while (ucst != 0); + if (shrAmt + bsize <= GetPrimTypeSize(primType) * 8) { + fold2extractbits = true; + // change to use extractbits + result = mirModule->GetMIRBuilder()->CreateExprExtractbits(OP_extractbits, GetUnsignedPrimType(primType), shrAmt, bsize, shrNode->Opnd(0)); + sum = 0; + } + } + } + if (!fold2extractbits) { + result = NewBinaryNode(node, op, primType, PairToExpr(lPrimTypes, lp), r); + sum = 0; + } } else if (op == OP_bior && cst == -1) { // X | (-1) -> -1 sum = 0; -- Gitee From e7f005d47a1dbc201979d45860ea4ec199d8195a Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Fri, 24 Jun 2022 00:40:27 -0700 Subject: [PATCH 3/3] My optimization exposed 2 situations where insertion of sext/zext is needed --- src/mapleall/maple_me/src/prop.cpp | 2 +- src/mapleall/maple_me/src/ssa_tab.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/mapleall/maple_me/src/prop.cpp b/src/mapleall/maple_me/src/prop.cpp index 0ff35e8454..bbe599f1fc 100644 --- a/src/mapleall/maple_me/src/prop.cpp +++ b/src/mapleall/maple_me/src/prop.cpp @@ -596,7 +596,7 @@ MeExpr *Prop::CheckTruncation(MeExpr *lhs, MeExpr *rhs) const { } if (IsPrimitiveInteger(lhsTy->GetPrimType()) && lhsTy->GetPrimType() != PTY_ptr && lhsTy->GetPrimType() != PTY_ref) { - if (GetPrimTypeSize(lhsTy->GetPrimType()) < GetPrimTypeSize(rhs->GetPrimType())) { + if (GetPrimTypeSize(lhsTy->GetPrimType()) < GetPrimTypeSize(GetRegPrimType(rhs->GetPrimType()))) { if (GetPrimTypeSize(lhsTy->GetPrimType()) >= 4) { return irMap.CreateMeExprTypeCvt(lhsTy->GetPrimType(), rhs->GetPrimType(), *rhs); } else { diff --git a/src/mapleall/maple_me/src/ssa_tab.cpp b/src/mapleall/maple_me/src/ssa_tab.cpp index 7da7182a2d..555abb6ff0 100644 --- a/src/mapleall/maple_me/src/ssa_tab.cpp +++ b/src/mapleall/maple_me/src/ssa_tab.cpp @@ -78,6 +78,16 @@ BaseNode *SSATab::CreateSSAExpr(BaseNode *expr) { expr->SetOpnd(newOpnd, i); } } + // special lowering for trunc whose result has size less than 4 bytes + if (expr->GetOpCode() == OP_trunc && GetPrimTypeSize(expr->GetPrimType()) < 4) { + Opcode extOp = IsSignedInteger(expr->GetPrimType()) ? OP_sext : OP_zext; + uint32 extSize = GetPrimTypeBitSize(expr->GetPrimType()); + PrimType newPrimType = GetRegPrimType(expr->GetPrimType()); + expr->SetPrimType(newPrimType); + BaseNode *extNode = mirModule.CurFunction()->GetCodeMemPool()->New(extOp, newPrimType, 0, extSize); + extNode->SetOpnd(expr, 0); + return extNode; + } return arrayLowered ? expr : nullptr; } -- Gitee