!8982 refactor overflow to delete use of struct

Merge pull request !8982 from huangyan/delete_struct_hy
This commit is contained in:
openharmony_ci 2024-08-30 19:46:48 +00:00 committed by Gitee
commit 65f7c113f0
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 87 additions and 109 deletions

View File

@ -776,6 +776,11 @@ void LiteCGIRBuilder::SaveGate2Expr(GateRef gate, Expr expr, bool isGlueAdd)
gate2Expr_[gate] = {LiteCGValueKind::kConstKind, static_cast<maple::ConstvalNode*>(newNode)->GetConstVal()};
}
void LiteCGIRBuilder::SaveGate2Expr(GateRef gate, PregIdx pregIdx1, PregIdx pregIdx2)
{
gate2Expr_[gate] = {LiteCGValueKind::kPregPairKind, std::make_pair(pregIdx1, pregIdx2)};
}
Expr LiteCGIRBuilder::GetConstant(GateRef gate)
{
std::bitset<64> value = acc_.GetConstantValue(gate); // 64 for bit width
@ -835,6 +840,18 @@ Expr LiteCGIRBuilder::GetExprFromGate(GateRef gate)
return lmirBuilder_->Regread(std::get<PregIdx>(value.data));
}
Expr LiteCGIRBuilder::GetExprFromGate(GateRef gate, uint32_t index)
{
LiteCGValue value = gate2Expr_[gate];
ASSERT(value.kind == LiteCGValueKind::kPregPairKind);
ASSERT(index == 0 || index == 1);
std::pair<PregIdx, PregIdx> pair = std::get<std::pair<PregIdx, PregIdx>>(value.data);
if (index == 0) {
return lmirBuilder_->Regread(pair.first);
}
return lmirBuilder_->Regread(pair.second);
}
void LiteCGIRBuilder::InitializeHandlers()
{
illegalOpHandlers_ = {OpCode::NOP,
@ -2065,25 +2082,7 @@ void LiteCGIRBuilder::HandleAddWithOverflow(GateRef gate)
void LiteCGIRBuilder::VisitAddWithOverflow(GateRef gate, GateRef e1, GateRef e2)
{
// need use different symbol name?
// get return type {i32 res, u1 carry}
auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
retType = retType ? retType
: lmirBuilder_->CreateStructType("overflow_internal@i32")
.Field("res", lmirBuilder_->i32Type)
.Field("carry", lmirBuilder_->u1Type)
.Done();
static uint32_t val = 0;
std::string retVarName = "add_overflow_ret@i32" + std::to_string(val++);
Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
// generate function call
Expr e1Value = GetExprFromGate(e1);
Expr e2Value = GetExprFromGate(e2);
std::vector<Expr> args = {e1Value, e2Value};
auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_ADD_WITH_OVERFLOW, args, &retVar);
SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
VisitBinaryOpWithOverflow(gate, e1, e2, IntrinsicId::INTRN_ADD_WITH_OVERFLOW);
}
void LiteCGIRBuilder::HandleSubWithOverflow(GateRef gate)
@ -2097,25 +2096,7 @@ void LiteCGIRBuilder::HandleSubWithOverflow(GateRef gate)
void LiteCGIRBuilder::VisitSubWithOverflow(GateRef gate, GateRef e1, GateRef e2)
{
// need use different symbol name?
// get return type {i32 res, u1 carry}
auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
retType = retType ? retType
: lmirBuilder_->CreateStructType("overflow_internal@i32")
.Field("res", lmirBuilder_->i32Type)
.Field("carry", lmirBuilder_->u1Type)
.Done();
static uint32_t val = 0;
std::string retVarName = "sub_overflow_ret@i32" + std::to_string(val++);
Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
// generate function call
Expr e1Value = GetExprFromGate(e1);
Expr e2Value = GetExprFromGate(e2);
std::vector<Expr> args = {e1Value, e2Value};
auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_SUB_WITH_OVERFLOW, args, &retVar);
SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
VisitBinaryOpWithOverflow(gate, e1, e2, IntrinsicId::INTRN_SUB_WITH_OVERFLOW);
}
void LiteCGIRBuilder::HandleMulWithOverflow(GateRef gate)
@ -2129,24 +2110,20 @@ void LiteCGIRBuilder::HandleMulWithOverflow(GateRef gate)
void LiteCGIRBuilder::VisitMulWithOverflow(GateRef gate, GateRef e1, GateRef e2)
{
// need use different symbol name?
// get return type {i32 res, u1 carry}
auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
retType = retType ? retType
: lmirBuilder_->CreateStructType("overflow_internal@i32")
.Field("res", lmirBuilder_->i32Type)
.Field("carry", lmirBuilder_->u1Type)
.Done();
static uint32_t val = 0;
std::string retVarName = "mul_overflow_ret@i32" + std::to_string(val++);
Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
VisitBinaryOpWithOverflow(gate, e1, e2, IntrinsicId::INTRN_MUL_WITH_OVERFLOW);
}
void LiteCGIRBuilder::VisitBinaryOpWithOverflow(GateRef gate, GateRef e1, GateRef e2, IntrinsicId intrinsicId)
{
PregIdx preg1 = lmirBuilder_->CreatePreg(lmirBuilder_->i32Type);
PregIdx preg2 = lmirBuilder_->CreatePreg(lmirBuilder_->u1Type);
// generate function call
Expr e1Value = GetExprFromGate(e1);
Expr e2Value = GetExprFromGate(e2);
std::vector<Expr> args = {e1Value, e2Value};
auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_MUL_WITH_OVERFLOW, args, &retVar);
SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
auto &call = lmirBuilder_->IntrinsicCall(intrinsicId, args, preg1, preg2);
SaveGate2Expr(gate, preg1, preg2);
lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
}
@ -2513,15 +2490,10 @@ void LiteCGIRBuilder::HandleExtractValue(GateRef gate)
void LiteCGIRBuilder::VisitExtractValue(GateRef gate, GateRef e1, GateRef e2)
{
Expr e1Value = GetExprFromGate(e1);
ASSERT((acc_.GetOpCode(e2) == OpCode::CONSTANT) && acc_.GetMachineType(e2) == MachineType::I32);
uint32_t index = static_cast<uint32_t>(acc_.GetConstantValue(e2));
Var *baseVar = lmirBuilder_->GetLocalVarFromExpr(e1Value);
ASSERT(baseVar != nullptr);
// in maple type system, field 0 means the agg itself and field index start from 1
Expr rhs = lmirBuilder_->DreadWithField(*baseVar, index + 1);
PregIdx pregIdx = lmirBuilder_->CreatePreg(rhs.GetType());
lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), lmirBuilder_->Regassign(rhs, pregIdx));
Expr expr = GetExprFromGate(e1, index);
PregIdx pregIdx = lmirBuilder_->GetPregIdxFromExpr(expr);
SaveGate2Expr(gate, lmirBuilder_->Regread(pregIdx));
}

View File

@ -146,7 +146,9 @@ private:
}
}
void SaveGate2Expr(GateRef gate, maple::litecg::Expr expr, bool isGlueAdd = false);
void SaveGate2Expr(GateRef gate, maple::litecg::PregIdx pregIdx1, maple::litecg::PregIdx pregIdx2);
maple::litecg::Expr GetExprFromGate(GateRef gate);
maple::litecg::Expr GetExprFromGate(GateRef gate, uint32_t index);
maple::litecg::Expr GetConstant(GateRef gate);
void BuildInstID2BBIDMap();
maple::litecg::BB &GetOrCreateBB(int bbID);
@ -216,6 +218,7 @@ private:
{
return enableLog_;
}
void VisitBinaryOpWithOverflow(GateRef gate, GateRef e1, GateRef e2, maple::litecg::IntrinsicId intrinsicId);
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_LITECG_IR_BUILDER_H

View File

@ -163,9 +163,6 @@ public:
void LowerAsmStmt(AsmNode *asmNode, BlockNode *blk);
/* Lower pointer/reference types if found in pseudo registers. */
void LowerPseudoRegs(const MIRFunction &func) const;
/* A pseudo register refers to a symbol when DreadNode is converted to RegreadNode. */
StIdx GetSymbolReferredToByPseudoRegister(PregIdx regNO) const
{

View File

@ -38,7 +38,6 @@ public:
hashLabelOpndTable(mallocator.Adapter()),
hashOfstOpndTable(mallocator.Adapter()),
hashMemOpndTable(mallocator.Adapter()),
stIdx2OverflowResult(mallocator.Adapter()),
memOpndsRequiringOffsetAdjustment(mallocator.Adapter()),
memOpndsForStkPassedArguments(mallocator.Adapter()),
immOpndsRequiringOffsetAdjustment(mallocator.Adapter()),
@ -533,7 +532,6 @@ private:
MapleUnorderedMap<LabelIdx, LabelOperand *> hashLabelOpndTable;
MapleUnorderedMap<OfstRegIdx, OfstOperand *> hashOfstOpndTable;
MapleUnorderedMap<MemOperand, MemOperand *> hashMemOpndTable;
MapleUnorderedMap<StIdx, std::pair<RegOperand *, RegOperand *>> stIdx2OverflowResult;
/*
* Local variables, formal parameters that are passed via registers
* need offset adjustment after callee-saved registers are known.

View File

@ -136,11 +136,12 @@ enum LiteCGValueKind {
kSymbolKind,
kConstKind,
kGlueAdd,
kPregPairKind,
};
struct LiteCGValue {
LiteCGValueKind kind;
std::variant<PregIdx, MIRSymbol*, MIRConst*> data;
std::variant<PregIdx, MIRSymbol*, MIRConst*, std::pair<PregIdx, PregIdx>> data;
};
using Args = std::vector<Expr>;
@ -405,6 +406,8 @@ public:
// when result is nullptr, don't need the result (or no result)
Stmt &IntrinsicCall(IntrinsicId func, Args &valueArgs, Var *result = nullptr);
Stmt &IntrinsicCall(IntrinsicId func, Args &valueArgs, PregIdx retPregIdx1, PregIdx retPregIdx2);
Stmt &Return(Expr returnVal);
// debug info

View File

@ -1265,17 +1265,6 @@ void CGLowerer::LowerEntry(MIRFunction &func)
}
}
void CGLowerer::LowerPseudoRegs(const MIRFunction &func) const
{
for (uint32 i = 1; i < func.GetPregTab()->Size(); ++i) {
MIRPreg *ipr = func.GetPregTab()->PregFromPregIdx(i);
PrimType primType = ipr->GetPrimType();
if (primType == PTY_u1) {
ipr->SetPrimType(PTY_u32);
}
}
}
void CGLowerer::CleanupBranches(MIRFunction &func) const
{
BlockNode *block = func.GetBody();
@ -1751,7 +1740,6 @@ void CGLowerer::LowerFunc(MIRFunction &func)
labelIdx = 0;
SetCurrentFunc(&func);
LowerEntry(func);
LowerPseudoRegs(func);
BlockNode *origBody = func.GetBody();
CHECK_FATAL(origBody != nullptr, "origBody should not be nullptr");

View File

@ -937,22 +937,6 @@ void AArch64CGFunc::SelectIassign(IassignNode &stmt)
Operand *AArch64CGFunc::SelectDread(const BaseNode &parent, DreadNode &expr)
{
MIRSymbol *symbol = GetFunction().GetLocalOrGlobalSymbol(expr.GetStIdx());
auto itr = stIdx2OverflowResult.find(expr.GetStIdx());
if (itr != stIdx2OverflowResult.end()) {
/* add_with_overflow / sub_with_overflow:
* reg1: param1
* reg2: param2
* adds/subs reg3, reg1, reg2
* cset reg4, vs
* result is saved in std::pair<RegOperand*, RegOperand*>(reg3, reg4)
*/
if (expr.GetFieldID() == 1) {
return itr->second.first;
} else {
DEBUG_ASSERT(expr.GetFieldID() == 2, "only has 2 fileds for intrinsic overflow call result");
return itr->second.second;
}
}
PrimType symType = symbol->GetType()->GetPrimType();
uint32 offset = 0;
@ -4771,8 +4755,12 @@ void AArch64CGFunc::SelectOverFlowCall(const IntrinsiccallNode &intrnNode)
intrnNode.Opnd(0)->GetPrimType()); /* first argument of intrinsic */
RegOperand &opnd1 = LoadIntoRegister(*HandleExpr(intrnNode, *intrnNode.Opnd(1)),
intrnNode.Opnd(1)->GetPrimType()); /* first argument of intrinsic */
RegOperand &resReg = CreateRegisterOperandOfType(type);
RegOperand &resReg2 = CreateRegisterOperandOfType(PTY_u8);
auto *retVals = &intrnNode.GetReturnVec();
CHECK_FATAL(retVals->size() == k2ByteSize, "there must be two return values");
PregIdx pregIdx = (*retVals)[0].second.GetPregIdx();
PregIdx pregIdx2 = (*retVals)[1].second.GetPregIdx();
RegOperand &resReg = GetOrCreateVirtualRegisterOperand(GetVirtualRegNOFromPseudoRegIdx(pregIdx));
RegOperand &resReg2 = GetOrCreateVirtualRegisterOperand(GetVirtualRegNOFromPseudoRegIdx(pregIdx2));
Operand &rflag = GetOrCreateRflag();
// arith operation with set flag
if (intrinsic == INTRN_ADD_WITH_OVERFLOW) {
@ -4791,11 +4779,6 @@ void AArch64CGFunc::SelectOverFlowCall(const IntrinsiccallNode &intrnNode)
} else {
CHECK_FATAL(false, "niy");
}
// store back
auto *retVals = &intrnNode.GetReturnVec();
auto &pair = retVals->at(0);
stIdx2OverflowResult[pair.first] = std::pair<RegOperand *, RegOperand *>(&resReg, &resReg2);
return;
}
void AArch64CGFunc::SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode)

View File

@ -416,17 +416,21 @@ void X64MPIsel::SelectOverFlowCall(const IntrinsiccallNode &intrnNode)
// store
auto *p2nrets = &intrnNode.GetReturnVec();
if (p2nrets->size() == k1ByteSize) {
StIdx stIdx = (*p2nrets)[0].first;
if (p2nrets->size() == k2ByteSize) {
CHECK_NULL_FATAL(cgFunc->GetBecommon().GetMIRModule().CurFunction());
MIRSymbol *sym =
cgFunc->GetBecommon().GetMIRModule().CurFunction()->GetSymTab()->GetSymbolFromStIdx(stIdx.Idx());
DEBUG_ASSERT(sym != nullptr, "nullptr check");
MemOperand &memOperand = GetOrCreateMemOpndFromSymbol(*sym, 1);
MemOperand &memOperand2 = GetOrCreateMemOpndFromSymbol(*sym, 2);
SelectCopy(memOperand, resReg, type);
Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(MOP_seto_m, X64CG::kMd[MOP_seto_m]);
insn.AddOpndChain(memOperand2);
PregIdx pregIdx = (*p2nrets)[0].second.GetPregIdx();
MIRPreg *mirPreg = cgFunc->GetFunction().GetPregTab()->PregFromPregIdx(pregIdx);
PrimType regType = mirPreg->GetPrimType();
RegOperand &retReg = cgFunc->GetOpndBuilder()->CreateVReg(cgFunc->GetVirtualRegNOFromPseudoRegIdx(pregIdx),
GetPrimTypeBitSize(regType), cgFunc->GetRegTyFromPrimTy(regType));
SelectCopy(retReg, resReg, type);
PregIdx pregIdx2 = (*p2nrets)[1].second.GetPregIdx();
MIRPreg *mirPreg2 = cgFunc->GetFunction().GetPregTab()->PregFromPregIdx(pregIdx2);
PrimType regType2 = mirPreg2->GetPrimType();
RegOperand &retReg2 = cgFunc->GetOpndBuilder()->CreateVReg(cgFunc->GetVirtualRegNOFromPseudoRegIdx(pregIdx2),
GetPrimTypeBitSize(regType2), cgFunc->GetRegTyFromPrimTy(regType2));
Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(MOP_seto_r, X64CG::kMd[MOP_seto_r]);
insn.AddOpndChain(retReg2);
cgFunc->GetCurBB()->AppendInsn(insn);
} else {
CHECK_FATAL(false, "should not happen");

View File

@ -562,6 +562,18 @@ Stmt &LMIRBuilder::IntrinsicCall(IntrinsicId func_, Args &args_, Var *result)
}
}
Stmt &LMIRBuilder::IntrinsicCall(IntrinsicId func_, Args &args_, PregIdx retPregIdx1, PregIdx retPregIdx2)
{
MapleVector<BaseNode *> args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter());
for (const auto &arg : args_) {
args.emplace_back(arg.GetNode());
}
// need to fix the type for IntrinsicId
auto func = static_cast<MIRIntrinsicID>(func_);
return *mirBuilder.CreateStmtIntrinsicCallAssigned(func, args, retPregIdx1, retPregIdx2);
}
Stmt &LMIRBuilder::Return(Expr returnVal)
{
return *mirBuilder.CreateStmtReturn(returnVal.GetNode());

View File

@ -303,6 +303,8 @@ public:
CallNode *CreateStmtCallRegassigned(PUIdx, const MapleVector<BaseNode *> &, PregIdx, Opcode);
IntrinsiccallNode *CreateStmtIntrinsicCallAssigned(MIRIntrinsicID idx, const MapleVector<BaseNode *> &arguments,
PregIdx retPregIdx);
IntrinsiccallNode *CreateStmtIntrinsicCallAssigned(MIRIntrinsicID idx, const MapleVector<BaseNode *> &arguments,
PregIdx retPregIdx1, PregIdx retPregIdx2);
IntrinsiccallNode *CreateStmtIntrinsicCallAssigned(MIRIntrinsicID idx, const MapleVector<BaseNode *> &arguments,
const MIRSymbol *ret, TyIdx tyIdx = TyIdx());
IntrinsiccallNode *CreateStmtXintrinsicCallAssigned(MIRIntrinsicID idx, const MapleVector<BaseNode *> &args,

View File

@ -1089,6 +1089,22 @@ IntrinsiccallNode *MIRBuilder::CreateStmtIntrinsicCallAssigned(MIRIntrinsicID id
return stmt;
}
IntrinsiccallNode *MIRBuilder::CreateStmtIntrinsicCallAssigned(MIRIntrinsicID idx, const MapleVector<BaseNode *> &args,
PregIdx retPregIdx1, PregIdx retPregIdx2)
{
auto *stmt =
NewNode<IntrinsiccallNode>(*GetCurrentFuncCodeMpAllocator(), OP_intrinsiccallassigned, idx);
DEBUG_ASSERT(stmt != nullptr, "stmt is null");
stmt->SetOpnds(args);
if (retPregIdx1 > 0) {
stmt->GetReturnVec().push_back(CallReturnPair(StIdx(), RegFieldPair(0, retPregIdx1)));
}
if (retPregIdx2 > 0) {
stmt->GetReturnVec().push_back(CallReturnPair(StIdx(), RegFieldPair(0, retPregIdx2)));
}
return stmt;
}
IntrinsiccallNode *MIRBuilder::CreateStmtIntrinsicCallAssigned(MIRIntrinsicID idx, const MapleVector<BaseNode *> &args,
const MIRSymbol *ret, TyIdx tyIdx)
{