Skip to content

Commit

Permalink
Optmize call convention in SBFv2
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasSte committed Mar 25, 2024
1 parent b51296e commit 52a91c7
Show file tree
Hide file tree
Showing 13 changed files with 284 additions and 28 deletions.
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

0 comments on commit 52a91c7

Please sign in to comment.