Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SOL] Optimize call convention in SBFv2 #94

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/lib/Target/SBF/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_llvm_target(SBFCodeGen
SBFMIChecking.cpp
SBFMISimplifyPatchable.cpp
BTFDebug.cpp
SBFFunctionInfo.cpp

LINK_COMPONENTS
Analysis
Expand Down
28 changes: 28 additions & 0 deletions llvm/lib/Target/SBF/SBFFunctionInfo.cpp
Original file line number Diff line number Diff line change
@@ -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
32 changes: 32 additions & 0 deletions llvm/lib/Target/SBF/SBFFunctionInfo.h
Original file line number Diff line number Diff line change
@@ -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 <unordered_set>

namespace llvm {

class SBFFunctionInfo final : public MachineFunctionInfo {
std::unordered_set<int> frameIndexes;

public:
SBFFunctionInfo(const Function &F, const SBFSubtarget *STI){};

void storeFrameIndexArgument(int FI);
bool containsFrameIndex(int FI) const;
};
} // namespace llvm

#endif // LLVM_SBFFUNCTIONINFO_H
78 changes: 58 additions & 20 deletions llvm/lib/Target/SBF/SBFISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//

#include "SBFFunctionInfo.h"
#include "SBFRegisterInfo.h"
#include "SBFSubtarget.h"
#include "llvm/CodeGen/CallingConvLower.h"
Expand Down Expand Up @@ -413,8 +414,15 @@ SDValue SBFTargetLowering::LowerFormalArguments(
SmallVector<CCValAssign, 16> 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);
Expand Down Expand Up @@ -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<int64_t>(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");
Expand Down Expand Up @@ -524,8 +549,14 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVector<CCValAssign, 16> 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);
Expand Down Expand Up @@ -595,6 +626,7 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
Subtarget->getRegisterInfo()->getFrameRegister(MF),
getPointerTy(MF.getDataLayout()));

SBFFunctionInfo * SBFFuncInfo = MF.getInfo<SBFFunctionInfo>();
// 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
Expand All @@ -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<int64_t>(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<int64_t>(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 {
Expand Down
25 changes: 21 additions & 4 deletions llvm/lib/Target/SBF/SBFRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<SBFSubtarget>().getHasDynamicFrames()) {
WarnSize(Offset, MF, DL);
Expand All @@ -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");
Expand Down Expand Up @@ -146,6 +147,22 @@ bool SBFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
return false;
}

int SBFRegisterInfo::resolveInternalFrameIndex(
const llvm::MachineFunction &MF, int FI, std::optional<int64_t> Imm) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
const SBFFunctionInfo *SBFFuncInfo = MF.getInfo<SBFFunctionInfo>();
int Offset = MFI.getObjectOffset(FI);
if (MF.getSubtarget<SBFSubtarget>().getEnableNewCallConvention() &&
SBFFuncInfo->containsFrameIndex(FI)) {
uint64_t StackSize = MFI.getStackSize();
Offset = -static_cast<int>(StackSize) - Offset;
} else if (Imm.has_value()) {
Offset += Imm.value();
}

return Offset;
}

Register SBFRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
return SBF::R10;
}
4 changes: 4 additions & 0 deletions llvm/lib/Target/SBF/SBFRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define LLVM_LIB_TARGET_SBF_SBFREGISTERINFO_H

#include "llvm/CodeGen/TargetRegisterInfo.h"
#include <optional>

#define GET_REGINFO_HEADER
#include "SBFGenRegisterInfo.inc"
Expand All @@ -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<int64_t> Imm) const;
};
}

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/SBF/SBFSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/SBF/SBFSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/SBF/SBFTargetFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;

Expand All @@ -55,4 +58,4 @@ def : Proc<"v2", []>;
def : Proc<"v3", [ALU32]>;
def : Proc<"sbfv2", [FeatureSolana, FeatureDynamicFrames, FeatureRelocAbs64, FeatureStaticSyscalls,
FeatureDisableNeg, FeatureReverseSubImm, FeatureDisableLddw, FeatureCallxRegSrc,
FeaturePqrInstr]>;
FeaturePqrInstr, FeatureCallConv]>;
10 changes: 9 additions & 1 deletion llvm/lib/Target/SBF/SBFTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<SBFFunctionInfo>(
Allocator, F, static_cast<const SBFSubtarget *>(STI));
}

// Install an instruction selector pass using
// the ISelDag to gen SBF code.
bool SBFPassConfig::addInstSelector() {
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/SBF/SBFTargetMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
}

Expand Down
Loading
Loading