diff --git a/mapleall/maple_be/include/cg/riscv64/riscv64_peep.h b/mapleall/maple_be/include/cg/riscv64/riscv64_peep.h index 02e7ac758b63a6f5dd83ba85ac9ae1849fcaa24d..e180b31ffb27f715c1ca29a620bfd46d4fa6f8eb 100644 --- a/mapleall/maple_be/include/cg/riscv64/riscv64_peep.h +++ b/mapleall/maple_be/include/cg/riscv64/riscv64_peep.h @@ -61,6 +61,7 @@ class Riscv64Peep { void PrePeepholeOpt(); void PrePeepholeOpt1(); void ReplaceInstruction(); + bool IfOperandIsLiveAfterInsn(RegOperand *regOpnd, Insn *insn); }; // class Riscv64Peep diff --git a/mapleall/maple_be/src/cg/riscv64/riscv64_cg_func.cpp b/mapleall/maple_be/src/cg/riscv64/riscv64_cg_func.cpp index ee72f0a5a966dd9f5d40f896c117c309d6d2c3be..69dbbae41201e3d97f43be16f2134f41abc18db3 100644 --- a/mapleall/maple_be/src/cg/riscv64/riscv64_cg_func.cpp +++ b/mapleall/maple_be/src/cg/riscv64/riscv64_cg_func.cpp @@ -4406,7 +4406,7 @@ MemOperand *Riscv64CGFunc::GetOrCreateMemOpnd(MIRSymbol * symbol, int32 offset, there is no need to repeat the offset in the actual mem opnd. */ return memPool->New(size, staddropnd, - static_cast(nullptr), GetOrCreateOfstOpnd(0, 32), symbol); + static_cast(nullptr), GetOrCreateOfstOpnd(0, 32), nullptr); } else { CG_ASSERT(false, "NYI"); } diff --git a/mapleall/maple_be/src/cg/riscv64/riscv64_emit.cpp b/mapleall/maple_be/src/cg/riscv64/riscv64_emit.cpp index 9779e095df81e1f9add6f940caea740b051d5a83..f2e247467e8a839537afedf8a5eb77052179c7db 100644 --- a/mapleall/maple_be/src/cg/riscv64/riscv64_emit.cpp +++ b/mapleall/maple_be/src/cg/riscv64/riscv64_emit.cpp @@ -226,14 +226,14 @@ void Riscv64Insn::EmitAdrpLabel(CG &cg, Emitter &emitter) { //GStrIdx strIdx = CG::curCgFunc->mirModule.CurFunction()->labelTab->labelTable[lidx]; //string labelStr = GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx); - // adrp xd, label + // lui xd, %hi(label) emitter.Emit("\t").Emit("lui").Emit("\t"); opnd0->Emit(emitter, prop0); emitter.Emit(", "); const char *idx = std::to_string(CG::curPuIdx).c_str(); emitter.Emit("%hi(").Emit(".label.").Emit(idx).Emit("__").Emit(lidx).Emit(")\n"); - // add xd, xd, #lo12:label + // addi xd, xd, %lo(label) emitter.Emit("\taddi\t"); opnd0->Emit(emitter, prop0); emitter.Emit(", "); diff --git a/mapleall/maple_be/src/cg/riscv64/riscv64_operand.cpp b/mapleall/maple_be/src/cg/riscv64/riscv64_operand.cpp index a492f3d1e55fb13a485ece17df981b650b745376..ca6ce0bb84d1ce6709a989871243d9851fbeb7a4 100644 --- a/mapleall/maple_be/src/cg/riscv64/riscv64_operand.cpp +++ b/mapleall/maple_be/src/cg/riscv64/riscv64_operand.cpp @@ -140,19 +140,37 @@ void Riscv64MemOperand::Emit(Emitter &emitter, OpndProp *prop) { #if DEBUG CG_ASSERT(isVector || is64bit || md->GetOperandSize() <= 32, ""); #endif + MIRSymbol *symbol = GetSymbol(); Riscv64OfstOperand *offset = GetOffsetImmediate(); - if (offset) { - if (CGOptions::doPIC && offset->op_kind_ == Opd_StImmediate && - (((StImmOperand *)offset)->GetSymbol()->GetStorageClass() == kScGlobal || - ((StImmOperand *)offset)->GetSymbol()->GetStorageClass() == kScExtern)) { - emitter.Emit("#:got_lo12:"); - emitter.Emit(((StImmOperand *)offset)->GetName()); - } else { - CG_ASSERT(!IsPIMMOffsetOutOfRange(offset->GetOffsetValue(), size_), ""); - if (!offset->IsZero()) { - offset->Emit(emitter, nullptr); - } + if (symbol && (symbol->IsGlobal() || symbol->storageClass == kScPstatic || + symbol->storageClass == kScFstatic)) { + emitter.Emit("%lo("); + // check for sKind since it might be created by cg. (i.eg. LB_*) + if (symbol->storageClass == kScPstatic && symbol->sKind != kStConst && + symbol->IsLocal()) { + emitter.Emit(symbol->GetName() + to_string(CG::curPuIdx)); + } else { + emitter.Emit(symbol->GetName()); + } + if (offset && !offset->IsZero()) { + emitter.Emit("+"); + offset->Emit(emitter, nullptr); + } + emitter.Emit(")"); + } else if (offset) { + if (CGOptions::doPIC && offset->op_kind_ == Opd_StImmediate && + (((StImmOperand *)offset)->GetSymbol()->GetStorageClass() == + kScGlobal || + ((StImmOperand *)offset)->GetSymbol()->GetStorageClass() == + kScExtern)) { + emitter.Emit("#:got_lo12:"); + emitter.Emit(((StImmOperand *)offset)->GetName()); + } else { + CG_ASSERT(!IsPIMMOffsetOutOfRange(offset->GetOffsetValue(), size_), ""); + if (!offset->IsZero()) { + offset->Emit(emitter, nullptr); } + } } emitter.Emit("("); Riscv64RegOperand *baseReg = static_cast(GetBaseRegister()); diff --git a/mapleall/maple_be/src/cg/riscv64/riscv64_peep.cpp b/mapleall/maple_be/src/cg/riscv64/riscv64_peep.cpp index 61af315669ea5d30912fdfaeb0897826a383c86f..a8464a6623dd6dc9cb51df809ae9f0a8bf6a3d95 100644 --- a/mapleall/maple_be/src/cg/riscv64/riscv64_peep.cpp +++ b/mapleall/maple_be/src/cg/riscv64/riscv64_peep.cpp @@ -807,6 +807,7 @@ Insn *Riscv64Peep::DefInsnOfOperandInBB(BB *bb, Insn *startinsn, Insn *checkinsn void Riscv64Peep::PrePeepholeOpt() { RemoveSext(); ReplaceInstruction(); + ComplexMemOperandOpt(); } void Riscv64Peep::PrePeepholeOpt1() { @@ -848,6 +849,130 @@ void Riscv64Peep::ReplaceInstruction() { } } +/* Check if a regOpnd is live after insn. True if live, otherwise false. + */ +bool Riscv64Peep::IfOperandIsLiveAfterInsn(RegOperand *regOpnd, Insn *insn) { + CG_ASSERT(insn, "insn should not be nullptr."); + + for (Insn *nextInsn = insn->next; + nextInsn && nextInsn != insn->bb->lastinsn->next; + nextInsn = nextInsn->next) { + if (!nextInsn->IsMachineInstruction()) { + continue; + } + + for (int i = Insn::kMaxOperandNum - 1; i >= 0; i--) { + Operand *opnd = nextInsn->opnds[i]; + if (opnd == nullptr) { + continue; + } + + if (opnd->IsMemoryAccessOperand()) { + MemOperand *mem = static_cast(opnd); + Operand *base = mem->GetBaseRegister(); + Operand *offset = mem->GetOffset(); + + if (base && base->IsRegister()) { + RegOperand *tmpRegOpnd = static_cast(base); + if (tmpRegOpnd->GetRegisterNumber() == regOpnd->GetRegisterNumber()) { + return true; + } + } + if (offset && offset->IsRegister()) { + RegOperand *tmpRegOpnd = static_cast(offset); + if (tmpRegOpnd->GetRegisterNumber() == regOpnd->GetRegisterNumber()) { + return true; + } + } + } + + if (opnd->IsRegister()) { + RegOperand *tmpRegOpnd = static_cast(opnd); + if (tmpRegOpnd->GetRegisterNumber() == regOpnd->GetRegisterNumber()) { + const Riscv64MD *md = + &Riscv64CG::kMd[static_cast(nextInsn)->mop_]; + Riscv64OpndProp *regprop = + static_cast(md->operand_[i]); + bool isUse = regprop->IsUse(); + if (isUse) { + return true; + } else { + // Redefined, no need to check live-out. + return false; + } + } + } + } + } + + // Check if it is live-out. + if (insn->bb->liveout_regno.find(regOpnd->GetRegisterNumber()) != + insn->bb->liveout_regno.end()) { + return true; + } + + return false; +} + +/* addi rY, rX, %lo(a) + ld rZ, (rY) + ==> + ld rZ, %lo(a)(rX) + */ +void Riscv64Peep::ComplexMemOperandOpt() { + Riscv64CGFunc *acgfunc = static_cast(cgfunc); + FOR_ALL_BB(bb, acgfunc) { + Insn *nextInsn = nullptr; + + for (Insn *insn = bb->firstinsn; insn; insn = nextInsn) { + nextInsn = insn->GetNextMachineInsn(); + if (nextInsn == nullptr) { + continue; + } + MOperator thisMop = insn->GetMachineOpcode(); + if (thisMop == MOP_adrpl12) { + MOperator nextMop = nextInsn->GetMachineOpcode(); + if (nextMop && ((nextMop >= MOP_wldrsb && nextMop <= MOP_dldr) || + (nextMop >= MOP_wstrb && nextMop <= MOP_dstr))) { + // Check if base register of nextInsn and the dest operand of insn are + // identical. + Riscv64MemOperand *memOpnd = + static_cast(nextInsn->GetMemOpnd()); + CG_ASSERT(memOpnd != nullptr, + "memOpnd is null in Riscv64Peep::ComplexMemOperandOpt"); + + RegOperand *regOpnd = static_cast(insn->GetOperand(0)); + + // Check if dest operand of add insn is identical with base register + // of nextInsn. + if (memOpnd->GetBaseRegister() != regOpnd) { + continue; + } + + // Check if rY is used after ldr insn or if it is in live-out. + if (IfOperandIsLiveAfterInsn(regOpnd, nextInsn)) { + continue; + } + + StImmOperand *stImmOpnd = + static_cast(insn->GetOperand(2)); + Riscv64OfstOperand *offopnd = acgfunc->GetOrCreateOfstOpnd( + stImmOpnd->GetOffset() + + memOpnd->GetOffsetImmediate()->GetOffsetValue(), + 32); + RegOperand *newBaseOpnd = + static_cast(insn->GetOperand(1)); + Riscv64MemOperand *newMemOpnd = acgfunc->GetOrCreateMemOpnd( + memOpnd->GetSize(), newBaseOpnd, nullptr, offopnd, + stImmOpnd->GetSymbol()); + nextInsn->SetOperand(1, newMemOpnd); + bb->RemoveInsn(insn); + } + } + } + } +} + AnalysisResult *CgDoPrePeepHole::Run(CGFunc *cgfunc, CgFuncResultMgr *m) { LiveAnalysis *live = nullptr; // It doesn't need live range information when -O1, because the register will not live out of bb.