Nikita Popov 4996e3be34 [ConstantFolding] Allow truncation when folding wasm.dot
Changes this to getSigned() to match the signedness of the calculation.
However, we still need to allow truncation because the addition
result may overflow, and the operation is specified to truncate
in that case.

Fixes https://github.com/llvm/llvm-project/issues/175159.
2026-01-09 17:15:31 +01:00

65 lines
2.6 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -passes=instsimplify -S < %s | FileCheck %s
; Test that intrinsics wasm dot call are constant folded
target triple = "wasm32-unknown-unknown"
define <4 x i32> @dot_zero() {
; CHECK-LABEL: define <4 x i32> @dot_zero() {
; CHECK-NEXT: ret <4 x i32> zeroinitializer
;
%res = tail call <4 x i32> @llvm.wasm.dot(<8 x i16> zeroinitializer, <8 x i16> zeroinitializer)
ret <4 x i32> %res
}
; a = 1 2 3 4 5 6 7 8
; b = 1 2 3 4 5 6 7 8
; k1|k2 = a * b = 1 4 9 16 25 36 49 64
; k1 + k2 = (1+4) | (9 + 16) | (25 + 36) | (49 + 64)
; result = 5 | 25 | 61 | 113
define <4 x i32> @dot_nonzero() {
; CHECK-LABEL: define <4 x i32> @dot_nonzero() {
; CHECK-NEXT: ret <4 x i32> <i32 5, i32 25, i32 61, i32 113>
;
%res = tail call <4 x i32> @llvm.wasm.dot(<8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>, <8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>)
ret <4 x i32> %res
}
define <4 x i32> @dot_one_negative() {
; CHECK-LABEL: define <4 x i32> @dot_one_negative() {
; CHECK-NEXT: ret <4 x i32> splat (i32 -2)
;
%res = tail call <4 x i32> @llvm.wasm.dot(<8 x i16> splat (i16 1), <8 x i16> splat (i16 -1))
ret <4 x i32> %res
}
define <4 x i32> @dot_doubly_negative() {
; CHECK-LABEL: define <4 x i32> @dot_doubly_negative() {
; CHECK-NEXT: ret <4 x i32> splat (i32 2)
;
%res = tail call <4 x i32> @llvm.wasm.dot(<8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>, <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
ret <4 x i32> %res
}
; Tests that i16 max signed values fit in i32
define <4 x i32> @dot_follow_modulo_spec_1() {
; CHECK-LABEL: define <4 x i32> @dot_follow_modulo_spec_1() {
; CHECK-NEXT: ret <4 x i32> <i32 2147352578, i32 0, i32 0, i32 0>
;
%res = tail call <4 x i32> @llvm.wasm.dot(<8 x i16> <i16 32767, i16 32767, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>, <8 x i16> <i16 32767, i16 32767, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>)
ret <4 x i32> %res
}
; Tests that i16 min signed values fit in i32
define <4 x i32> @dot_follow_modulo_spec_2() {
; CHECK-LABEL: define <4 x i32> @dot_follow_modulo_spec_2() {
; CHECK-NEXT: ret <4 x i32> <i32 -2147483648, i32 0, i32 0, i32 0>
;
%res = tail call <4 x i32> @llvm.wasm.dot(<8 x i16> <i16 -32768, i16 -32768, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>, <8 x i16> <i16 -32768, i16 -32768, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>)
ret <4 x i32> %res
}