diff --git a/src/mapleall/maple_me/src/me_rename2preg.cpp b/src/mapleall/maple_me/src/me_rename2preg.cpp index 9549dff0045f07a826df5f40109875300b4f4d39..d7cc818212755e597aacbad4f511554ddf4ef687 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 227cb6a761f6297a9ab6c99aa066f9063f7763a8..66c1df57af4c26996eca926bfea1e35beeb5e807 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/maple_me/src/prop.cpp b/src/mapleall/maple_me/src/prop.cpp index 0ff35e8454349f23dc1aac97c8694bbfae64928d..bbe599f1fcfdae27a293ba2790d6a206304167ca 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 7da7182a2dcbc0000a6ad1f44612bf0b9642b0e2..555abb6ff0f0d3b627ea0fab745df5edfc54a191 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; } diff --git a/src/mapleall/mpl2mpl/src/constantfold.cpp b/src/mapleall/mpl2mpl/src/constantfold.cpp index f84c351bd85b33eba986519e469bb88a1a1ffdc2..1ba1aea93bd68e50a1340abcc929b38f739be0ed 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;