This patch try to get rid of vsetvl implict vl/vtype def-use chain and improve the register allocation quality by moving the vsetvl insertion pass after RVV register allocation It will gain the benefit for the following optimization from 1. unblock scheduler's constraints by removing vl/vtype def-use chain 2. Support RVV re-materialization 3. Support partial spill This patch add a new option `-riscv-vsetvl-after-rvv-regalloc=<1|0>` to control this feature and default set as disable.
313 lines
8.4 KiB
LLVM
313 lines
8.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+v \
|
|
; RUN: -verify-machineinstrs | FileCheck %s
|
|
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+v \
|
|
; RUN: -verify-machineinstrs | FileCheck %s
|
|
|
|
declare iXLen @llvm.riscv.vfirst.iXLen.nxv1i1(
|
|
<vscale x 1 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_m_nxv1i1(<vscale x 1 x i1> %0, iXLen %1) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_m_nxv1i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.iXLen.nxv1i1(
|
|
<vscale x 1 x i1> %0,
|
|
iXLen %1)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
define iXLen @intrinsic_vfirst_m_nxv1i1_zero(<vscale x 1 x i1> %0) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_m_nxv1i1_zero:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: li a0, -1
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.iXLen.nxv1i1(
|
|
<vscale x 1 x i1> %0,
|
|
iXLen 0)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.mask.iXLen.nxv1i1(
|
|
<vscale x 1 x i1>,
|
|
<vscale x 1 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_mask_m_nxv1i1(<vscale x 1 x i1> %0, <vscale x 1 x i1> %1, iXLen %2) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_mask_m_nxv1i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vmv1r.v v9, v0
|
|
; CHECK-NEXT: vmv1r.v v0, v8
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v9, v0.t
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.mask.iXLen.nxv1i1(
|
|
<vscale x 1 x i1> %0,
|
|
<vscale x 1 x i1> %1,
|
|
iXLen %2)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
define iXLen @intrinsic_vfirst_mask_m_nxv1i1_zero(<vscale x 1 x i1> %0, <vscale x 1 x i1> %1) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_mask_m_nxv1i1_zero:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: li a0, -1
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.mask.iXLen.nxv1i1(
|
|
<vscale x 1 x i1> %0,
|
|
<vscale x 1 x i1> %1,
|
|
iXLen 0)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.iXLen.nxv2i1(
|
|
<vscale x 2 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_m_nxv2i1(<vscale x 2 x i1> %0, iXLen %1) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_m_nxv2i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, mf4, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.iXLen.nxv2i1(
|
|
<vscale x 2 x i1> %0,
|
|
iXLen %1)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.mask.iXLen.nxv2i1(
|
|
<vscale x 2 x i1>,
|
|
<vscale x 2 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_mask_m_nxv2i1(<vscale x 2 x i1> %0, <vscale x 2 x i1> %1, iXLen %2) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_mask_m_nxv2i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vmv1r.v v9, v0
|
|
; CHECK-NEXT: vmv1r.v v0, v8
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, mf4, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v9, v0.t
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.mask.iXLen.nxv2i1(
|
|
<vscale x 2 x i1> %0,
|
|
<vscale x 2 x i1> %1,
|
|
iXLen %2)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.iXLen.nxv4i1(
|
|
<vscale x 4 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_m_nxv4i1(<vscale x 4 x i1> %0, iXLen %1) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_m_nxv4i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, mf2, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.iXLen.nxv4i1(
|
|
<vscale x 4 x i1> %0,
|
|
iXLen %1)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.mask.iXLen.nxv4i1(
|
|
<vscale x 4 x i1>,
|
|
<vscale x 4 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_mask_m_nxv4i1(<vscale x 4 x i1> %0, <vscale x 4 x i1> %1, iXLen %2) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_mask_m_nxv4i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vmv1r.v v9, v0
|
|
; CHECK-NEXT: vmv1r.v v0, v8
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, mf2, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v9, v0.t
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.mask.iXLen.nxv4i1(
|
|
<vscale x 4 x i1> %0,
|
|
<vscale x 4 x i1> %1,
|
|
iXLen %2)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.iXLen.nxv8i1(
|
|
<vscale x 8 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_m_nxv8i1(<vscale x 8 x i1> %0, iXLen %1) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_m_nxv8i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, m1, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.iXLen.nxv8i1(
|
|
<vscale x 8 x i1> %0,
|
|
iXLen %1)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.mask.iXLen.nxv8i1(
|
|
<vscale x 8 x i1>,
|
|
<vscale x 8 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_mask_m_nxv8i1(<vscale x 8 x i1> %0, <vscale x 8 x i1> %1, iXLen %2) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_mask_m_nxv8i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vmv1r.v v9, v0
|
|
; CHECK-NEXT: vmv1r.v v0, v8
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, m1, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v9, v0.t
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.mask.iXLen.nxv8i1(
|
|
<vscale x 8 x i1> %0,
|
|
<vscale x 8 x i1> %1,
|
|
iXLen %2)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.iXLen.nxv16i1(
|
|
<vscale x 16 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_m_nxv16i1(<vscale x 16 x i1> %0, iXLen %1) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_m_nxv16i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, m2, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.iXLen.nxv16i1(
|
|
<vscale x 16 x i1> %0,
|
|
iXLen %1)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.mask.iXLen.nxv16i1(
|
|
<vscale x 16 x i1>,
|
|
<vscale x 16 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_mask_m_nxv16i1(<vscale x 16 x i1> %0, <vscale x 16 x i1> %1, iXLen %2) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_mask_m_nxv16i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vmv1r.v v9, v0
|
|
; CHECK-NEXT: vmv1r.v v0, v8
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, m2, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v9, v0.t
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.mask.iXLen.nxv16i1(
|
|
<vscale x 16 x i1> %0,
|
|
<vscale x 16 x i1> %1,
|
|
iXLen %2)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.iXLen.nxv32i1(
|
|
<vscale x 32 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_m_nxv32i1(<vscale x 32 x i1> %0, iXLen %1) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_m_nxv32i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, m4, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.iXLen.nxv32i1(
|
|
<vscale x 32 x i1> %0,
|
|
iXLen %1)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.mask.iXLen.nxv32i1(
|
|
<vscale x 32 x i1>,
|
|
<vscale x 32 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_mask_m_nxv32i1(<vscale x 32 x i1> %0, <vscale x 32 x i1> %1, iXLen %2) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_mask_m_nxv32i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vmv1r.v v9, v0
|
|
; CHECK-NEXT: vmv1r.v v0, v8
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, m4, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v9, v0.t
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.mask.iXLen.nxv32i1(
|
|
<vscale x 32 x i1> %0,
|
|
<vscale x 32 x i1> %1,
|
|
iXLen %2)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.iXLen.nxv64i1(
|
|
<vscale x 64 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_m_nxv64i1(<vscale x 64 x i1> %0, iXLen %1) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_m_nxv64i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, m8, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.iXLen.nxv64i1(
|
|
<vscale x 64 x i1> %0,
|
|
iXLen %1)
|
|
|
|
ret iXLen %a
|
|
}
|
|
|
|
declare iXLen @llvm.riscv.vfirst.mask.iXLen.nxv64i1(
|
|
<vscale x 64 x i1>,
|
|
<vscale x 64 x i1>,
|
|
iXLen);
|
|
|
|
define iXLen @intrinsic_vfirst_mask_m_nxv64i1(<vscale x 64 x i1> %0, <vscale x 64 x i1> %1, iXLen %2) nounwind {
|
|
; CHECK-LABEL: intrinsic_vfirst_mask_m_nxv64i1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: vmv1r.v v9, v0
|
|
; CHECK-NEXT: vmv1r.v v0, v8
|
|
; CHECK-NEXT: vsetvli zero, a0, e8, m8, ta, ma
|
|
; CHECK-NEXT: vfirst.m a0, v9, v0.t
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a = call iXLen @llvm.riscv.vfirst.mask.iXLen.nxv64i1(
|
|
<vscale x 64 x i1> %0,
|
|
<vscale x 64 x i1> %1,
|
|
iXLen %2)
|
|
|
|
ret iXLen %a
|
|
}
|