Skip to content

[RISCV][GISEL] Add support for scalable vector types in lowerReturnVal #71587

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

Merged
merged 2 commits into from
Nov 15, 2023
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
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ bool IRTranslator::translateCompare(const User &U,
bool IRTranslator::translateRet(const User &U, MachineIRBuilder &MIRBuilder) {
const ReturnInst &RI = cast<ReturnInst>(U);
const Value *Ret = RI.getReturnValue();
if (Ret && DL->getTypeStoreSize(Ret->getType()) == 0)
if (Ret && DL->getTypeStoreSize(Ret->getType()).isZero())
Ret = nullptr;

ArrayRef<Register> VRegs;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,9 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
if (SrcReg.isVirtual() && DstReg.isPhysical() && SrcSize.isScalable() &&
!DstSize.isScalable())
break;
if (SrcReg.isVirtual() && DstReg.isPhysical() && SrcSize.isScalable() &&
!DstSize.isScalable())
break;

if (SrcSize.isNonZero() && DstSize.isNonZero() && SrcSize != DstSize) {
if (!DstOp.getSubReg() && !SrcOp.getSubReg()) {
Expand Down
12 changes: 10 additions & 2 deletions llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,10 @@ static bool isSupportedArgumentType(Type *T, const RISCVSubtarget &Subtarget,
}

// TODO: Only integer, pointer and aggregate types are supported now.
static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget) {
// TODO: Remove IsLowerRetVal argument by adding support for vectors in
// lowerCall.
static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget,
bool IsLowerRetVal = false) {
// TODO: Integers larger than 2*XLen are passed indirectly which is not
// supported yet.
if (T->isIntegerTy())
Expand All @@ -368,6 +371,11 @@ static bool isSupportedReturnType(Type *T, const RISCVSubtarget &Subtarget) {
return true;
}

if (IsLowerRetVal && T->isVectorTy() && Subtarget.hasVInstructions() &&
T->isScalableTy() &&
isLegalElementTypeForRVV(T->getScalarType(), Subtarget))
return true;

return false;
}

Expand All @@ -380,7 +388,7 @@ bool RISCVCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,

const RISCVSubtarget &Subtarget =
MIRBuilder.getMF().getSubtarget<RISCVSubtarget>();
if (!isSupportedReturnType(Val->getType(), Subtarget))
if (!isSupportedReturnType(Val->getType(), Subtarget, /*IsLowerRetVal=*/true))
return false;

MachineFunction &MF = MIRBuilder.getMF();
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19638,12 +19638,15 @@ unsigned RISCVTargetLowering::getCustomCtpopCost(EVT VT,
}

bool RISCVTargetLowering::fallBackToDAGISel(const Instruction &Inst) const {
// We don't support scalable vectors in GISel.
// At the moment, the only scalable instruction GISel knows how to lower is
// ret with scalable argument.

if (Inst.getType()->isScalableTy())
return true;

for (unsigned i = 0; i < Inst.getNumOperands(); ++i)
if (Inst.getOperand(i)->getType()->isScalableTy())
if (Inst.getOperand(i)->getType()->isScalableTy() &&
!isa<ReturnInst>(&Inst))
return true;

if (const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
; RUN: not --crash llc -mtriple=riscv32 -mattr=+v -global-isel -stop-after=irtranslator \
; RUN: -verify-machineinstrs < %s 2>&1 | FileCheck %s
; RUN: not --crash llc -mtriple=riscv64 -mattr=+v -global-isel -stop-after=irtranslator \
; RUN: -verify-machineinstrs < %s 2>&1 | FileCheck %s

; The purpose of this test is to show that the compiler throws an error when
; there is no support for bf16 vectors. If the compiler did not throw an error,
; then it will try to scalarize the argument to an s32, which may drop elements.
define <vscale x 1 x bfloat> @test_ret_nxv1bf16() {
entry:
ret <vscale x 1 x bfloat> undef
}

; CHECK: LLVM ERROR: unable to translate instruction: ret (in function: test_ret_nxv1bf16)
14 changes: 14 additions & 0 deletions llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/vec-ret-f16-err.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
; RUN: not --crash llc -mtriple=riscv32 -mattr=+v -global-isel -stop-after=irtranslator \
; RUN: -verify-machineinstrs < %s 2>&1 | FileCheck %s
; RUN: not --crash llc -mtriple=riscv64 -mattr=+v -global-isel -stop-after=irtranslator \
; RUN: -verify-machineinstrs < %s 2>&1 | FileCheck %s

; The purpose of this test is to show that the compiler throws an error when
; there is no support for f16 vectors. If the compiler did not throw an error,
; then it will try to scalarize the argument to an s32, which may drop elements.
define <vscale x 1 x half> @test_ret_nxv1f16() {
entry:
ret <vscale x 1 x half> undef
}

; CHECK: LLVM ERROR: unable to translate instruction: ret (in function: test_ret_nxv1f16)
Loading