GlobalISel was previously inefficient in handling bitreverses of vector types. This deals with i16, i32, i64 vector types and converts them into i8 bitreverses and rev instructions.
285 lines
7.6 KiB
LLVM
285 lines
7.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s --check-prefixes=CHECK,SDAG
|
|
; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=1 %s -o - | FileCheck %s --check-prefixes=CHECK,GISEL
|
|
|
|
; These tests just check that the plumbing is in place for @llvm.bitreverse.
|
|
|
|
declare <2 x i16> @llvm.bitreverse.v2i16(<2 x i16>) readnone
|
|
|
|
define <2 x i16> @f(<2 x i16> %a) {
|
|
; SDAG-LABEL: f:
|
|
; SDAG: // %bb.0:
|
|
; SDAG-NEXT: rev32 v0.8b, v0.8b
|
|
; SDAG-NEXT: rbit v0.8b, v0.8b
|
|
; SDAG-NEXT: ushr v0.2s, v0.2s, #16
|
|
; SDAG-NEXT: ret
|
|
;
|
|
; GISEL-LABEL: f:
|
|
; GISEL: // %bb.0:
|
|
; GISEL-NEXT: uzp1 v0.4h, v0.4h, v0.4h
|
|
; GISEL-NEXT: rev16 v0.8b, v0.8b
|
|
; GISEL-NEXT: rbit v0.8b, v0.8b
|
|
; GISEL-NEXT: ushll v0.4s, v0.4h, #0
|
|
; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0
|
|
; GISEL-NEXT: ret
|
|
%b = call <2 x i16> @llvm.bitreverse.v2i16(<2 x i16> %a)
|
|
ret <2 x i16> %b
|
|
}
|
|
|
|
declare i8 @llvm.bitreverse.i8(i8) readnone
|
|
|
|
define i8 @g(i8 %a) {
|
|
; CHECK-LABEL: g:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit w8, w0
|
|
; CHECK-NEXT: lsr w0, w8, #24
|
|
; CHECK-NEXT: ret
|
|
%b = call i8 @llvm.bitreverse.i8(i8 %a)
|
|
ret i8 %b
|
|
}
|
|
|
|
declare i16 @llvm.bitreverse.i16(i16) readnone
|
|
|
|
define i16 @g_16(i16 %a) {
|
|
; CHECK-LABEL: g_16:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit w8, w0
|
|
; CHECK-NEXT: lsr w0, w8, #16
|
|
; CHECK-NEXT: ret
|
|
%b = call i16 @llvm.bitreverse.i16(i16 %a)
|
|
ret i16 %b
|
|
}
|
|
|
|
declare i32 @llvm.bitreverse.i32(i32) readnone
|
|
|
|
define i32 @g_32(i32 %a) {
|
|
; CHECK-LABEL: g_32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit w0, w0
|
|
; CHECK-NEXT: ret
|
|
%b = call i32 @llvm.bitreverse.i32(i32 %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
declare i64 @llvm.bitreverse.i64(i64) readnone
|
|
|
|
define i64 @g_64(i64 %a) {
|
|
; CHECK-LABEL: g_64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit x0, x0
|
|
; CHECK-NEXT: ret
|
|
%b = call i64 @llvm.bitreverse.i64(i64 %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
declare <16 x i3> @llvm.bitreverse.v16i3(<16 x i3>) readnone
|
|
|
|
define <16 x i3> @g_vec_16x3(<16 x i3> %a) {
|
|
; CHECK-LABEL: g_vec_16x3:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: ushr v0.16b, v0.16b, #5
|
|
; CHECK-NEXT: ret
|
|
%b = call <16 x i3> @llvm.bitreverse.v16i3(<16 x i3> %a)
|
|
ret <16 x i3> %b
|
|
}
|
|
|
|
declare <16 x i4> @llvm.bitreverse.v16i4(<16 x i4>) readnone
|
|
|
|
define <16 x i4> @g_vec_16x4(<16 x i4> %a) {
|
|
; CHECK-LABEL: g_vec_16x4:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: ushr v0.16b, v0.16b, #4
|
|
; CHECK-NEXT: ret
|
|
%b = call <16 x i4> @llvm.bitreverse.v16i4(<16 x i4> %a)
|
|
ret <16 x i4> %b
|
|
}
|
|
|
|
declare <8 x i8> @llvm.bitreverse.v8i8(<8 x i8>) readnone
|
|
|
|
define <8 x i8> @g_vec(<8 x i8> %a) {
|
|
; CHECK-LABEL: g_vec:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit v0.8b, v0.8b
|
|
; CHECK-NEXT: ret
|
|
%b = call <8 x i8> @llvm.bitreverse.v8i8(<8 x i8> %a)
|
|
ret <8 x i8> %b
|
|
}
|
|
|
|
declare <16 x i8> @llvm.bitreverse.v16i8(<16 x i8>) readnone
|
|
|
|
define <16 x i8> @g_vec_16x8(<16 x i8> %a) {
|
|
; CHECK-LABEL: g_vec_16x8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <16 x i8> @llvm.bitreverse.v16i8(<16 x i8> %a)
|
|
ret <16 x i8> %b
|
|
}
|
|
|
|
declare <32 x i8> @llvm.bitreverse.v32i8(<32 x i8>) readnone
|
|
|
|
define <32 x i8> @g_vec_32x8(<32 x i8> %a) {
|
|
; CHECK-LABEL: g_vec_32x8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: rbit v1.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <32 x i8> @llvm.bitreverse.v32i8(<32 x i8> %a)
|
|
ret <32 x i8> %b
|
|
}
|
|
|
|
declare <4 x i8> @llvm.bitreverse.v4i8(<4 x i8>) readnone
|
|
|
|
define <4 x i8> @g_vec_4x8(<4 x i8> %a) {
|
|
; SDAG-LABEL: g_vec_4x8:
|
|
; SDAG: // %bb.0:
|
|
; SDAG-NEXT: rev16 v0.8b, v0.8b
|
|
; SDAG-NEXT: rbit v0.8b, v0.8b
|
|
; SDAG-NEXT: ushr v0.4h, v0.4h, #8
|
|
; SDAG-NEXT: ret
|
|
;
|
|
; GISEL-LABEL: g_vec_4x8:
|
|
; GISEL: // %bb.0:
|
|
; GISEL-NEXT: uzp1 v0.8b, v0.8b, v0.8b
|
|
; GISEL-NEXT: rbit v0.8b, v0.8b
|
|
; GISEL-NEXT: ushll v0.8h, v0.8b, #0
|
|
; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0
|
|
; GISEL-NEXT: ret
|
|
%b = call <4 x i8> @llvm.bitreverse.v4i8(<4 x i8> %a)
|
|
ret <4 x i8> %b
|
|
}
|
|
|
|
declare <9 x i8> @llvm.bitreverse.v9i8(<9 x i8>) readnone
|
|
|
|
define <9 x i8> @g_vec_9x8(<9 x i8> %a) {
|
|
; CHECK-LABEL: g_vec_9x8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <9 x i8> @llvm.bitreverse.v9i8(<9 x i8> %a)
|
|
ret <9 x i8> %b
|
|
}
|
|
|
|
declare <4 x i16> @llvm.bitreverse.v4i16(<4 x i16>) readnone
|
|
|
|
define <4 x i16> @g_vec_4x16(<4 x i16> %a) {
|
|
; CHECK-LABEL: g_vec_4x16:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rev16 v0.8b, v0.8b
|
|
; CHECK-NEXT: rbit v0.8b, v0.8b
|
|
; CHECK-NEXT: ret
|
|
%b = call <4 x i16> @llvm.bitreverse.v4i16(<4 x i16> %a)
|
|
ret <4 x i16> %b
|
|
}
|
|
|
|
declare <8 x i16> @llvm.bitreverse.v8i16(<8 x i16>) readnone
|
|
|
|
define <8 x i16> @g_vec_8x16(<8 x i16> %a) {
|
|
; CHECK-LABEL: g_vec_8x16:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rev16 v0.16b, v0.16b
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <8 x i16> @llvm.bitreverse.v8i16(<8 x i16> %a)
|
|
ret <8 x i16> %b
|
|
}
|
|
|
|
declare <16 x i16> @llvm.bitreverse.v16i16(<16 x i16>) readnone
|
|
|
|
define <16 x i16> @g_vec_16x16(<16 x i16> %a) {
|
|
; CHECK-LABEL: g_vec_16x16:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rev16 v0.16b, v0.16b
|
|
; CHECK-NEXT: rev16 v1.16b, v1.16b
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: rbit v1.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <16 x i16> @llvm.bitreverse.v16i16(<16 x i16> %a)
|
|
ret <16 x i16> %b
|
|
}
|
|
|
|
declare <2 x i32> @llvm.bitreverse.v2i32(<2 x i32>) readnone
|
|
|
|
define <2 x i32> @g_vec_2x32(<2 x i32> %a) {
|
|
; CHECK-LABEL: g_vec_2x32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rev32 v0.8b, v0.8b
|
|
; CHECK-NEXT: rbit v0.8b, v0.8b
|
|
; CHECK-NEXT: ret
|
|
%b = call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %a)
|
|
ret <2 x i32> %b
|
|
}
|
|
|
|
declare <4 x i32> @llvm.bitreverse.v4i32(<4 x i32>) readnone
|
|
|
|
define <4 x i32> @g_vec_4x32(<4 x i32> %a) {
|
|
; CHECK-LABEL: g_vec_4x32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rev32 v0.16b, v0.16b
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <4 x i32> @llvm.bitreverse.v4i32(<4 x i32> %a)
|
|
ret <4 x i32> %b
|
|
}
|
|
|
|
declare <8 x i32> @llvm.bitreverse.v8i32(<8 x i32>) readnone
|
|
|
|
define <8 x i32> @g_vec_8x32(<8 x i32> %a) {
|
|
; CHECK-LABEL: g_vec_8x32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rev32 v0.16b, v0.16b
|
|
; CHECK-NEXT: rev32 v1.16b, v1.16b
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: rbit v1.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <8 x i32> @llvm.bitreverse.v8i32(<8 x i32> %a)
|
|
ret <8 x i32> %b
|
|
}
|
|
|
|
declare <1 x i64> @llvm.bitreverse.v1i64(<1 x i64>) readnone
|
|
|
|
define <1 x i64> @g_vec_1x64(<1 x i64> %a) {
|
|
; SDAG-LABEL: g_vec_1x64:
|
|
; SDAG: // %bb.0:
|
|
; SDAG-NEXT: rev64 v0.8b, v0.8b
|
|
; SDAG-NEXT: rbit v0.8b, v0.8b
|
|
; SDAG-NEXT: ret
|
|
;
|
|
; GISEL-LABEL: g_vec_1x64:
|
|
; GISEL: // %bb.0:
|
|
; GISEL-NEXT: fmov x8, d0
|
|
; GISEL-NEXT: rbit x8, x8
|
|
; GISEL-NEXT: fmov d0, x8
|
|
; GISEL-NEXT: ret
|
|
%b = call <1 x i64> @llvm.bitreverse.v1i64(<1 x i64> %a)
|
|
ret <1 x i64> %b
|
|
}
|
|
|
|
declare <2 x i64> @llvm.bitreverse.v2i64(<2 x i64>) readnone
|
|
|
|
define <2 x i64> @g_vec_2x64(<2 x i64> %a) {
|
|
; CHECK-LABEL: g_vec_2x64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rev64 v0.16b, v0.16b
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <2 x i64> @llvm.bitreverse.v2i64(<2 x i64> %a)
|
|
ret <2 x i64> %b
|
|
}
|
|
|
|
declare <4 x i64> @llvm.bitreverse.v4i64(<4 x i64>) readnone
|
|
|
|
define <4 x i64> @g_vec_4x64(<4 x i64> %a) {
|
|
; CHECK-LABEL: g_vec_4x64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: rev64 v0.16b, v0.16b
|
|
; CHECK-NEXT: rev64 v1.16b, v1.16b
|
|
; CHECK-NEXT: rbit v0.16b, v0.16b
|
|
; CHECK-NEXT: rbit v1.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%b = call <4 x i64> @llvm.bitreverse.v4i64(<4 x i64> %a)
|
|
ret <4 x i64> %b
|
|
}
|