From 52a91c7515eef5f1a367759f698177c61d63a030 Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 25 Mar 2024 16:35:27 -0300 Subject: [PATCH] Optmize call convention in SBFv2 --- llvm/lib/Target/SBF/CMakeLists.txt | 1 + llvm/lib/Target/SBF/SBFFunctionInfo.cpp | 28 +++++ llvm/lib/Target/SBF/SBFFunctionInfo.h | 32 ++++++ llvm/lib/Target/SBF/SBFISelLowering.cpp | 78 +++++++++---- llvm/lib/Target/SBF/SBFRegisterInfo.cpp | 25 ++++- llvm/lib/Target/SBF/SBFRegisterInfo.h | 4 + llvm/lib/Target/SBF/SBFSubtarget.cpp | 1 + llvm/lib/Target/SBF/SBFSubtarget.h | 7 +- llvm/lib/Target/SBF/SBFTargetFeatures.td | 5 +- llvm/lib/Target/SBF/SBFTargetMachine.cpp | 10 +- llvm/lib/Target/SBF/SBFTargetMachine.h | 4 + llvm/test/CodeGen/SBF/many_args_new_conv.ll | 115 ++++++++++++++++++++ llvm/test/CodeGen/SBF/stack_args_v2.ll | 2 +- 13 files changed, 284 insertions(+), 28 deletions(-) create mode 100644 llvm/lib/Target/SBF/SBFFunctionInfo.cpp create mode 100644 llvm/lib/Target/SBF/SBFFunctionInfo.h create mode 100644 llvm/test/CodeGen/SBF/many_args_new_conv.ll diff --git a/llvm/lib/Target/SBF/CMakeLists.txt b/llvm/lib/Target/SBF/CMakeLists.txt index 2f0147a5476f1..9e1111d368afb 100644 --- a/llvm/lib/Target/SBF/CMakeLists.txt +++ b/llvm/lib/Target/SBF/CMakeLists.txt @@ -34,6 +34,7 @@ add_llvm_target(SBFCodeGen SBFMIChecking.cpp SBFMISimplifyPatchable.cpp BTFDebug.cpp + SBFFunctionInfo.cpp LINK_COMPONENTS Analysis diff --git a/llvm/lib/Target/SBF/SBFFunctionInfo.cpp b/llvm/lib/Target/SBF/SBFFunctionInfo.cpp new file mode 100644 index 0000000000000..d3c494ae2f347 --- /dev/null +++ b/llvm/lib/Target/SBF/SBFFunctionInfo.cpp @@ -0,0 +1,28 @@ +//=- SBFFunctionInfo.cpp - SBF Machine Function Info ---------=// + +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements SBF-specific per-machine-function +/// information. +/// +//===----------------------------------------------------------------------===// + +#include "SBFFunctionInfo.h" + +namespace llvm { + +void SBFFunctionInfo::storeFrameIndexArgument(int FI) { + frameIndexes.insert(FI); +} + +bool SBFFunctionInfo::containsFrameIndex(int FI) const { + return frameIndexes.find(FI) != frameIndexes.end(); +} + +} // namespace llvm \ No newline at end of file diff --git a/llvm/lib/Target/SBF/SBFFunctionInfo.h b/llvm/lib/Target/SBF/SBFFunctionInfo.h new file mode 100644 index 0000000000000..2316d965366b7 --- /dev/null +++ b/llvm/lib/Target/SBF/SBFFunctionInfo.h @@ -0,0 +1,32 @@ +//=- SBFFunctionInfo.h - SBF machine function info -*- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares SBF-specific per-machine-function information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SBFFUNCTIONINFO_H +#define LLVM_SBFFUNCTIONINFO_H + +#include "SBFSubtarget.h" +#include + +namespace llvm { + +class SBFFunctionInfo final : public MachineFunctionInfo { + std::unordered_set frameIndexes; + +public: + SBFFunctionInfo(const Function &F, const SBFSubtarget *STI){}; + + void storeFrameIndexArgument(int FI); + bool containsFrameIndex(int FI) const; +}; +} // namespace llvm + +#endif // LLVM_SBFFUNCTIONINFO_H \ No newline at end of file diff --git a/llvm/lib/Target/SBF/SBFISelLowering.cpp b/llvm/lib/Target/SBF/SBFISelLowering.cpp index 3ee4fca066c78..4e7051b960a5a 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.cpp +++ b/llvm/lib/Target/SBF/SBFISelLowering.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "SBFFunctionInfo.h" #include "SBFRegisterInfo.h" #include "SBFSubtarget.h" #include "llvm/CodeGen/CallingConvLower.h" @@ -413,8 +414,15 @@ SDValue SBFTargetLowering::LowerFormalArguments( SmallVector ArgLocs; CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); if (Subtarget->isSolana() && Ins.size() > MaxArgs) { - // Pass args 1-4 via registers, remaining args via stack, referenced via SBF::R5 - CCInfo.AnalyzeFormalArguments(Ins, getHasAlu32() ? CC_SBF32_X : CC_SBF64_X); + if (Subtarget->getEnableNewCallConvention()) { + // Pass args 1-5 via registers, remaining args via stack. + CCInfo.AnalyzeFormalArguments(Ins, getHasAlu32() ? CC_SBF32 : CC_SBF64); + } else { + // Pass args 1-4 via registers, remaining args via stack, referenced via + // SBF::R5 + CCInfo.AnalyzeFormalArguments(Ins, + getHasAlu32() ? CC_SBF32_X : CC_SBF64_X); + } } else { // Pass all args via registers CCInfo.AnalyzeFormalArguments(Ins, getHasAlu32() ? CC_SBF32 : CC_SBF64); @@ -461,20 +469,37 @@ SDValue SBFTargetLowering::LowerFormalArguments( EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()); EVT LocVT = VA.getLocVT(); - unsigned Offset; - if (Subtarget->getHasDynamicFrames()) { - // In SBFv2, the arguments are stored on the start of the frame. - Offset = VA.getLocMemOffset() + PtrVT.getFixedSizeInBits() / 8; + SDValue SDV; + if (Subtarget->getEnableNewCallConvention()) { + // In the new convention, arguments are in at the start + // of the callee frame + uint64_t Size = PtrVT.getFixedSizeInBits() / 8; + int64_t Offset = -static_cast(VA.getLocMemOffset() + Size); + int FrameIndex = + MF.getFrameInfo().CreateFixedObject(Size, Offset, false); + SDValue DstAddr = DAG.getFrameIndex(FrameIndex, PtrVT); + MachinePointerInfo DstInfo = + MachinePointerInfo::getFixedStack(MF, FrameIndex, Offset); + SDV = DAG.getLoad(LocVT, DL, Chain, DstAddr, DstInfo); } else { - Offset = SBFRegisterInfo::FrameLength - VA.getLocMemOffset(); + unsigned Offset; + if (Subtarget->getHasDynamicFrames()) { + // In the old convention, the arguments are stored on + // the start of caller the frame. + Offset = VA.getLocMemOffset() + PtrVT.getFixedSizeInBits() / 8; + } else { + Offset = SBFRegisterInfo::FrameLength - VA.getLocMemOffset(); + } + + // Arguments relative to SBF::R5 + unsigned reg = MF.addLiveIn(SBF::R5, &SBF::GPRRegClass); + SDValue Const = DAG.getConstant(Offset, DL, MVT::i64); + SDV = DAG.getCopyFromReg(Chain, DL, reg, + getPointerTy(MF.getDataLayout())); + SDV = DAG.getNode(ISD::SUB, DL, PtrVT, SDV, Const); + SDV = DAG.getLoad(LocVT, DL, Chain, SDV, MachinePointerInfo()); } - // Arguments relative to SBF::R5 - unsigned reg = MF.addLiveIn(SBF::R5, &SBF::GPRRegClass); - SDValue Const = DAG.getConstant(Offset, DL, MVT::i64); - SDValue SDV = DAG.getCopyFromReg(Chain, DL, reg, getPointerTy(MF.getDataLayout())); - SDV = DAG.getNode(ISD::SUB, DL, PtrVT, SDV, Const); - SDV = DAG.getLoad(LocVT, DL, Chain, SDV, MachinePointerInfo()); InVals.push_back(SDV); } else { fail(DL, DAG, "defined with too many args"); @@ -524,8 +549,14 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVector ArgLocs; CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); if (Subtarget->isSolana() && Outs.size() > MaxArgs) { - // Pass args 1-4 via registers, remaining args via stack, referenced via SBF::R5 - CCInfo.AnalyzeCallOperands(Outs, getHasAlu32() ? CC_SBF32_X : CC_SBF64_X); + if (Subtarget->getEnableNewCallConvention()) { + // Pass args 1-5 via registers, remaining args via stack + CCInfo.AnalyzeCallOperands(Outs, getHasAlu32() ? CC_SBF32 : CC_SBF64); + } else { + // Pass args 1-4 via registers, remaining args via stack, referenced via + // SBF::R5 + CCInfo.AnalyzeCallOperands(Outs, getHasAlu32() ? CC_SBF32_X : CC_SBF64_X); + } } else { // Pass all args via registers CCInfo.AnalyzeCallOperands(Outs, getHasAlu32() ? CC_SBF32 : CC_SBF64); @@ -595,6 +626,7 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, Subtarget->getRegisterInfo()->getFrameRegister(MF), getPointerTy(MF.getDataLayout())); + SBFFunctionInfo * SBFFuncInfo = MF.getInfo(); // Stack arguments have to be walked in reverse order by inserting // chained stores, this ensures their order is not changed by the scheduler // and that the push instruction sequence generated is correct, otherwise they @@ -610,13 +642,19 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SDValue DstAddr; MachinePointerInfo DstInfo; if (Subtarget->getHasDynamicFrames()) { - // When dynamic frames are enabled, the frame size is only calculated - // after lowering instructions, so we must place arguments at the start - // of the frame. - int64_t Offset = -static_cast(VA.getLocMemOffset() + - PtrVT.getFixedSizeInBits() / 8); + // In the new call convention, arguments are stored in the callee frame + // The positive offset signals that the variable does not occupy space + // in the caller frame. + int64_t Offset = static_cast(VA.getLocMemOffset() + + PtrVT.getFixedSizeInBits() / 8); + if (!Subtarget->getEnableNewCallConvention()) + // In the old call convention, we place argument at the start of the + // frame in a fixed stack offset. + Offset = -Offset; + int FrameIndex = MF.getFrameInfo().CreateFixedObject( VA.getLocVT().getFixedSizeInBits() / 8, Offset, false); + SBFFuncInfo->storeFrameIndexArgument(FrameIndex); DstAddr = DAG.getFrameIndex(FrameIndex, PtrVT); DstInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex, Offset); } else { diff --git a/llvm/lib/Target/SBF/SBFRegisterInfo.cpp b/llvm/lib/Target/SBF/SBFRegisterInfo.cpp index 15164c37c7121..9e183ca62cedc 100644 --- a/llvm/lib/Target/SBF/SBFRegisterInfo.cpp +++ b/llvm/lib/Target/SBF/SBFRegisterInfo.cpp @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// +#include "SBFFunctionInfo.h" #include "SBFRegisterInfo.h" -#include "SBF.h" #include "SBFSubtarget.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -102,7 +102,7 @@ bool SBFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); if (MI.getOpcode() == SBF::MOV_rr) { - int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex); + int Offset = resolveInternalFrameIndex(MF, FrameIndex, std::nullopt); if (!MF.getSubtarget().getHasDynamicFrames()) { WarnSize(Offset, MF, DL); @@ -115,8 +115,9 @@ bool SBFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, return false; } - int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) + - MI.getOperand(i + 1).getImm(); + int Offset = + resolveInternalFrameIndex(MF, FrameIndex, MI.getOperand(i + 1).getImm()); + if (!isInt<32>(Offset)) llvm_unreachable("bug in frame offset"); @@ -146,6 +147,22 @@ bool SBFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, return false; } +int SBFRegisterInfo::resolveInternalFrameIndex( + const llvm::MachineFunction &MF, int FI, std::optional Imm) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const SBFFunctionInfo *SBFFuncInfo = MF.getInfo(); + int Offset = MFI.getObjectOffset(FI); + if (MF.getSubtarget().getEnableNewCallConvention() && + SBFFuncInfo->containsFrameIndex(FI)) { + uint64_t StackSize = MFI.getStackSize(); + Offset = -static_cast(StackSize) - Offset; + } else if (Imm.has_value()) { + Offset += Imm.value(); + } + + return Offset; +} + Register SBFRegisterInfo::getFrameRegister(const MachineFunction &MF) const { return SBF::R10; } diff --git a/llvm/lib/Target/SBF/SBFRegisterInfo.h b/llvm/lib/Target/SBF/SBFRegisterInfo.h index a58586905b9fa..ee5b9f99c5fea 100644 --- a/llvm/lib/Target/SBF/SBFRegisterInfo.h +++ b/llvm/lib/Target/SBF/SBFRegisterInfo.h @@ -14,6 +14,7 @@ #define LLVM_LIB_TARGET_SBF_SBFREGISTERINFO_H #include "llvm/CodeGen/TargetRegisterInfo.h" +#include #define GET_REGINFO_HEADER #include "SBFGenRegisterInfo.inc" @@ -34,6 +35,9 @@ struct SBFRegisterInfo : public SBFGenRegisterInfo { RegScavenger *RS = nullptr) const override; Register getFrameRegister(const MachineFunction &MF) const override; + + int resolveInternalFrameIndex(const MachineFunction &MF, int FI, + std::optional Imm) const; }; } diff --git a/llvm/lib/Target/SBF/SBFSubtarget.cpp b/llvm/lib/Target/SBF/SBFSubtarget.cpp index 5f4c4593f32f2..e3474791ddc32 100644 --- a/llvm/lib/Target/SBF/SBFSubtarget.cpp +++ b/llvm/lib/Target/SBF/SBFSubtarget.cpp @@ -47,6 +47,7 @@ void SBFSubtarget::initializeEnvironment(const Triple &TT) { NoLddw = false; CallxRegSrc = false; HasPqrClass = false; + NewCallConvention = false; } void SBFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { diff --git a/llvm/lib/Target/SBF/SBFSubtarget.h b/llvm/lib/Target/SBF/SBFSubtarget.h index 935fde7ea2ffa..a21eca0f82da5 100644 --- a/llvm/lib/Target/SBF/SBFSubtarget.h +++ b/llvm/lib/Target/SBF/SBFSubtarget.h @@ -80,6 +80,9 @@ class SBFSubtarget : public SBFGenSubtargetInfo { // Whether we have the PQR instruction class bool HasPqrClass; + // Whether to use the new call convention in SBFv2 + bool NewCallConvention; + public: // This constructor initializes the data members to match that // of the specified triple. @@ -102,7 +105,9 @@ class SBFSubtarget : public SBFGenSubtargetInfo { bool getNoLddw() const { return NoLddw; } bool getCallXRegSrc() const { return CallxRegSrc; } bool getHasPqrClass() const { return HasPqrClass; } - + bool getEnableNewCallConvention() const { + return HasDynamicFrames && NewCallConvention; + } const SBFInstrInfo *getInstrInfo() const override { return &InstrInfo; } const SBFFrameLowering *getFrameLowering() const override { return &FrameLowering; diff --git a/llvm/lib/Target/SBF/SBFTargetFeatures.td b/llvm/lib/Target/SBF/SBFTargetFeatures.td index 2a6d1186836df..3644dbfdd0a1f 100644 --- a/llvm/lib/Target/SBF/SBFTargetFeatures.td +++ b/llvm/lib/Target/SBF/SBFTargetFeatures.td @@ -46,6 +46,9 @@ def FeatureCallxRegSrc : SubtargetFeature<"callx-reg-src", "CallxRegSrc", "true" def FeaturePqrInstr : SubtargetFeature<"pqr-instr", "HasPqrClass", "true", "Enable the PQR instruction class">; +def FeatureCallConv : SubtargetFeature<"new-call-conv", "NewCallConvention", "true", + "Enable new call convetion for SBFv2">; + class Proc Features> : Processor; @@ -55,4 +58,4 @@ def : Proc<"v2", []>; def : Proc<"v3", [ALU32]>; def : Proc<"sbfv2", [FeatureSolana, FeatureDynamicFrames, FeatureRelocAbs64, FeatureStaticSyscalls, FeatureDisableNeg, FeatureReverseSubImm, FeatureDisableLddw, FeatureCallxRegSrc, - FeaturePqrInstr]>; \ No newline at end of file + FeaturePqrInstr, FeatureCallConv]>; \ No newline at end of file diff --git a/llvm/lib/Target/SBF/SBFTargetMachine.cpp b/llvm/lib/Target/SBF/SBFTargetMachine.cpp index 3b338d74db486..f83954cefc0a1 100644 --- a/llvm/lib/Target/SBF/SBFTargetMachine.cpp +++ b/llvm/lib/Target/SBF/SBFTargetMachine.cpp @@ -10,9 +10,10 @@ // //===----------------------------------------------------------------------===// -#include "SBFTargetMachine.h" #include "SBF.h" +#include "SBFTargetMachine.h" #include "SBFTargetTransformInfo.h" +#include "SBFFunctionInfo.h" #include "MCTargetDesc/SBFMCAsmInfo.h" #include "TargetInfo/SBFTargetInfo.h" #include "llvm/CodeGen/Passes.h" @@ -134,6 +135,13 @@ SBFTargetMachine::getTargetTransformInfo(const Function &F) const { return TargetTransformInfo(SBFTTIImpl(this, F)); } +MachineFunctionInfo *SBFTargetMachine::createMachineFunctionInfo( + llvm::BumpPtrAllocator &Allocator, const llvm::Function &F, + const llvm::TargetSubtargetInfo *STI) const { + return SBFFunctionInfo::create( + Allocator, F, static_cast(STI)); +} + // Install an instruction selector pass using // the ISelDag to gen SBF code. bool SBFPassConfig::addInstSelector() { diff --git a/llvm/lib/Target/SBF/SBFTargetMachine.h b/llvm/lib/Target/SBF/SBFTargetMachine.h index cd03b3473b36a..20637687dfe9a 100644 --- a/llvm/lib/Target/SBF/SBFTargetMachine.h +++ b/llvm/lib/Target/SBF/SBFTargetMachine.h @@ -42,6 +42,10 @@ class SBFTargetMachine : public LLVMTargetMachine { } void registerPassBuilderCallbacks(PassBuilder &PB) override; + + MachineFunctionInfo * + createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, + const TargetSubtargetInfo *STI) const override; }; } diff --git a/llvm/test/CodeGen/SBF/many_args_new_conv.ll b/llvm/test/CodeGen/SBF/many_args_new_conv.ll new file mode 100644 index 0000000000000..a21a00d60613f --- /dev/null +++ b/llvm/test/CodeGen/SBF/many_args_new_conv.ll @@ -0,0 +1,115 @@ +; RUN: llc -O2 -march=sbf -mcpu=sbfv2 < %s | FileCheck %s + +; Function Attrs: nounwind uwtable +define i32 @caller_no_alloca(i32 %a, i32 %b, i32 %c) #0 { +entry: +; CHECK-LABEL: caller_no_alloca + +; No changes to the stack pointer +; CHECK-NOT: add64 r11 + +; Saving arguments on the stack +; CHECK: mov64 r4, 55 +; CHECK: stxdw [r10 - 32], r4 +; CHECK: mov64 r4, 60 +; CHECK: stxdw [r10 - 40], r4 +; CHECK: mov64 r4, 50 +; CHECK: stxdw [r10 - 24], r4 +; CHECK: mov64 r4, 4 +; CHECK: stxdw [r10 - 16], r4 +; CHECK: mov64 r4, 3 +; CHECK: stxdw [r10 - 8], r4 +; CHECK: mov64 r4, 1 +; CHECK: mov64 r5, 2 +; CHECK: call callee_alloca + + %call = tail call i32 @callee_alloca(i32 %a, i32 %b, i32 %c, i32 1, i32 2, i32 3, i32 4, i32 50, i32 55, i32 60) #3 + ret i32 %call +} + +; Function Attrs: nounwind uwtable +define i32 @caller_alloca(i32 %a, i32 %b, i32 %c) #0 { +; CHECK-LABEL: caller_alloca +; CHECK: add64 r11, -24 +; CHECK: ldxw r1, [r10 - 4] + +; Saving arguments in the stack +; CHECK: mov64 r4, 55 + +; Offset in the callee: (-56) - (-24) = -32 +; CHECK: stxdw [r10 - 56], r4 +; CHECK: mov64 r4, 60 +; Offset in the callee: (-64) - (-24) = -40 +; CHECK: stxdw [r10 - 64], r4 +; CHECK: mov64 r4, 50 +; Offset in the callee: (-48) - (-24) = -24 +; CHECK: stxdw [r10 - 48], r4 +; CHECK: mov64 r4, 4 +; Offset in the callee: (-40) - (-24) = -16 +; CHECK: stxdw [r10 - 40], r4 +; CHECK: mov64 r4, 3 +; Offset in the callee: (-32) - (-24) = -8 +; CHECK: stxdw [r10 - 32], r4 +; CHECK: mov64 r4, 1 +; CHECK: mov64 r5, 2 +; CHECK: call callee_no_alloca + +entry: + %g = alloca i32 + %g1 = load i32, ptr %g + %call = tail call i32 @callee_no_alloca(i32 %g1, i32 %b, i32 %c, i32 1, i32 2, i32 3, i32 4, i32 50, i32 55, i32 60) #3 + %h = alloca i128 + %h1 = load i32, ptr %h + %res = sub i32 %call, %h1 + ret i32 %res +} + +; Function Attrs: nounwind uwtable +define i32 @callee_alloca(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %p, i32 %y, i32 %a1, i32 %a2) #1 { +; CHECK-LABEL: callee_alloca +; Loading arguments +; CHECK: ldxdw r2, [r10 - 8] +; CHECK: ldxdw r2, [r10 - 16] +; CHECK: ldxdw r2, [r10 - 24] +; CHECK: ldxdw r2, [r10 - 32] +; CHECK: ldxdw r2, [r10 - 40] +; Loading allocated i32 +; CHECK: ldxw r0, [r10 - 44] + +entry: + %o = alloca i32 + %g = add i32 %a, %b + %h = sub i32 %g, %c + %i = add i32 %h, %d + %j = sub i32 %i, %e + %k = add i32 %j, %f + %l = add i32 %k, %p + %m = add i32 %l, %y + %n = add i32 %m, %a1 + %q = add i32 %n, %a2 + %r = load i32, ptr %o + %s = add i32 %r, %q + ret i32 %s +} + +; Function Attrs: nounwind uwtable +define i32 @callee_no_alloca(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %p, i32 %y, i32 %a1, i32 %a2) #1 { +; CHECK-LABEL: callee_no_alloca +; Loading arguments +; CHECK: ldxdw r1, [r10 - 8] +; CHECK: ldxdw r1, [r10 - 16] +; CHECK: ldxdw r1, [r10 - 24] +; CHECK: ldxdw r1, [r10 - 32] +; CHECK: ldxdw r1, [r10 - 40] +entry: + %g = add i32 %a, %b + %h = sub i32 %g, %c + %i = add i32 %h, %d + %j = sub i32 %i, %e + %k = add i32 %j, %f + %l = add i32 %k, %p + %m = add i32 %l, %y + %n = add i32 %m, %a1 + %q = add i32 %n, %a2 + ret i32 %q +} \ No newline at end of file diff --git a/llvm/test/CodeGen/SBF/stack_args_v2.ll b/llvm/test/CodeGen/SBF/stack_args_v2.ll index 4a13de3771ecc..942bc06756216 100644 --- a/llvm/test/CodeGen/SBF/stack_args_v2.ll +++ b/llvm/test/CodeGen/SBF/stack_args_v2.ll @@ -1,4 +1,4 @@ -; RUN: llc -O2 -march=sbf -mcpu=sbfv2 < %s | FileCheck %s +; RUN: llc -O2 -march=sbf -mattr=+dynamic-frames < %s | FileCheck %s ; Function Attrs: nounwind uwtable define i32 @foo(i32 %a, i32 %b, i32 %c) #0 {