Skip to content

Commit

Permalink
Recommit [RISCV] RISCV vector calling convention (2/2) (#79096) (#87736)
Browse files Browse the repository at this point in the history
Bug fix: Handle RVV return type in calling convention correctly.
Return values are handled in a same way as function arguments.
One thing to mention is that if a type can be broken down into
homogeneous
vector types, e.g. {<vscale x 4 x i32>, {<vscale x 4 x i32>, <vscale x 4
x i32>}},
it is considered as a vector tuple type and need to be handled by tuple
type rule.
  • Loading branch information
4vtomat authored Apr 16, 2024
1 parent 75244a1 commit 91dd844
Show file tree
Hide file tree
Showing 7 changed files with 515 additions and 85 deletions.
12 changes: 10 additions & 2 deletions llvm/lib/CodeGen/TargetLoweringBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1809,8 +1809,16 @@ void llvm::GetReturnInfo(CallingConv::ID CC, Type *ReturnType,
else if (attr.hasRetAttr(Attribute::ZExt))
Flags.setZExt();

for (unsigned i = 0; i < NumParts; ++i)
Outs.push_back(ISD::OutputArg(Flags, PartVT, VT, /*isfixed=*/true, 0, 0));
for (unsigned i = 0; i < NumParts; ++i) {
ISD::ArgFlagsTy OutFlags = Flags;
if (NumParts > 1 && i == 0)
OutFlags.setSplit();
else if (i == NumParts - 1 && i != 0)
OutFlags.setSplitEnd();

Outs.push_back(
ISD::OutputArg(OutFlags, PartVT, VT, /*isfixed=*/true, 0, 0));
}
}
}

Expand Down
57 changes: 29 additions & 28 deletions llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ struct RISCVOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {
// Whether this is assigning args for a return.
bool IsRet;

// true if assignArg has been called for a mask argument, false otherwise.
bool AssignedFirstMaskArg = false;
RVVArgDispatcher &RVVDispatcher;

public:
RISCVOutgoingValueAssigner(
RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet,
RVVArgDispatcher &RVVDispatcher)
: CallLowering::OutgoingValueAssigner(nullptr),
RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}
RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet),
RVVDispatcher(RVVDispatcher) {}

bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
Expand All @@ -51,16 +52,9 @@ struct RISCVOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {
const DataLayout &DL = MF.getDataLayout();
const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();

std::optional<unsigned> FirstMaskArgument;
if (Subtarget.hasVInstructions() && !AssignedFirstMaskArg &&
ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1) {
FirstMaskArgument = ValNo;
AssignedFirstMaskArg = true;
}

if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
LocInfo, Flags, State, Info.IsFixed, IsRet, Info.Ty,
*Subtarget.getTargetLowering(), FirstMaskArgument))
*Subtarget.getTargetLowering(), RVVDispatcher))
return true;

StackSize = State.getStackSize();
Expand Down Expand Up @@ -181,14 +175,15 @@ struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
// Whether this is assigning args from a return.
bool IsRet;

// true if assignArg has been called for a mask argument, false otherwise.
bool AssignedFirstMaskArg = false;
RVVArgDispatcher &RVVDispatcher;

public:
RISCVIncomingValueAssigner(
RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet,
RVVArgDispatcher &RVVDispatcher)
: CallLowering::IncomingValueAssigner(nullptr),
RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}
RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet),
RVVDispatcher(RVVDispatcher) {}

bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
Expand All @@ -201,16 +196,9 @@ struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
if (LocVT.isScalableVector())
MF.getInfo<RISCVMachineFunctionInfo>()->setIsVectorCall();

std::optional<unsigned> FirstMaskArgument;
if (Subtarget.hasVInstructions() && !AssignedFirstMaskArg &&
ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1) {
FirstMaskArgument = ValNo;
AssignedFirstMaskArg = true;
}

if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
LocInfo, Flags, State, /*IsFixed=*/true, IsRet, Info.Ty,
*Subtarget.getTargetLowering(), FirstMaskArgument))
*Subtarget.getTargetLowering(), RVVDispatcher))
return true;

StackSize = State.getStackSize();
Expand Down Expand Up @@ -420,9 +408,11 @@ bool RISCVCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
SmallVector<ArgInfo, 4> SplitRetInfos;
splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC);

RVVArgDispatcher Dispatcher{&MF, getTLI<RISCVTargetLowering>(),
ArrayRef(F.getReturnType())};
RISCVOutgoingValueAssigner Assigner(
CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
/*IsRet=*/true);
/*IsRet=*/true, Dispatcher);
RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret);
return determineAndHandleAssignments(Handler, Assigner, SplitRetInfos,
MIRBuilder, CC, F.isVarArg());
Expand Down Expand Up @@ -531,6 +521,7 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
CallingConv::ID CC = F.getCallingConv();

SmallVector<ArgInfo, 32> SplitArgInfos;
SmallVector<Type *, 4> TypeList;
unsigned Index = 0;
for (auto &Arg : F.args()) {
// Construct the ArgInfo object from destination register and argument type.
Expand All @@ -542,12 +533,16 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
// correspondingly and appended to SplitArgInfos.
splitToValueTypes(AInfo, SplitArgInfos, DL, CC);

TypeList.push_back(Arg.getType());

++Index;
}

RVVArgDispatcher Dispatcher{&MF, getTLI<RISCVTargetLowering>(),
ArrayRef(TypeList)};
RISCVIncomingValueAssigner Assigner(
CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
/*IsRet=*/false);
/*IsRet=*/false, Dispatcher);
RISCVFormalArgHandler Handler(MIRBuilder, MF.getRegInfo());

SmallVector<CCValAssign, 16> ArgLocs;
Expand Down Expand Up @@ -585,11 +580,13 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,

SmallVector<ArgInfo, 32> SplitArgInfos;
SmallVector<ISD::OutputArg, 8> Outs;
SmallVector<Type *, 4> TypeList;
for (auto &AInfo : Info.OrigArgs) {
// Handle any required unmerging of split value types from a given VReg into
// physical registers. ArgInfo objects are constructed correspondingly and
// appended to SplitArgInfos.
splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
TypeList.push_back(AInfo.Ty);
}

// TODO: Support tail calls.
Expand All @@ -607,9 +604,11 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));

RVVArgDispatcher ArgDispatcher{&MF, getTLI<RISCVTargetLowering>(),
ArrayRef(TypeList)};
RISCVOutgoingValueAssigner ArgAssigner(
CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
/*IsRet=*/false);
/*IsRet=*/false, ArgDispatcher);
RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call);
if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos,
MIRBuilder, CC, Info.IsVarArg))
Expand Down Expand Up @@ -637,9 +636,11 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
SmallVector<ArgInfo, 4> SplitRetInfos;
splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC);

RVVArgDispatcher RetDispatcher{&MF, getTLI<RISCVTargetLowering>(),
ArrayRef(F.getReturnType())};
RISCVIncomingValueAssigner RetAssigner(
CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
/*IsRet=*/true);
/*IsRet=*/true, RetDispatcher);
RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call);
if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos,
MIRBuilder, CC, Info.IsVarArg))
Expand Down
Loading

0 comments on commit 91dd844

Please sign in to comment.