From bb4830c53eebecf67facf781b118747b83611b49 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Mon, 22 Jul 2024 19:25:05 +0800 Subject: [PATCH] [CodeGen] Support store frametype and jsfunc before prologue Sink the store for frametype and jsfunc from arkcompiler to llvm backend. 1. frametype is recorded in the attribute of function. Just store it to stack. 2. jsfunc is passed in the arguments, the index is recorded in the attribute of function. Use it and the calling convention to find out the jsfunc and store it to stack. Issue: https://gitee.com/openharmony/third_party_llvm-project/issues/IADN8Z Signed-off-by: ZhouGuangyuan --- llvm/include/llvm/CodeGen/MachineFunction.h | 13 ++ .../llvm/CodeGen/TargetFrameLowering.h | 9 + llvm/lib/CodeGen/PrologEpilogInserter.cpp | 10 + llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp | 8 + .../Target/AArch64/AArch64FrameLowering.cpp | 201 ++++++++++++++++++ .../lib/Target/AArch64/AArch64FrameLowering.h | 5 + .../Target/AArch64/AArch64ISelLowering.cpp | 12 ++ .../AArch64/AArch64MachineFunctionInfo.h | 15 ++ llvm/lib/Target/X86/X86FrameLowering.cpp | 64 ++++++ llvm/lib/Target/X86/X86FrameLowering.h | 6 + llvm/lib/Target/X86/X86ISelLowering.cpp | 12 ++ llvm/lib/Target/X86/X86MachineFunctionInfo.h | 16 ++ llvm/test/CMakeLists.txt | 1 + .../CodeGen/AArch64/ArkCompiler/frame-save.ll | 201 ++++++++++++++++++ .../CodeGen/X86/ArkCompiler/frame-save.ll | 40 ++++ llvm/test/lit.cfg.py | 3 + llvm/test/lit.site.cfg.py.in | 1 + 17 files changed, 617 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/ArkCompiler/frame-save.ll create mode 100644 llvm/test/CodeGen/X86/ArkCompiler/frame-save.ll diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index 958c5b9625c2..4846a4cb9c99 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -93,6 +93,19 @@ template <> struct ilist_callback_traits { /// of type are accessed/created with MF::getInfo and destroyed when the /// MachineFunction is destroyed. struct MachineFunctionInfo { + +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL begin + struct ArkArgInfo { + int64_t MemOffset; + Register Reg; + int32_t OriginIndex; + ArkArgInfo(int64_t MemOffset, Register Reg, int32_t OriginIndex) + : MemOffset(MemOffset), Reg(Reg), OriginIndex(OriginIndex) {} + }; + // OHOS_LOCAL end +#endif + virtual ~MachineFunctionInfo(); /// Factory function: default behavior is to call new using the diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 2e96fcd0415d..5ac6ee4dd0aa 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -306,6 +306,15 @@ public: virtual int getArkFrameAdaptationOffset(const MachineFunction &MF) const { return 0; } + +#ifdef ARK_GC_SUPPORT + virtual void adjustForArkFrame(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} + static const std::string TypeKey; + static const std::string JSFuncIdxKey; + static const std::string TypeOffsetKey; + static const std::string JSFuncIdxOffsetKey; +#endif // OHOS_LOCAL end /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 5dbcd0facfd1..441523c3b879 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -1405,6 +1405,16 @@ void PEI::insertPrologEpilogCode(MachineFunction &MF) { for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.adjustForSegmentedStacks(MF, *SaveBlock); } + // OHOS_LOCAL begin +#ifdef ARK_GC_SUPPORT + // Insert the prologue to save ark-frame-type + if (MF.getFunction().hasFnAttribute(TargetFrameLowering::TypeKey) || + MF.getFunction().hasFnAttribute(TargetFrameLowering::JSFuncIdxKey)) { + for (MachineBasicBlock *SaveBlock : SaveBlocks) + TFI.adjustForArkFrame(MF, *SaveBlock); + } +#endif + // OHOS_LOCAL end // Emit additional code that is required to explicitly handle the stack in // HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The diff --git a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp index 0e026bdf42f1..ef8261e845fb 100644 --- a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp +++ b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp @@ -181,6 +181,7 @@ TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const { } #ifdef ARK_GC_SUPPORT +// OHOS_LOCAL begin int TargetFrameLowering::GetFrameReserveSize(MachineFunction &MF) const { int slotSize = sizeof(uint64_t); @@ -192,4 +193,11 @@ int TargetFrameLowering::GetFrameReserveSize(MachineFunction &MF) const .getAsInteger(10, marker); return marker; } + +const std::string TargetFrameLowering::TypeKey = "ark-frame-type"; +const std::string TargetFrameLowering::JSFuncIdxKey = "ark-jsfunc-arg-idx"; +const std::string TargetFrameLowering::TypeOffsetKey = TypeKey + "-offset"; +const std::string TargetFrameLowering::JSFuncIdxOffsetKey = + JSFuncIdxKey + "-offset"; +// OHOS_LOCAL end #endif diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 43ee70edcd23..a27de4b7d769 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1656,6 +1656,18 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, assert(Prolog->getOpcode() == AArch64::HOM_Prolog); Prolog->addOperand(MachineOperand::CreateImm(FPOffset)); } else { +#ifdef ARK_GC_SUPPORT + if (!CombineSPBump) { + auto ReserveSize = alignTo(GetFrameReserveSize(MF), getStackAlign()); + emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, + StackOffset::getFixed(-ReserveSize), TII, + MachineInstr::FrameSetup, false, NeedsWinCFI, + &HasWinCFI, EmitCFI, + StackOffset::getFixed(PrologueSaveSize)); + NumBytes -= ReserveSize; + FPOffset += ReserveSize; + } +#endif // Issue sub fp, sp, FPOffset or // mov fp,sp when FPOffset is zero. // Note: All stores of callee-saved registers are marked as "FrameSetup". @@ -4029,3 +4041,192 @@ void AArch64FrameLowering::orderFrameObjects( dbgs() << "\n"; }); } + +#ifdef ARK_GC_SUPPORT +// OHOS_LOCAL begin +namespace { +int64_t getStringAttrToInt(const Function &F, const StringRef Key) { + int64_t Value = 0; + bool Res = F.getFnAttribute(Key).getValueAsString().getAsInteger(10,Value); + assert(!Res && "Can get attribute to int"); + return Value; +} +} // namespace + +static bool useTempBaseRegisterIfNeed( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, const TargetInstrInfo *TII, unsigned Opcode, + int32_t MaxNeedOffset, int32_t &NewBaseOffset, Register &BaseReg) { + TypeSize Scale = TypeSize::Fixed(1); + unsigned Width; + int64_t MinOffset; + int64_t MaxOffset; + bool Res = AArch64InstrInfo::getMemOpInfo(Opcode, Scale, Width, MinOffset, + MaxOffset); + assert(Res && "Unsupported opcode"); + if (MaxNeedOffset > Scale * MaxOffset) { + auto NewBaseRegister = AArch64::X16; + emitFrameOffset(MBB, MBBI, DL, NewBaseRegister, BaseReg, + StackOffset::getFixed(NewBaseOffset), TII); + BaseReg = NewBaseRegister; + NewBaseOffset = 0; + return true; + } + return false; +} + +void AArch64FrameLowering::adjustForArkFrame( + MachineFunction &MF, MachineBasicBlock &PrologueMBB) const { + const auto &F = MF.getFunction(); + AArch64FunctionInfo *AFI = MF.getInfo(); + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const AArch64InstrInfo *TII = + MF.getSubtarget().getInstrInfo(); + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + assert(F.hasFnAttribute("fpToCallerSpDelta") && "missing fpToCallerSpDelta"); + const StringRef FPToCallerSPDeltaStr = + F.getFnAttribute("fpToCallerSpDelta").getValueAsString(); + const int64_t FPToCallerSPDelta = std::stoi(FPToCallerSPDeltaStr.str()); + + MachineBasicBlock::iterator InsertPos; + // if CombineSPBump, the sp is updated once at the entry of the function. + // the frametype and jsfunc should be saved after sp is updated. + // if CombineSPBump is false, the sp is updated at least twice, the frametype + // and jsfunc should be saved before fp is updated. + bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, MFI.getStackSize()); + Register DefineReg = CombineSPBump ? AArch64::SP : AArch64::FP; + for (auto &Iter : PrologueMBB) { + if (Iter.definesRegister(DefineReg, RegInfo)) { + InsertPos = Iter; + break; + } + } + if (CombineSPBump) { + // the InsertPos should be the position after sp update. + InsertPos = InsertPos->getNextNode(); + if (InsertPos->isCFIInstruction()) { + InsertPos = InsertPos->getNextNode(); + } + } + uint64_t ReserveSize = alignTo(GetFrameReserveSize(MF), getStackAlign()); + uint64_t SPOffset = + CombineSPBump ? MFI.getStackSize() : ReserveSize + FPToCallerSPDelta; + + assert(InsertPos.isValid() && InsertPos->isCFIInstruction() && + "Can't find the instruction to update fp"); + + DebugLoc DL = InsertPos->getDebugLoc(); + + struct SaveInfo { + bool NeedSave; + Register Reg; + int32_t Offset; + uint32_t RegState; + bool operator<(const SaveInfo &Other) const { + return this->Offset < Other.Offset; + } + }; + + SaveInfo FrameTypeInfo = SaveInfo{false, MCRegister::NoRegister, 0, 0}; + SaveInfo JSFuncArgInfo = SaveInfo{false, MCRegister::NoRegister, 0, 0}; + + if (F.hasFnAttribute(TypeKey)) { + assert(F.hasFnAttribute(TypeOffsetKey) && "missing ark-frame-type-offset"); + const int64_t ArkFrameType = getStringAttrToInt(F, TypeKey); + const int32_t FrameTypeOffset = getStringAttrToInt(F, TypeOffsetKey); + Register ScratchFrameTypeReg; + uint32_t Flags = 0; + if (ArkFrameType == 0) { + // ScratchFrameTypeReg is zxr + ScratchFrameTypeReg = AArch64::XZR; + } else { + // mov x8, #ArkFrameType + ScratchFrameTypeReg = AArch64::X8; + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::MOVi64imm), + ScratchFrameTypeReg) + .addImm(ArkFrameType); + Flags = RegState::Kill; + // after store. x8 will not be used. So mark it kill. + } + FrameTypeInfo = SaveInfo{true, ScratchFrameTypeReg, FrameTypeOffset, Flags}; + } + + if (F.hasFnAttribute(JSFuncIdxKey)) { + assert(F.hasFnAttribute(JSFuncIdxOffsetKey) && + "missing ark-jsfunc-arg-idx-offset"); + const int64_t JSFuncIdx = getStringAttrToInt(F, JSFuncIdxKey); + const int32_t JSFuncOffset = getStringAttrToInt(F, JSFuncIdxOffsetKey); + using ArkArgInfo = MachineFunctionInfo::ArkArgInfo; + const ArkArgInfo *JSFuncArg = + llvm::find_if(AFI->getArkArgInfos(), [JSFuncIdx](const ArkArgInfo Arg) { + return Arg.OriginIndex == JSFuncIdx; + }); + + Register ScratchJSFuncReg; + unsigned Flags = 0; + if (JSFuncArg->Reg != MCRegister::NoRegister) { + // ScratchJSFuncReg is the JSFuncIdx arg register. + ScratchJSFuncReg = JSFuncArg->Reg; + } else { + Register TempSP = AArch64::SP; + int32_t ArgToTempSP = SPOffset + JSFuncArg->MemOffset; + useTempBaseRegisterIfNeed(PrologueMBB, InsertPos, DL, TII, + AArch64::LDRXui, ArgToTempSP, ArgToTempSP, + TempSP); + // ldr x9, [TempSP, #SPOffset+JSFuncArg->MemOffset] + ScratchJSFuncReg = AArch64::X9; + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::LDRXui)) + .addDef(ScratchJSFuncReg) + .addUse(TempSP) + .addImm(ArgToTempSP / 8); + Flags = RegState::Kill; + // after store. x9 will not be used. So mark it kill. + } + JSFuncArgInfo = SaveInfo{true, ScratchJSFuncReg, JSFuncOffset, Flags}; + } + + const bool CanUseSTP = + (FrameTypeInfo.NeedSave && JSFuncArgInfo.NeedSave && + std::abs(FrameTypeInfo.Offset - JSFuncArgInfo.Offset) == 8); + // 8 bytes distance store can be combined to stp + + const int32_t MaxSaveOffset = + std::max(FrameTypeInfo.Offset, JSFuncArgInfo.Offset); + Register TempSP = AArch64::SP; + int32_t ArkSlotToTempSP = SPOffset - FPToCallerSPDelta - MaxSaveOffset; + int32_t MaxSaveSlotToTempSP = ArkSlotToTempSP + MaxSaveOffset; + + useTempBaseRegisterIfNeed(PrologueMBB, InsertPos, DL, TII, + CanUseSTP ? AArch64::STPXi : AArch64::STRXui, + CanUseSTP ? ArkSlotToTempSP : MaxSaveSlotToTempSP, + ArkSlotToTempSP, TempSP); + + if (CanUseSTP) { + auto Max = std::max(FrameTypeInfo, JSFuncArgInfo); + auto Min = std::min(FrameTypeInfo, JSFuncArgInfo); + // stp RegArg, x8, [TempSP, #ArkSlotToTempSP] + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::STPXi)) + .addUse(Max.Reg, Max.RegState) + .addUse(Min.Reg, Min.RegState) + .addReg(TempSP) + .addImm(ArkSlotToTempSP / 8); + return; + } + + if (FrameTypeInfo.NeedSave) { + // stur x8, [TempSP, #(ArkSlotToTempSP+MaxSaveOffset-FrameTypeInfo.Offset)] + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::STRXui)) + .addUse(FrameTypeInfo.Reg, FrameTypeInfo.RegState) + .addReg(TempSP) + .addImm((ArkSlotToTempSP + (MaxSaveOffset - FrameTypeInfo.Offset)) / 8); + } + if (JSFuncArgInfo.NeedSave) { + // stur x9, [TempSP, #(ArkSlotToTempSP+MaxSaveOffset-JSFuncArgInfo.Offset)] + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::STRXui)) + .addUse(JSFuncArgInfo.Reg, JSFuncArgInfo.RegState) + .addReg(TempSP) + .addImm((ArkSlotToTempSP + (MaxSaveOffset - JSFuncArgInfo.Offset)) / 8); + } +} +// OHOS_LOCAL end +#endif diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h index 221f92856c55..91d399d40457 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -83,6 +83,11 @@ public: } int getArkFrameAdaptationOffset(const MachineFunction &MF) const override; + +#ifdef ARK_GC_SUPPORT + void adjustForArkFrame(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const override; +#endif // OHOS_LOCAL end bool hasFP(const MachineFunction &MF) const override; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index d742d87eca22..fa0dd4421823 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5916,6 +5916,11 @@ SDValue AArch64TargetLowering::LowerFormalArguments( ArgValue = DAG.getZExtOrTrunc(ArgValue, DL, VA.getValVT()); break; } +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL + // Record the register and index of every argument which in register. + FuncInfo->addArkArgInfo(0, VA.getLocReg(), Ins[i].getOrigArgIndex()); +#endif } else { // VA.isRegLoc() assert(VA.isMemLoc() && "CCValAssign is neither reg nor mem"); unsigned ArgOffset = VA.getLocMemOffset(); @@ -5963,6 +5968,13 @@ SDValue AArch64TargetLowering::LowerFormalArguments( ArgValue = DAG.getExtLoad(ExtType, DL, VA.getLocVT(), Chain, FIN, MachinePointerInfo::getFixedStack(MF, FI), MemVT); +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL + // Record the offset (relative to SP) and index of every argument which on + // stack. + FuncInfo->addArkArgInfo(VA.getLocMemOffset(), MCRegister::NoRegister, + Ins[i].getOrigArgIndex()); +#endif } if (VA.getLocInfo() == CCValAssign::Indirect) { diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h index c658f821464e..707c542685db 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -189,6 +189,11 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { /// Temporary symbol used by PARTS to generate a runtime dependent modifier based on /// the position of function. Epilogue emission relys on this value beging set. MCSymbol *PartsSym = nullptr; // OHOS_LOCAL + +#ifdef ARK_GC_SUPPORT + SmallVector ArkArgInfos; // OHOS_LOCAL +#endif + public: explicit AArch64FunctionInfo(MachineFunction &MF); @@ -438,6 +443,16 @@ public: // OHOS_LOCAL begin void setPartsSym(MCSymbol *Sym) { PartsSym = Sym; } MCSymbol *getPartsSym() const { return PartsSym; } + +#ifdef ARK_GC_SUPPORT + void addArkArgInfo(int64_t MemOffset, Register Reg, int32_t OriginIndex) { + ArkArgInfos.emplace_back(MemOffset, Reg, OriginIndex); + } + SmallVector getArkArgInfos() const { + return ArkArgInfos; + } +#endif + // OHOS_LOCAL end private: // Hold the lists of LOHs. diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 0267b00aefba..677a490d2046 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -3977,4 +3977,68 @@ void X86FrameLowering::restoreWinEHStackPointersInParent( int X86FrameLowering::getOffsetOfLocalArea(CallingConv::ID CC) const { return CC == CallingConv::ArkInt ? 0 : TargetFrameLowering::getOffsetOfLocalArea(); } + +#ifdef ARK_GC_SUPPORT +namespace { +int64_t getStringAttrToInt(const Function &F, const StringRef Key) { + int64_t Value = 0; + bool Res = F.getFnAttribute(Key).getValueAsString().getAsInteger(10,Value); + assert(!Res && "Can get attribute to int"); + return Value; +} +} // namespace + +void X86FrameLowering::adjustForArkFrame(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const { + const auto &F = MF.getFunction(); + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const X86MachineFunctionInfo *FuncInfo = MF.getInfo(); + assert(Uses64BitFramePtr && "only support 64Bit Frame Pointer"); + const int64_t FPSlot = hasFP(MF) ? 8 : 0; + auto InsertPos = PrologueMBB.begin(); + auto DL = InsertPos->getDebugLoc(); + if (F.hasFnAttribute(TypeKey)) { + assert(F.hasFnAttribute(TypeOffsetKey) && "missing ark-frame-type-offset"); + const int64_t ArkFrameType = getStringAttrToInt(F, TypeKey); + const int64_t FrameTypeOffset = getStringAttrToInt(F, TypeOffsetKey); + // movq $ArkFrameType, (-FPSlot - FrameTypeOffset)(%rsp) + addRegOffset(BuildMI(PrologueMBB, InsertPos, InsertPos->getDebugLoc(), + TII.get(X86::MOV64mi32)), + StackPtr, false, -FPSlot - FrameTypeOffset) + .addImm(ArkFrameType); + } + if (F.hasFnAttribute(JSFuncIdxKey)) { + assert(F.hasFnAttribute(JSFuncIdxOffsetKey) && + "missing ark-jsfunc-arg-idx-offset"); + + const int64_t JSFuncIdx = getStringAttrToInt(F, JSFuncIdxKey); + const int64_t JSFuncOffset = getStringAttrToInt(F, JSFuncIdxOffsetKey); + + using ArkArgInfo = MachineFunctionInfo::ArkArgInfo; + ArkArgInfo *JSFuncArg = + llvm::find_if(FuncInfo->getArkArgInfos(), [JSFuncIdx](ArkArgInfo Arg) { + return Arg.OriginIndex == JSFuncIdx; + }); + + Register ScratchJSFuncReg; + unsigned Flags = 0; + if (JSFuncArg->Reg != MCRegister::NoRegister) { + // ScratchJSFuncReg is the JSFuncIdx arg register. + ScratchJSFuncReg = JSFuncArg->Reg; + } else { + // mov (retaddrsize + JSFuncArg->MemOffset)(%rsp),%ScratchJSFuncReg + constexpr int Retaddrsize = 8; + ScratchJSFuncReg = GetScratchRegister(Is64Bit, IsLP64, MF, true); + addRegOffset(BuildMI(PrologueMBB, InsertPos, DL, TII.get(X86::MOV64rm), + ScratchJSFuncReg), + StackPtr, false, Retaddrsize + JSFuncArg->MemOffset); + Flags = RegState::Kill; + } + // mov %ScratchJSFuncReg,(-FPSlot - JSFuncOffset)(%rsp) + addRegOffset(BuildMI(PrologueMBB, InsertPos, DL, TII.get(X86::MOV64mr)), + StackPtr, false, -FPSlot - JSFuncOffset) + .addReg(ScratchJSFuncReg, Flags); + } +} // OHOS_LOCAL end +#endif diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h index 9783c7ca2d35..1857878ee348 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.h +++ b/llvm/lib/Target/X86/X86FrameLowering.h @@ -280,6 +280,12 @@ private: // OHOS_LOCAL begin int getOffsetOfLocalArea(CallingConv::ID CC = CallingConv::C) const override; + +#ifdef ARK_GC_SUPPORT + void adjustForArkFrame(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const override; +#endif + // OHOS_LOCAL end }; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 3f8336b25900..527ca29e58d9 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4157,10 +4157,22 @@ SDValue X86TargetLowering::LowerFormalArguments( } else ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); } +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL + // Record the register and index of every argument which in register. + FuncInfo->addArkArgInfo(0, VA.getLocReg(), Ins[InsIndex].getOrigArgIndex()); +#endif } else { assert(VA.isMemLoc()); ArgValue = LowerMemArgument(Chain, CallConv, Ins, dl, DAG, VA, MFI, InsIndex); +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL + // Record the offset (relative to SP) and index of every argument which on + // stack. + FuncInfo->addArkArgInfo(VA.getLocMemOffset(), MCRegister::NoRegister, + Ins[InsIndex].getOrigArgIndex()); +#endif } // If value is passed via pointer - do a load. diff --git a/llvm/lib/Target/X86/X86MachineFunctionInfo.h b/llvm/lib/Target/X86/X86MachineFunctionInfo.h index 99cc9f525b2c..84df3a390047 100644 --- a/llvm/lib/Target/X86/X86MachineFunctionInfo.h +++ b/llvm/lib/Target/X86/X86MachineFunctionInfo.h @@ -125,6 +125,10 @@ class X86MachineFunctionInfo : public MachineFunctionInfo { SmallVector PreallocatedStackSizes; SmallVector, 0> PreallocatedArgOffsets; +#ifdef ARK_GC_SUPPORT + SmallVector ArkArgInfos; // OHOS_LOCAL +#endif + private: /// ForwardedMustTailRegParms - A list of virtual and physical registers /// that must be forwarded to every musttail call. @@ -253,6 +257,18 @@ public: assert(!PreallocatedArgOffsets[Id].empty() && "arg offsets not set"); return PreallocatedArgOffsets[Id]; } + +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL begin + void addArkArgInfo(int64_t MemOffset, Register Reg, int32_t OriginIndex) { + ArkArgInfos.emplace_back(MemOffset, Reg, OriginIndex); + } + SmallVector getArkArgInfos() const { + return ArkArgInfos; + } + // OHOS_LOCAL end +#endif + }; } // End llvm namespace diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt index e7dd22261cc4..dd55dd4ff804 100644 --- a/llvm/test/CMakeLists.txt +++ b/llvm/test/CMakeLists.txt @@ -24,6 +24,7 @@ llvm_canonicalize_cmake_booleans( LLVM_ENABLE_EXPENSIVE_CHECKS LLVM_INCLUDE_DXIL_TESTS LLVM_TOOL_LLVM_DRIVER_BUILD + BUILD_ARK_GC_SUPPORT ) configure_lit_site_cfg( diff --git a/llvm/test/CodeGen/AArch64/ArkCompiler/frame-save.ll b/llvm/test/CodeGen/AArch64/ArkCompiler/frame-save.ll new file mode 100644 index 000000000000..792196fe7353 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ArkCompiler/frame-save.ll @@ -0,0 +1,201 @@ +; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 < %s | FileCheck %s +; ark-compiler use aarch64-unknown-linux-gnu as target currently, so use same target instead of ohos target to test it. + +; REQUIRES: ark_gc_support + +; CHECK-LABEL: SaveFrameType0: +; CHECK: sub sp, sp, #32 +; CHECK: str xzr, [sp, #8] +; CHECK: add x29, sp, #16 +define i32 @SaveFrameType0() #0 { +entry: + ret i32 0 +} +attributes #0 = { "ark-frame-type"="0" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameType1: +; CHECK: sub sp, sp, #32 +; CHECK: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #8] +; CHECK: add x29, sp, #16 +define i32 @SaveFrameType1() #1 { +entry: + ret i32 0 +} +attributes #1 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeAndJsfunc0: +; CHECK: stp x0, xzr, [sp, #-32]! +; CHECK: add x29, sp, #16 +define i32 @SaveFrameTypeAndJsfunc0(i64 %i) #2 { +entry: + ret i32 0 +} +attributes #2 = { "ark-frame-type"="0" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="0" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeAndJsfunc1: +; CHECK: mov x8, #24 +; CHECK-NEXT: stp x0, x8, [sp, #-32]! +; CHECK: add x29, sp, #16 +define i32 @SaveFrameTypeAndJsfunc1(i64 %i) #3 { +entry: + ret i32 0 +} +attributes #3 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="0" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + + +; CHECK-LABEL: SaveFrameTypeAndJsfunc2: +; CHECK: sub sp, sp, #32 +; CHECK: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #32] +; CHECK-NEXT: stp x9, x8, [sp] +; CHECK: add x29, sp, #16 +define webkit_jscc i32 @SaveFrameTypeAndJsfunc2(i64 %i, i64 %j) #4 { +entry: + ret i32 0 +} +attributes #4 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeWithLargeStack: +; CHECK: sub sp, sp, #496 +; CHECK-NEXT: .cfi_def_cfa_offset 496 +; CHECK-NEXT: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #456] +; CHECK: add x29, sp, #464 +define i32 @SaveFrameTypeWithLargeStack() #5 { +entry: + %buf = alloca [56 x i64], align 8 + ret i32 0 +} +attributes #5 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeWithLargeStack1: +; CHECK: sub sp, sp, #496 +; CHECK-NEXT: .cfi_def_cfa_offset 496 +; CHECK-NEXT: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #456] +; CHECK: add x29, sp, #464 +define i32 @SaveFrameTypeWithLargeStack1() #6 { +entry: + %buf = alloca [57 x i64], align 8 + ret i32 0 +} +attributes #6 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeWithLargeStack2: +; CHECK: stp x29, x30, [sp, #-32]! +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #8] +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #464 +define i32 @SaveFrameTypeWithLargeStack2() #7 { +entry: + %buf = alloca [58 x i64], align 8 + ret i32 0 +} +attributes #7 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeWithHugeStack: +; CHECK: stp x29, x30, [sp, #-32]! +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #8] +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #127, lsl #12 +; CHECK-NEXT: sub sp, sp, #4080 + +define i32 @SaveFrameTypeWithHugeStack() #7 { +entry: + %buf = alloca [65535 x i64], align 8 + ret i32 0 +} +attributes #7 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack: +; CHECK: sub sp, sp, #496 +; CHECK-NEXT: .cfi_def_cfa_offset 496 +; CHECK-NEXT: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #496] +; CHECK-NEXT: stp x9, x8, [sp, #448] +; CHECK: add x29, sp, #464 +define webkit_jscc i32 @SaveFrameTypeAndJsfuncWithLargeStack(i64 %i, i64 %j) #8 { +entry: + %buf = alloca [56 x i64], align 8 + ret i32 0 +} +attributes #8 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack1: +; CHECK: stp x29, x30, [sp, #-32]! +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #48] +; CHECK-NEXT: stp x9, x8, [sp] +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #464 + +define webkit_jscc i32 @SaveFrameTypeAndJsfuncWithLargeStack1(i64 %i, i64 %j) #9 { +entry: + %buf = alloca [57 x i64], align 8 + ret i32 0 +} +attributes #9 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack2: +; CHECK: stp x29, x30, [sp, #-32]! +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK: mov x8, #24 +; CHECK: stp x1, x8, [sp, #-16]! +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #464 + +define i32 @SaveFrameTypeAndJsfuncWithLargeStack2(i64 %i, i64 %j) #10 { +entry: + %buf = alloca [57 x i64], align 8 + ret i32 0 +} +attributes #10 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack3: +; CHECK: sub sp, sp, #496 +; CHECK-NEXT: .cfi_def_cfa_offset 496 +; CHECK-NEXT: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #496] +; CHECK-NEXT: stp x9, x8, [sp, #384] +; CHECK: add x29, sp, #400 + +define webkit_jscc i32 @SaveFrameTypeAndJsfuncWithLargeStack3(i64 %i, i64 %j) #11 { +entry: + %buf = alloca [47 x i64], align 8 + call void asm sideeffect "nop", "~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{memory}"() nounwind + ret i32 0 +} +attributes #11 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack4: +; CHECK: stp x29, x30, [sp, #-96]! +; CHECK-NEXT: .cfi_def_cfa_offset 96 +; CHECK: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 112 +; CHECK-NEXT: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #112] +; CHECK-NEXT: stp x9, x8, [sp] +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #400 + +define webkit_jscc i32 @SaveFrameTypeAndJsfuncWithLargeStack4(i64 %i, i64 %j) #12 { +entry: + %buf = alloca [48 x i64], align 8 + call void asm sideeffect "nop", "~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{memory}"() nounwind + ret i32 0 +} +attributes #12 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } diff --git a/llvm/test/CodeGen/X86/ArkCompiler/frame-save.ll b/llvm/test/CodeGen/X86/ArkCompiler/frame-save.ll new file mode 100644 index 000000000000..2d4bb27e22fd --- /dev/null +++ b/llvm/test/CodeGen/X86/ArkCompiler/frame-save.ll @@ -0,0 +1,40 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O2 < %s | FileCheck %s +; ark-compiler use x86_64-unknown-linux-gnu as target currently, so use same target instead of ohos target to test it. + +; REQUIRES: ark_gc_support + +; CHECK-LABEL: saveframetype0: +; CHECK: movq $0, -16(%rsp) +; CHECK-NEXT: pushq %rbp +; CHECK: movq %rsp, %rbp +; CHECK: subq $16, %rsp +define i32 @saveframetype0() #0 { +entry: + ret i32 0 +} +attributes #0 = { "ark-frame-type"="0" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: saveframetypeAndJsfunc0: +; CHECK: movq $0, -16(%rsp) +; CHECK: movq %rdi, -24(%rsp) +; CHECK-NEXT: pushq %rbp +; CHECK: movq %rsp, %rbp +; CHECK: subq $16, %rsp +define i32 @saveframetypeAndJsfunc0(i64 %i) #2 { +entry: + ret i32 0 +} +attributes #2 = { "ark-frame-type"="0" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="0" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: saveframetypeAndJsfunc2: +; CHECK: movq $24, -16(%rsp) +; CHECK-NEXT: movq 8(%rsp), %r11 +; CHECK-NEXT: movq %r11, -24(%rsp) +; CHECK-NEXT: pushq %rbp +; CHECK: movq %rsp, %rbp +; CHECK: subq $16, %rsp +define webkit_jscc i32 @saveframetypeAndJsfunc2(i64 %i, i64 %j) #4 { +entry: + ret i32 0 +} +attributes #4 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } \ No newline at end of file diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py index 75a38b4c5dad..bbd0c983bc9e 100644 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -354,6 +354,9 @@ if config.target_triple: if config.have_llvm_driver: config.available_features.add('llvm-driver') +if config.ark_gc_support: + config.available_features.add('ark_gc_support') + import subprocess diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in index 09210e2e56d4..0192624cd230 100644 --- a/llvm/test/lit.site.cfg.py.in +++ b/llvm/test/lit.site.cfg.py.in @@ -62,6 +62,7 @@ config.llvm_raevict_model_autogenerated = @LLVM_RAEVICT_MODEL_AUTOGENERATED@ config.expensive_checks = @LLVM_ENABLE_EXPENSIVE_CHECKS@ config.dxil_tests = @LLVM_INCLUDE_DXIL_TESTS@ config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@ +config.ark_gc_support = "@BUILD_ARK_GC_SUPPORT@" import lit.llvm lit.llvm.initialize(lit_config, config) -- Gitee