This mechanism causes the greedy register allocator to prefer allocating register classes with higher priority first. This helps to ensure that high LMUL registers obtain a register without having to go through the eviction mechanism. In practice, it seems to cause a bunch of code churn, and some minor improvement around widening and narrowing operations. In a few of the widening tests, we have what look like code size regressions because we end up with two smaller register class copies instead of one larger one after the instruction. However, in any larger code sequence, these are likely to be folded into the producing instructions. (But so were the wider copies after the operation.) Two observations: 1) We're not setting the greedy-regclass-priority-trumps-globalness flag on the register class, so this doesn't help long mask ranges. I thought about doing that, but the benefit is non-obvious, so I decided it was worth a separate change at minimum. 2) We could arguably set the priority higher for the register classes that exclude v0. I tried that, and it caused a whole bunch of further churn. I may return to it in a separate patch.
111 lines
4.4 KiB
LLVM
111 lines
4.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=riscv32 -mattr=+v,+f,+d -target-abi=ilp32d \
|
|
; RUN: -verify-machineinstrs < %s | FileCheck %s
|
|
; RUN: llc -mtriple=riscv64 -mattr=+v,+f,+d -target-abi=lp64d \
|
|
; RUN: -verify-machineinstrs < %s | FileCheck %s
|
|
|
|
define <vscale x 1 x i64> @llrint_nxv1i64_nxv1f32(<vscale x 1 x float> %x) {
|
|
; CHECK-LABEL: llrint_nxv1i64_nxv1f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma
|
|
; CHECK-NEXT: vfwcvt.x.f.v v9, v8
|
|
; CHECK-NEXT: vmv1r.v v8, v9
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 1 x i64> @llvm.llrint.nxv1i64.nxv1f32(<vscale x 1 x float> %x)
|
|
ret <vscale x 1 x i64> %a
|
|
}
|
|
declare <vscale x 1 x i64> @llvm.llrint.nxv1i64.nxv1f32(<vscale x 1 x float>)
|
|
|
|
define <vscale x 2 x i64> @llrint_nxv2i64_nxv2f32(<vscale x 2 x float> %x) {
|
|
; CHECK-LABEL: llrint_nxv2i64_nxv2f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma
|
|
; CHECK-NEXT: vmv1r.v v10, v8
|
|
; CHECK-NEXT: vfwcvt.x.f.v v8, v10
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 2 x i64> @llvm.llrint.nxv2i64.nxv2f32(<vscale x 2 x float> %x)
|
|
ret <vscale x 2 x i64> %a
|
|
}
|
|
declare <vscale x 2 x i64> @llvm.llrint.nxv2i64.nxv2f32(<vscale x 2 x float>)
|
|
|
|
define <vscale x 4 x i64> @llrint_nxv4i64_nxv4f32(<vscale x 4 x float> %x) {
|
|
; CHECK-LABEL: llrint_nxv4i64_nxv4f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
|
|
; CHECK-NEXT: vmv2r.v v12, v8
|
|
; CHECK-NEXT: vfwcvt.x.f.v v8, v12
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 4 x i64> @llvm.llrint.nxv4i64.nxv4f32(<vscale x 4 x float> %x)
|
|
ret <vscale x 4 x i64> %a
|
|
}
|
|
declare <vscale x 4 x i64> @llvm.llrint.nxv4i64.nxv4f32(<vscale x 4 x float>)
|
|
|
|
define <vscale x 8 x i64> @llrint_nxv8i64_nxv8f32(<vscale x 8 x float> %x) {
|
|
; CHECK-LABEL: llrint_nxv8i64_nxv8f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma
|
|
; CHECK-NEXT: vmv4r.v v16, v8
|
|
; CHECK-NEXT: vfwcvt.x.f.v v8, v16
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 8 x i64> @llvm.llrint.nxv8i64.nxv8f32(<vscale x 8 x float> %x)
|
|
ret <vscale x 8 x i64> %a
|
|
}
|
|
declare <vscale x 8 x i64> @llvm.llrint.nxv8i64.nxv8f32(<vscale x 8 x float>)
|
|
|
|
define <vscale x 16 x i64> @llrint_nxv16i64_nxv16f32(<vscale x 16 x float> %x) {
|
|
; CHECK-LABEL: llrint_nxv16i64_nxv16f32:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma
|
|
; CHECK-NEXT: vfwcvt.x.f.v v24, v8
|
|
; CHECK-NEXT: vfwcvt.x.f.v v16, v12
|
|
; CHECK-NEXT: vmv8r.v v8, v24
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 16 x i64> @llvm.llrint.nxv16i64.nxv16f32(<vscale x 16 x float> %x)
|
|
ret <vscale x 16 x i64> %a
|
|
}
|
|
declare <vscale x 16 x i64> @llvm.llrint.nxv16i64.nxv16f32(<vscale x 16 x float>)
|
|
|
|
define <vscale x 1 x i64> @llrint_nxv1i64_nxv1f64(<vscale x 1 x double> %x) {
|
|
; CHECK-LABEL: llrint_nxv1i64_nxv1f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma
|
|
; CHECK-NEXT: vfcvt.x.f.v v8, v8
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 1 x i64> @llvm.llrint.nxv1i64.nxv1f64(<vscale x 1 x double> %x)
|
|
ret <vscale x 1 x i64> %a
|
|
}
|
|
declare <vscale x 1 x i64> @llvm.llrint.nxv1i64.nxv1f64(<vscale x 1 x double>)
|
|
|
|
define <vscale x 2 x i64> @llrint_nxv2i64_nxv2f64(<vscale x 2 x double> %x) {
|
|
; CHECK-LABEL: llrint_nxv2i64_nxv2f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma
|
|
; CHECK-NEXT: vfcvt.x.f.v v8, v8
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 2 x i64> @llvm.llrint.nxv2i64.nxv2f64(<vscale x 2 x double> %x)
|
|
ret <vscale x 2 x i64> %a
|
|
}
|
|
declare <vscale x 2 x i64> @llvm.llrint.nxv2i64.nxv2f64(<vscale x 2 x double>)
|
|
|
|
define <vscale x 4 x i64> @llrint_nxv4i64_nxv4f64(<vscale x 4 x double> %x) {
|
|
; CHECK-LABEL: llrint_nxv4i64_nxv4f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma
|
|
; CHECK-NEXT: vfcvt.x.f.v v8, v8
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 4 x i64> @llvm.llrint.nxv4i64.nxv4f64(<vscale x 4 x double> %x)
|
|
ret <vscale x 4 x i64> %a
|
|
}
|
|
declare <vscale x 4 x i64> @llvm.llrint.nxv4i64.nxv4f64(<vscale x 4 x double>)
|
|
|
|
define <vscale x 8 x i64> @llrint_nxv8i64_nxv8f64(<vscale x 8 x double> %x) {
|
|
; CHECK-LABEL: llrint_nxv8i64_nxv8f64:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma
|
|
; CHECK-NEXT: vfcvt.x.f.v v8, v8
|
|
; CHECK-NEXT: ret
|
|
%a = call <vscale x 8 x i64> @llvm.llrint.nxv8i64.nxv8f64(<vscale x 8 x double> %x)
|
|
ret <vscale x 8 x i64> %a
|
|
}
|
|
declare <vscale x 8 x i64> @llvm.llrint.nxv8i64.nxv8f64(<vscale x 8 x double>)
|