[RISCV] Support passing scalable vectur values through the stack.

After consuming all vector registers, the scalable vector values will be
passed indirectly. The pointer values will be saved in general
registers. If all general registers are used up, we will report an error to
notify users the compiler does not support passing scalable vector
values through the stack. In this patch, we remove the restriction. After
all general registers are used up, we use the stack to save the
pointers which point to the indirect passed scalable vector values.

Differential Revision: https://reviews.llvm.org/D116310
This commit is contained in:
Hsiangkai Wang 2021-12-27 22:35:27 +08:00
parent 049cd480a0
commit a1c7ddf926
3 changed files with 64 additions and 13 deletions

View File

@ -8393,7 +8393,8 @@ static bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
LocVT = XLenVT;
LocInfo = CCValAssign::Indirect;
} else if (ValVT.isScalableVector()) {
report_fatal_error("Unable to pass scalable vector types on the stack");
LocVT = XLenVT;
LocInfo = CCValAssign::Indirect;
} else {
// Pass fixed-length vectors on the stack.
LocVT = ValVT;
@ -8592,6 +8593,12 @@ static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
EVT LocVT = VA.getLocVT();
EVT ValVT = VA.getValVT();
EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0));
if (ValVT.isScalableVector()) {
// When the value is a scalable vector, we save the pointer which points to
// the scalable vector value in the stack. The ValVT will be the pointer
// type, instead of the scalable vector type.
ValVT = LocVT;
}
int FI = MFI.CreateFixedObject(ValVT.getStoreSize(), VA.getLocMemOffset(),
/*Immutable=*/true);
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);

View File

@ -0,0 +1,56 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -mattr=+experimental-v < %s 2>&1 | FileCheck %s
define <vscale x 16 x i32> @bar(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, <vscale x 16 x i32> %w, <vscale x 16 x i32> %x, <vscale x 16 x i32> %y, <vscale x 16 x i32> %z) {
; CHECK-LABEL: bar:
; CHECK: # %bb.0:
; CHECK-NEXT: ld a0, 0(sp)
; CHECK-NEXT: ld a1, 8(sp)
; CHECK-NEXT: vl8re32.v v24, (a0)
; CHECK-NEXT: vl8re32.v v0, (a1)
; CHECK-NEXT: vsetvli a0, zero, e32, m8, ta, mu
; CHECK-NEXT: vadd.vv v8, v8, v24
; CHECK-NEXT: vadd.vv v16, v16, v0
; CHECK-NEXT: vadd.vv v8, v8, v16
; CHECK-NEXT: ret
%s0 = add <vscale x 16 x i32> %w, %y
%s1 = add <vscale x 16 x i32> %x, %z
%s = add <vscale x 16 x i32> %s0, %s1
ret <vscale x 16 x i32> %s
}
define <vscale x 16 x i32> @foo(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, <vscale x 16 x i32> %x) {
; CHECK-LABEL: foo:
; CHECK: # %bb.0:
; CHECK-NEXT: addi sp, sp, -48
; CHECK-NEXT: .cfi_def_cfa_offset 48
; CHECK-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; CHECK-NEXT: .cfi_offset ra, -8
; CHECK-NEXT: csrr t0, vlenb
; CHECK-NEXT: slli t0, t0, 4
; CHECK-NEXT: sub sp, sp, t0
; CHECK-NEXT: addi t0, sp, 40
; CHECK-NEXT: sd t0, 8(sp)
; CHECK-NEXT: csrr t0, vlenb
; CHECK-NEXT: slli t0, t0, 3
; CHECK-NEXT: add t0, sp, t0
; CHECK-NEXT: addi t0, t0, 40
; CHECK-NEXT: sd t0, 0(sp)
; CHECK-NEXT: addi t0, sp, 40
; CHECK-NEXT: vs8r.v v8, (t0)
; CHECK-NEXT: csrr t0, vlenb
; CHECK-NEXT: slli t0, t0, 3
; CHECK-NEXT: add t0, sp, t0
; CHECK-NEXT: addi t0, t0, 40
; CHECK-NEXT: vs8r.v v8, (t0)
; CHECK-NEXT: vmv8r.v v16, v8
; CHECK-NEXT: call bar@plt
; CHECK-NEXT: csrr a0, vlenb
; CHECK-NEXT: slli a0, a0, 4
; CHECK-NEXT: add sp, sp, a0
; CHECK-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; CHECK-NEXT: addi sp, sp, 48
; CHECK-NEXT: ret
%ret = call <vscale x 16 x i32> @bar(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, <vscale x 16 x i32> %x, <vscale x 16 x i32> %x, <vscale x 16 x i32> %x, <vscale x 16 x i32> %x)
ret <vscale x 16 x i32> %ret
}

View File

@ -1,12 +0,0 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: not --crash llc -mtriple=riscv64 -mattr=+experimental-v < %s 2>&1 | FileCheck %s
; A rather pathological test case in which we exhaust all vector registers and
; all scalar registers, forcing %z to go through the stack. This is not yet
; supported, so check that a reasonable error message is produced rather than
; hitting an assertion or producing incorrect code.
; CHECK: LLVM ERROR: Unable to pass scalable vector types on the stack
define <vscale x 16 x i32> @bar(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, <vscale x 16 x i32> %x, <vscale x 16 x i32> %y, <vscale x 16 x i32> %z) {
%s = add <vscale x 16 x i32> %x, %z
ret <vscale x 16 x i32> %s
}