llvm-project/llvm/test/CodeGen/AArch64/avoid-pre-trunc.ll
Simon Pilgrim f8edcba62d
[DAG] visitTRUNCATE - more aggressively fold trunc(add(x,x)) -> add(trunc(x),trunc(x)) (#164227)
We're very careful not to truncate binary arithmetic ops if it will
affect legality, or cause additional truncation instructions, hence we
currently limit this to cases where one operand is constant.

But if both ops are the same (i.e. for some add/mul cases) then we
wouldn't increase the number of truncations, so can be slightly more
aggressive at folding the truncation.
2025-10-21 10:17:57 +00:00

139 lines
5.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
; RUN: llc -mtriple=aarch64 < %s | FileCheck %s
define <16 x i8> @lower_trunc_16xi8(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e, i16 %f, i16 %g, i16 %h, i16 %i, i16 %j, i16 %k, i16 %l, i16 %m, i16 %n, i16 %o, i16 %p) {
; CHECK-LABEL: lower_trunc_16xi8:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov s0, w0
; CHECK-NEXT: mov x8, sp
; CHECK-NEXT: mov v0.b[1], w1
; CHECK-NEXT: mov v0.b[2], w2
; CHECK-NEXT: mov v0.b[3], w3
; CHECK-NEXT: mov v0.b[4], w4
; CHECK-NEXT: mov v0.b[5], w5
; CHECK-NEXT: mov v0.b[6], w6
; CHECK-NEXT: mov v0.b[7], w7
; CHECK-NEXT: ld1 { v0.b }[8], [x8]
; CHECK-NEXT: add x8, sp, #8
; CHECK-NEXT: ld1 { v0.b }[9], [x8]
; CHECK-NEXT: add x8, sp, #16
; CHECK-NEXT: ld1 { v0.b }[10], [x8]
; CHECK-NEXT: add x8, sp, #24
; CHECK-NEXT: ld1 { v0.b }[11], [x8]
; CHECK-NEXT: add x8, sp, #32
; CHECK-NEXT: ld1 { v0.b }[12], [x8]
; CHECK-NEXT: add x8, sp, #40
; CHECK-NEXT: ld1 { v0.b }[13], [x8]
; CHECK-NEXT: add x8, sp, #48
; CHECK-NEXT: ld1 { v0.b }[14], [x8]
; CHECK-NEXT: add x8, sp, #56
; CHECK-NEXT: ld1 { v0.b }[15], [x8]
; CHECK-NEXT: add v1.16b, v0.16b, v0.16b
; CHECK-NEXT: eor v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%a1 = insertelement <16 x i16> poison, i16 %a, i16 0
%b1 = insertelement <16 x i16> %a1, i16 %b, i16 1
%c1 = insertelement <16 x i16> %b1, i16 %c, i16 2
%d1 = insertelement <16 x i16> %c1, i16 %d, i16 3
%e1 = insertelement <16 x i16> %d1, i16 %e, i16 4
%f1 = insertelement <16 x i16> %e1, i16 %f, i16 5
%g1 = insertelement <16 x i16> %f1, i16 %g, i16 6
%h1 = insertelement <16 x i16> %g1, i16 %h, i16 7
%i1 = insertelement <16 x i16> %h1, i16 %i, i16 8
%j1 = insertelement <16 x i16> %i1, i16 %j, i16 9
%k1 = insertelement <16 x i16> %j1, i16 %k, i16 10
%l1 = insertelement <16 x i16> %k1, i16 %l, i16 11
%m1 = insertelement <16 x i16> %l1, i16 %m, i16 12
%n1 = insertelement <16 x i16> %m1, i16 %n, i16 13
%o1 = insertelement <16 x i16> %n1, i16 %o, i16 14
%p1 = insertelement <16 x i16> %o1, i16 %p, i16 15
%t = trunc <16 x i16> %p1 to <16 x i8>
%s = add <16 x i16> %p1, %p1
%t2 = trunc <16 x i16> %s to <16 x i8>
%pro = xor <16 x i8> %t, %t2
ret <16 x i8> %pro
}
define <8 x i16> @lower_trunc_8xi16(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {
; CHECK-LABEL: lower_trunc_8xi16:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov s0, w0
; CHECK-NEXT: mov v0.h[1], w1
; CHECK-NEXT: mov v0.h[2], w2
; CHECK-NEXT: mov v0.h[3], w3
; CHECK-NEXT: mov v0.h[4], w4
; CHECK-NEXT: mov v0.h[5], w5
; CHECK-NEXT: mov v0.h[6], w6
; CHECK-NEXT: mov v0.h[7], w7
; CHECK-NEXT: add v1.8h, v0.8h, v0.8h
; CHECK-NEXT: eor v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%a1 = insertelement <8 x i32> poison, i32 %a, i32 0
%b1 = insertelement <8 x i32> %a1, i32 %b, i32 1
%c1 = insertelement <8 x i32> %b1, i32 %c, i32 2
%d1 = insertelement <8 x i32> %c1, i32 %d, i32 3
%e1 = insertelement <8 x i32> %d1, i32 %e, i32 4
%f1 = insertelement <8 x i32> %e1, i32 %f, i32 5
%g1 = insertelement <8 x i32> %f1, i32 %g, i32 6
%h1 = insertelement <8 x i32> %g1, i32 %h, i32 7
%t = trunc <8 x i32> %h1 to <8 x i16>
%s = add <8 x i32> %h1, %h1
%t2 = trunc <8 x i32> %s to <8 x i16>
%o = xor <8 x i16> %t, %t2
ret <8 x i16> %o
}
define <4 x i32> @lower_trunc_4xi32(i64 %a, i64 %b, i64 %c, i64 %d) {
; CHECK-LABEL: lower_trunc_4xi32:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov s0, w0
; CHECK-NEXT: mov v0.s[1], w1
; CHECK-NEXT: mov v0.s[2], w2
; CHECK-NEXT: mov v0.s[3], w3
; CHECK-NEXT: add v1.4s, v0.4s, v0.4s
; CHECK-NEXT: eor v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%a1 = insertelement <4 x i64> poison, i64 %a, i64 0
%b1 = insertelement <4 x i64> %a1, i64 %b, i64 1
%c1 = insertelement <4 x i64> %b1, i64 %c, i64 2
%d1 = insertelement <4 x i64> %c1, i64 %d, i64 3
%t = trunc <4 x i64> %d1 to <4 x i32>
%s = add <4 x i64> %d1, %d1
%t2 = trunc <4 x i64> %s to <4 x i32>
%o = xor <4 x i32> %t, %t2
ret <4 x i32> %o
}
define <8 x i32> @lower_trunc_8xi32(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g, i64 %h) {
; CHECK-LABEL: lower_trunc_8xi32:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov d0, x6
; CHECK-NEXT: fmov d1, x4
; CHECK-NEXT: fmov d2, x2
; CHECK-NEXT: fmov d3, x0
; CHECK-NEXT: mov v0.d[1], x7
; CHECK-NEXT: mov v1.d[1], x5
; CHECK-NEXT: mov v2.d[1], x3
; CHECK-NEXT: mov v3.d[1], x1
; CHECK-NEXT: uzp1 v1.4s, v1.4s, v0.4s
; CHECK-NEXT: uzp1 v2.4s, v3.4s, v2.4s
; CHECK-NEXT: add v3.4s, v1.4s, v1.4s
; CHECK-NEXT: add v0.4s, v2.4s, v2.4s
; CHECK-NEXT: eor v1.16b, v1.16b, v3.16b
; CHECK-NEXT: eor v0.16b, v2.16b, v0.16b
; CHECK-NEXT: ret
%a1 = insertelement <8 x i64> poison, i64 %a, i64 0
%b1 = insertelement <8 x i64> %a1, i64 %b, i64 1
%c1 = insertelement <8 x i64> %b1, i64 %c, i64 2
%d1 = insertelement <8 x i64> %c1, i64 %d, i64 3
%e1 = insertelement <8 x i64> %d1, i64 %e, i64 4
%f1 = insertelement <8 x i64> %e1, i64 %f, i64 5
%g1 = insertelement <8 x i64> %f1, i64 %g, i64 6
%h1 = insertelement <8 x i64> %g1, i64 %h, i64 7
%t = trunc <8 x i64> %h1 to <8 x i32>
%s = add <8 x i64> %h1, %h1
%t2 = trunc <8 x i64> %s to <8 x i32>
%o = xor <8 x i32> %t, %t2
ret <8 x i32> %o
}