Files
clang-p2996/llvm/test/CodeGen/WebAssembly/wide-arithmetic.ll
Alex Crichton c2293b33dd [WebAssembly] Implement the wide-arithmetic proposal (#111598)
This commit implements the [wide-arithmetic] proposal which has recently
reached phase 2 in the WebAssembly proposals process. The goal here is
to implement support in LLVM for emitting these instructions which are
gated behind a new feature flag by default. A new `wide-arithmetic`
feature flag is introduced which gates these four new instructions from
being emitted.

Emission of each instruction itself is relatively simple given LLVM's
preexisting lowering rules and infrastructure. The main gotcha is that
due to the multi-result nature of all of these instructions it needed
the lowerings to be implemented in C++ rather than in TableGen.

[wide-arithmetic]: https://github.com/WebAssembly/wide-arithmetic
2024-10-23 11:39:58 -07:00

133 lines
3.7 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mattr=+wide-arithmetic < %s | FileCheck %s
target triple = "wasm32-unknown-unknown"
define i128 @add_i128(i128 %a, i128 %b) {
; CHECK-LABEL: add_i128:
; CHECK: .functype add_i128 (i32, i64, i64, i64, i64) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i64.add128
; CHECK-NEXT: local.set 3
; CHECK-NEXT: local.set 4
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i64.store 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i64.store 0
; CHECK-NEXT: # fallthrough-return
%c = add i128 %a, %b
ret i128 %c
}
define i128 @sub_i128(i128 %a, i128 %b) {
; CHECK-LABEL: sub_i128:
; CHECK: .functype sub_i128 (i32, i64, i64, i64, i64) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 3
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i64.sub128
; CHECK-NEXT: local.set 3
; CHECK-NEXT: local.set 4
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i64.store 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i64.store 0
; CHECK-NEXT: # fallthrough-return
%c = sub i128 %a, %b
ret i128 %c
}
define i128 @mul_i128(i128 %a, i128 %b) {
; CHECK-LABEL: mul_i128:
; CHECK: .functype mul_i128 (i32, i64, i64, i64, i64) -> ()
; CHECK-NEXT: .local i64
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i64.mul_wide_u
; CHECK-NEXT: local.set 5
; CHECK-NEXT: i64.store 0
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 5
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 4
; CHECK-NEXT: i64.mul
; CHECK-NEXT: i64.add
; CHECK-NEXT: local.get 2
; CHECK-NEXT: local.get 3
; CHECK-NEXT: i64.mul
; CHECK-NEXT: i64.add
; CHECK-NEXT: i64.store 8
; CHECK-NEXT: # fallthrough-return
%c = mul i128 %a, %b
ret i128 %c
}
define i128 @i64_mul_wide_s(i64 %a, i64 %b) {
; CHECK-LABEL: i64_mul_wide_s:
; CHECK: .functype i64_mul_wide_s (i32, i64, i64) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 2
; CHECK-NEXT: i64.mul_wide_s
; CHECK-NEXT: local.set 1
; CHECK-NEXT: local.set 2
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
; CHECK-NEXT: i64.store 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 2
; CHECK-NEXT: i64.store 0
; CHECK-NEXT: # fallthrough-return
%a128 = sext i64 %a to i128
%b128 = sext i64 %b to i128
%c = mul i128 %a128, %b128
ret i128 %c
}
define i128 @i64_mul_wide_u(i64 %a, i64 %b) {
; CHECK-LABEL: i64_mul_wide_u:
; CHECK: .functype i64_mul_wide_u (i32, i64, i64) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 2
; CHECK-NEXT: i64.mul_wide_u
; CHECK-NEXT: local.set 1
; CHECK-NEXT: local.set 2
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
; CHECK-NEXT: i64.store 8
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 2
; CHECK-NEXT: i64.store 0
; CHECK-NEXT: # fallthrough-return
%a128 = zext i64 %a to i128
%b128 = zext i64 %b to i128
%c = mul i128 %a128, %b128
ret i128 %c
}
define i64 @mul_i128_only_lo(i128 %a, i128 %b) {
; CHECK-LABEL: mul_i128_only_lo:
; CHECK: .functype mul_i128_only_lo (i64, i64, i64, i64) -> (i64)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 2
; CHECK-NEXT: i64.mul
; CHECK-NEXT: # fallthrough-return
%c = mul i128 %a, %b
%d = trunc i128 %c to i64
ret i64 %d
}