[llvm] [WebAssembly] [Codegen] Add pattern for relaxed min max from pmin/pmax-based patterns over v4f32 and v2f64 (PR #164486)
Jasmine Tang via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 22 03:00:55 PDT 2025
https://github.com/badumbatish updated https://github.com/llvm/llvm-project/pull/164486
>From 33e285cac2b051b0a042b4f874a1702ca85c3e1f Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Fri, 10 Oct 2025 16:57:54 -0700
Subject: [PATCH 1/8] Precommit test for relaxed min max
---
.../CodeGen/WebAssembly/simd-relaxed-fmax.ll | 35 +++++++++++++++++++
.../CodeGen/WebAssembly/simd-relaxed-fmin.ll | 34 ++++++++++++++++++
2 files changed, 69 insertions(+)
create mode 100644 llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
new file mode 100644
index 0000000000000..d54ad2a084e5c
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
@@ -0,0 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+
+; RUN: llc < %s -mtriple=wasm32-unknown-unknown -mattr=+simd128,+relaxed-simd | FileCheck %s
+
+; Test that fminimum and fmaximum get transformed to relaxed_min and relaxed_max
+
+target triple = "wasm32"
+
+define <4 x float> @test_max_f32x4(<4 x float> %a, <4 x float> %b) {
+; CHECK-LABEL: test_max_f32x4:
+; CHECK: .functype test_max_f32x4 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.max
+; CHECK-NEXT: # fallthrough-return
+ %result = call <4 x float> @llvm.maximum.v4f32(<4 x float> %a, <4 x float> %b)
+ ret <4 x float> %result
+}
+
+
+define <2 x double> @test_max_f64x2(<2 x double> %a, <2 x double> %b) {
+; CHECK-LABEL: test_max_f64x2:
+; CHECK: .functype test_max_f64x2 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.max
+; CHECK-NEXT: # fallthrough-return
+ %result = call <2 x double> @llvm.maximum.v2f64(<2 x double> %a, <2 x double> %b)
+ ret <2 x double> %result
+}
+
+declare <4 x float> @llvm.maximum.v4f32(<4 x float>, <4 x float>)
+declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
new file mode 100644
index 0000000000000..11f96181914d7
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=wasm32-unknown-unknown -mattr=+simd128,+relaxed-simd | FileCheck %s
+
+; Test that fminimum and fmaximum get transformed to relaxed_min and relaxed_max
+
+target triple = "wasm32"
+
+define <4 x float> @test_min_f32x4(<4 x float> %a, <4 x float> %b) {
+; CHECK-LABEL: test_min_f32x4:
+; CHECK: .functype test_min_f32x4 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.min
+; CHECK-NEXT: # fallthrough-return
+ %result = call <4 x float> @llvm.minimum.v4f32(<4 x float> %a, <4 x float> %b)
+ ret <4 x float> %result
+}
+
+
+define <2 x double> @test_min_f64x2(<2 x double> %a, <2 x double> %b) {
+; CHECK-LABEL: test_min_f64x2:
+; CHECK: .functype test_min_f64x2 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.min
+; CHECK-NEXT: # fallthrough-return
+ %result = call <2 x double> @llvm.minimum.v2f64(<2 x double> %a, <2 x double> %b)
+ ret <2 x double> %result
+}
+
+declare <4 x float> @llvm.minimum.v4f32(<4 x float>, <4 x float>)
+declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>)
>From 944fdbeb134006a8b480c75cf9514d838e9f70d2 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Fri, 10 Oct 2025 16:58:07 -0700
Subject: [PATCH 2/8] Add implementation
---
.../WebAssembly/WebAssemblyInstrSIMD.td | 20 +++++++++++++++++++
.../CodeGen/WebAssembly/simd-relaxed-fmax.ll | 4 ++--
.../CodeGen/WebAssembly/simd-relaxed-fmin.ll | 4 ++--
3 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index 49af78bce68c3..0dd5e30ed9c86 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -1692,6 +1692,26 @@ defm SIMD_RELAXED_FMIN :
defm SIMD_RELAXED_FMAX :
RelaxedBinary<F64x2, int_wasm_relaxed_max, "relaxed_max", 0x110>;
+// Transform standard fminimum/fmaximum to relaxed versions
+// AddedComplexity ensures these patterns match before the standard MIN/MAX
+let AddedComplexity = 1 in {
+def : Pat<(v4f32 (fminimum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
+
+def : Pat<(v4f32 (fmaximum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
+
+def : Pat<(v2f64 (fminimum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
+
+def : Pat<(v2f64 (fmaximum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
+}
+
//===----------------------------------------------------------------------===//
// Relaxed rounding q15 multiplication
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
index d54ad2a084e5c..1339f3a730150 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
@@ -12,7 +12,7 @@ define <4 x float> @test_max_f32x4(<4 x float> %a, <4 x float> %b) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.max
+; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
%result = call <4 x float> @llvm.maximum.v4f32(<4 x float> %a, <4 x float> %b)
ret <4 x float> %result
@@ -25,7 +25,7 @@ define <2 x double> @test_max_f64x2(<2 x double> %a, <2 x double> %b) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.max
+; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
%result = call <2 x double> @llvm.maximum.v2f64(<2 x double> %a, <2 x double> %b)
ret <2 x double> %result
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
index 11f96181914d7..799cc4a45144c 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
@@ -11,7 +11,7 @@ define <4 x float> @test_min_f32x4(<4 x float> %a, <4 x float> %b) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.min
+; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
%result = call <4 x float> @llvm.minimum.v4f32(<4 x float> %a, <4 x float> %b)
ret <4 x float> %result
@@ -24,7 +24,7 @@ define <2 x double> @test_min_f64x2(<2 x double> %a, <2 x double> %b) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.min
+; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
%result = call <2 x double> @llvm.minimum.v2f64(<2 x double> %a, <2 x double> %b)
ret <2 x double> %result
>From 653c167ae3d773a99058ef2ff2e424403d907a4b Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Mon, 20 Oct 2025 12:41:31 -0700
Subject: [PATCH 3/8] Replace min/max with fminnum fminimumnum fmaxnum
fmaximumnum
---
.../WebAssembly/WebAssemblyISelLowering.cpp | 5 ++
.../WebAssembly/WebAssemblyInstrSIMD.td | 40 +++++++++++-----
.../CodeGen/WebAssembly/simd-relaxed-fmax.ll | 47 ++++++++++++++-----
.../CodeGen/WebAssembly/simd-relaxed-fmin.ll | 47 ++++++++++++++-----
4 files changed, 105 insertions(+), 34 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 64723340051b8..70c9e499945fe 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -183,6 +183,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
for (auto T : {MVT::i32, MVT::i64})
setOperationAction(Op, T, Custom);
+ if (Subtarget->hasRelaxedSIMD()) {
+ setOperationAction(
+ {ISD::FMINNUM, ISD::FMINIMUMNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM},
+ {MVT::v4f32, MVT::v2f64}, Legal);
+ }
// SIMD-specific configuration
if (Subtarget->hasSIMD128()) {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index 0dd5e30ed9c86..c165de5f18678 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -1695,21 +1695,37 @@ defm SIMD_RELAXED_FMAX :
// Transform standard fminimum/fmaximum to relaxed versions
// AddedComplexity ensures these patterns match before the standard MIN/MAX
let AddedComplexity = 1 in {
-def : Pat<(v4f32 (fminimum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+ def : Pat<(v4f32 (fminnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
-def : Pat<(v4f32 (fmaximum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+ def : Pat<(v4f32 (fminimumnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
-def : Pat<(v2f64 (fminimum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+ def : Pat<(v4f32 (fmaxnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
-def : Pat<(v2f64 (fmaximum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+ def : Pat<(v4f32 (fmaximumnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
+
+ def : Pat<(v2f64 (fminnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
+
+ def : Pat<(v2f64 (fminimumnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
+
+ def : Pat<(v2f64 (fmaxnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
+
+ def : Pat<(v2f64 (fmaximumnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
index 1339f3a730150..45f4ddd783a55 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
@@ -2,34 +2,59 @@
; RUN: llc < %s -mtriple=wasm32-unknown-unknown -mattr=+simd128,+relaxed-simd | FileCheck %s
-; Test that fminimum and fmaximum get transformed to relaxed_min and relaxed_max
+; Test that fmaxnum and fmaximumnum get transformed to relaxed_max
target triple = "wasm32"
-define <4 x float> @test_max_f32x4(<4 x float> %a, <4 x float> %b) {
-; CHECK-LABEL: test_max_f32x4:
-; CHECK: .functype test_max_f32x4 (v128, v128) -> (v128)
+define <4 x float> @test_maxnum_f32x4(<4 x float> %a, <4 x float> %b) {
+; CHECK-LABEL: test_maxnum_f32x4:
+; CHECK: .functype test_maxnum_f32x4 (v128, v128) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
- %result = call <4 x float> @llvm.maximum.v4f32(<4 x float> %a, <4 x float> %b)
+ %result = call <4 x float> @llvm.maxnum.v4f32(<4 x float> %a, <4 x float> %b)
ret <4 x float> %result
}
+define <4 x float> @test_maximumnum_f32x4(<4 x float> %a, <4 x float> %b) {
+; CHECK-LABEL: test_maximumnum_f32x4:
+; CHECK: .functype test_maximumnum_f32x4 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.relaxed_max
+; CHECK-NEXT: # fallthrough-return
+ %result = call <4 x float> @llvm.maximumnum.v4f32(<4 x float> %a, <4 x float> %b)
+ ret <4 x float> %result
+}
+
+define <2 x double> @test_maxnum_f64x2(<2 x double> %a, <2 x double> %b) {
+; CHECK-LABEL: test_maxnum_f64x2:
+; CHECK: .functype test_maxnum_f64x2 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.relaxed_max
+; CHECK-NEXT: # fallthrough-return
+ %result = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %a, <2 x double> %b)
+ ret <2 x double> %result
+}
-define <2 x double> @test_max_f64x2(<2 x double> %a, <2 x double> %b) {
-; CHECK-LABEL: test_max_f64x2:
-; CHECK: .functype test_max_f64x2 (v128, v128) -> (v128)
+define <2 x double> @test_minimumnum_f64x2(<2 x double> %a, <2 x double> %b) {
+; CHECK-LABEL: test_minimumnum_f64x2:
+; CHECK: .functype test_minimumnum_f64x2 (v128, v128) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
- %result = call <2 x double> @llvm.maximum.v2f64(<2 x double> %a, <2 x double> %b)
+ %result = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> %a, <2 x double> %b)
ret <2 x double> %result
}
-declare <4 x float> @llvm.maximum.v4f32(<4 x float>, <4 x float>)
-declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
+declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>)
+declare <4 x float> @llvm.maximumnum.v4f32(<4 x float>, <4 x float>)
+declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)
+declare <2 x double> @llvm.maximumnum.v2f64(<2 x double>, <2 x double>)
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
index 799cc4a45144c..f3eec023663a7 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
@@ -1,34 +1,59 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=wasm32-unknown-unknown -mattr=+simd128,+relaxed-simd | FileCheck %s
-; Test that fminimum and fmaximum get transformed to relaxed_min and relaxed_max
+; Test that fminnum and fminimumnum get transformed to relaxed_min
target triple = "wasm32"
-define <4 x float> @test_min_f32x4(<4 x float> %a, <4 x float> %b) {
-; CHECK-LABEL: test_min_f32x4:
-; CHECK: .functype test_min_f32x4 (v128, v128) -> (v128)
+define <4 x float> @test_minnum_f32x4(<4 x float> %a, <4 x float> %b) {
+; CHECK-LABEL: test_minnum_f32x4:
+; CHECK: .functype test_minnum_f32x4 (v128, v128) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
- %result = call <4 x float> @llvm.minimum.v4f32(<4 x float> %a, <4 x float> %b)
+ %result = call <4 x float> @llvm.minnum.v4f32(<4 x float> %a, <4 x float> %b)
ret <4 x float> %result
}
+define <4 x float> @test_minimumnum_f32x4(<4 x float> %a, <4 x float> %b) {
+; CHECK-LABEL: test_minimumnum_f32x4:
+; CHECK: .functype test_minimumnum_f32x4 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.relaxed_min
+; CHECK-NEXT: # fallthrough-return
+ %result = call <4 x float> @llvm.minimumnum.v4f32(<4 x float> %a, <4 x float> %b)
+ ret <4 x float> %result
+}
+
+define <2 x double> @test_minnum_f64x2(<2 x double> %a, <2 x double> %b) {
+; CHECK-LABEL: test_minnum_f64x2:
+; CHECK: .functype test_minnum_f64x2 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.relaxed_min
+; CHECK-NEXT: # fallthrough-return
+ %result = call <2 x double> @llvm.minnum.v2f64(<2 x double> %a, <2 x double> %b)
+ ret <2 x double> %result
+}
-define <2 x double> @test_min_f64x2(<2 x double> %a, <2 x double> %b) {
-; CHECK-LABEL: test_min_f64x2:
-; CHECK: .functype test_min_f64x2 (v128, v128) -> (v128)
+define <2 x double> @test_minimumnum_f64x2(<2 x double> %a, <2 x double> %b) {
+; CHECK-LABEL: test_minimumnum_f64x2:
+; CHECK: .functype test_minimumnum_f64x2 (v128, v128) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
- %result = call <2 x double> @llvm.minimum.v2f64(<2 x double> %a, <2 x double> %b)
+ %result = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> %a, <2 x double> %b)
ret <2 x double> %result
}
-declare <4 x float> @llvm.minimum.v4f32(<4 x float>, <4 x float>)
-declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>)
+declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>)
+declare <4 x float> @llvm.fminimumnum.v4f32(<4 x float>, <4 x float>)
+declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)
+declare <2 x double> @llvm.fminimumnum.v2f64(<2 x double>, <2 x double>)
>From 657d189e413758501ccb7061cb626551569fc664 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 21 Oct 2025 09:21:28 -0700
Subject: [PATCH 4/8] Remove AddedComplexity
---
.../WebAssembly/WebAssemblyInstrSIMD.td | 51 +++++++++----------
1 file changed, 24 insertions(+), 27 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index c165de5f18678..4d87157aa92c9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -1693,40 +1693,37 @@ defm SIMD_RELAXED_FMAX :
RelaxedBinary<F64x2, int_wasm_relaxed_max, "relaxed_max", 0x110>;
// Transform standard fminimum/fmaximum to relaxed versions
-// AddedComplexity ensures these patterns match before the standard MIN/MAX
-let AddedComplexity = 1 in {
- def : Pat<(v4f32 (fminnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+def : Pat<(v4f32 (fminnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
- def : Pat<(v4f32 (fminimumnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+def : Pat<(v4f32 (fminimumnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
- def : Pat<(v4f32 (fmaxnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+def : Pat<(v4f32 (fmaxnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
- def : Pat<(v4f32 (fmaximumnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+def : Pat<(v4f32 (fmaximumnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
- def : Pat<(v2f64 (fminnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+def : Pat<(v2f64 (fminnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
- def : Pat<(v2f64 (fminimumnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+def : Pat<(v2f64 (fminimumnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
- def : Pat<(v2f64 (fmaxnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+def : Pat<(v2f64 (fmaxnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
- def : Pat<(v2f64 (fmaximumnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
-}
+def : Pat<(v2f64 (fmaximumnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
+ (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
+ Requires<[HasRelaxedSIMD]>;
//===----------------------------------------------------------------------===//
// Relaxed rounding q15 multiplication
>From fa53adc18f0222b0d56985e90b7686d9aacbfd9e Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 21 Oct 2025 10:57:31 -0700
Subject: [PATCH 5/8] Refactor patterns for future PRs
---
.../WebAssembly/WebAssemblyInstrSIMD.td | 48 +++++++------------
1 file changed, 16 insertions(+), 32 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index 4d87157aa92c9..19bafaf85ba8f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -1692,38 +1692,22 @@ defm SIMD_RELAXED_FMIN :
defm SIMD_RELAXED_FMAX :
RelaxedBinary<F64x2, int_wasm_relaxed_max, "relaxed_max", 0x110>;
-// Transform standard fminimum/fmaximum to relaxed versions
-def : Pat<(v4f32 (fminnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
-
-def : Pat<(v4f32 (fminimumnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
-
-def : Pat<(v4f32 (fmaxnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
-
-def : Pat<(v4f32 (fmaximumnum (v4f32 V128:$lhs), (v4f32 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F32x4 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
-
-def : Pat<(v2f64 (fminnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
-
-def : Pat<(v2f64 (fminimumnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMIN_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
-
-def : Pat<(v2f64 (fmaxnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
-
-def : Pat<(v2f64 (fmaximumnum (v2f64 V128:$lhs), (v2f64 V128:$rhs))),
- (SIMD_RELAXED_FMAX_F64x2 V128:$lhs, V128:$rhs)>,
- Requires<[HasRelaxedSIMD]>;
+let Predicates = [HasRelaxedSIMD] in {
+ foreach vec = [F32x4, F64x2] in {
+ defvar relaxed_min = !cast<NI>("SIMD_RELAXED_FMIN_"#vec);
+ defvar relaxed_max = !cast<NI>("SIMD_RELAXED_FMAX_"#vec);
+
+ // Transform standard fminimum/fmaximum to relaxed versions
+ def : Pat<(vec.vt (fminnum (vec.vt V128:$lhs), (vec.vt V128:$rhs))),
+ (relaxed_min V128:$lhs, V128:$rhs)>;
+ def : Pat<(vec.vt (fminimumnum (vec.vt V128:$lhs), (vec.vt V128:$rhs))),
+ (relaxed_min V128:$lhs, V128:$rhs)>;
+ def : Pat<(vec.vt (fmaxnum (vec.vt V128:$lhs), (vec.vt V128:$rhs))),
+ (relaxed_max V128:$lhs, V128:$rhs)>;
+ def : Pat<(vec.vt (fmaximumnum (vec.vt V128:$lhs), (vec.vt V128:$rhs))),
+ (relaxed_max V128:$lhs, V128:$rhs)>;
+ }
+}
//===----------------------------------------------------------------------===//
// Relaxed rounding q15 multiplication
>From a107ba56204a260fc3518fafd14e20f105ad4582 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 21 Oct 2025 12:53:40 -0700
Subject: [PATCH 6/8] Precommit pmin pmax
---
.../CodeGen/WebAssembly/simd-relaxed-fmax.ll | 244 +++++++++++++++++
.../CodeGen/WebAssembly/simd-relaxed-fmin.ll | 246 ++++++++++++++++++
2 files changed, 490 insertions(+)
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
index 45f4ddd783a55..80699f2543fc5 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
@@ -54,6 +54,250 @@ define <2 x double> @test_minimumnum_f64x2(<2 x double> %a, <2 x double> %b) {
ret <2 x double> %result
}
+define <4 x float> @test_pmax_v4f32_olt(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmax_v4f32_olt:
+; CHECK: .functype test_pmax_v4f32_olt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp olt <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+define <4 x float> @test_pmax_v4f32_ole(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmax_v4f32_ole:
+; CHECK: .functype test_pmax_v4f32_ole (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp ole <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+define <4 x float> @test_pmax_v4f32_ogt(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmax_v4f32_ogt:
+; CHECK: .functype test_pmax_v4f32_ogt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp ogt <4 x float> %y, %x
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+define <4 x float> @test_pmax_v4f32_oge(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmax_v4f32_oge:
+; CHECK: .functype test_pmax_v4f32_oge (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp oge <4 x float> %y, %x
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+; For setlt
+define <4 x float> @pmax_v4f32_fast_olt(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: pmax_v4f32_fast_olt:
+; CHECK: .functype pmax_v4f32_fast_olt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.relaxed_max
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast olt <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+; For setle
+define <4 x float> @test_pmax_v4f32_fast_ole(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmax_v4f32_fast_ole:
+; CHECK: .functype test_pmax_v4f32_fast_ole (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast ole <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+; For setgt
+define <4 x float> @test_pmax_v4f32_fast_ogt(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmax_v4f32_fast_ogt:
+; CHECK: .functype test_pmax_v4f32_fast_ogt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.relaxed_max
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast ogt <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %x, <4 x float> %y
+ ret <4 x float> %a
+}
+
+; For setge
+define <4 x float> @test_pmax_v4f32_fast_oge(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmax_v4f32_fast_oge:
+; CHECK: .functype test_pmax_v4f32_fast_oge (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast oge <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %x, <4 x float> %y
+ ret <4 x float> %a
+}
+
+define <4 x i32> @test_pmax_int_v4f32(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: test_pmax_int_v4f32:
+; CHECK: .functype test_pmax_int_v4f32 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: # fallthrough-return
+ %fx = bitcast <4 x i32> %x to <4 x float>
+ %fy = bitcast <4 x i32> %y to <4 x float>
+ %c = fcmp olt <4 x float> %fy, %fx
+ %a = select <4 x i1> %c, <4 x i32> %x, <4 x i32> %y
+ ret <4 x i32> %a
+}
+
+define <2 x double> @test_pmax_v2f64_olt(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmax_v2f64_olt:
+; CHECK: .functype test_pmax_v2f64_olt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp olt <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+define <2 x double> @test_pmax_v2f64_ole(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmax_v2f64_ole:
+; CHECK: .functype test_pmax_v2f64_ole (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp ole <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+define <2 x double> @test_pmax_v2f64_ogt(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmax_v2f64_ogt:
+; CHECK: .functype test_pmax_v2f64_ogt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp ogt <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %a
+}
+define <2 x double> @test_pmax_v2f64_oge(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmax_v2f64_oge:
+; CHECK: .functype test_pmax_v2f64_oge (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp oge <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %a
+}
+
+; For setlt
+define <2 x double> @pmax_v2f64_fast_olt(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: pmax_v2f64_fast_olt:
+; CHECK: .functype pmax_v2f64_fast_olt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.relaxed_max
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast olt <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+; For setle
+define <2 x double> @test_pmax_v2f64_fast_ole(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmax_v2f64_fast_ole:
+; CHECK: .functype test_pmax_v2f64_fast_ole (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast ole <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+; For setgt
+define <2 x double> @test_pmax_v2f64_fast_ogt(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmax_v2f64_fast_ogt:
+; CHECK: .functype test_pmax_v2f64_fast_ogt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.relaxed_max
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast ogt <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %a
+}
+
+; For setge
+define <2 x double> @test_pmax_v2f64_fast_oge(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmax_v2f64_fast_oge:
+; CHECK: .functype test_pmax_v2f64_fast_oge (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast oge <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %a
+}
+
+define <2 x i64> @test_pmax_int_v2f64(<2 x i64> %x, <2 x i64> %y) {
+; CHECK-LABEL: test_pmax_int_v2f64:
+; CHECK: .functype test_pmax_int_v2f64 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: # fallthrough-return
+ %fx = bitcast <2 x i64> %x to <2 x double>
+ %fy = bitcast <2 x i64> %y to <2 x double>
+ %c = fcmp olt <2 x double> %fy, %fx
+ %a = select <2 x i1> %c, <2 x i64> %x, <2 x i64> %y
+ ret <2 x i64> %a
+}
+
declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>)
declare <4 x float> @llvm.maximumnum.v4f32(<4 x float>, <4 x float>)
declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
index f3eec023663a7..2bfa665a136dc 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
@@ -53,6 +53,252 @@ define <2 x double> @test_minimumnum_f64x2(<2 x double> %a, <2 x double> %b) {
ret <2 x double> %result
}
+define <4 x float> @test_pmin_v4f32_olt(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmin_v4f32_olt:
+; CHECK: .functype test_pmin_v4f32_olt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp olt <4 x float> %y, %x
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+define <4 x float> @test_pmin_v4f32_ole(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmin_v4f32_ole:
+; CHECK: .functype test_pmin_v4f32_ole (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp ole <4 x float> %y, %x
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+define <4 x float> @test_pmin_v4f32_ogt(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmin_v4f32_ogt:
+; CHECK: .functype test_pmin_v4f32_ogt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp ogt <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+define <4 x float> @test_pmin_v4f32_oge(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmin_v4f32_oge:
+; CHECK: .functype test_pmin_v4f32_oge (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp oge <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+; For setlt
+define <4 x float> @pmin_v4f32_fast_olt(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: pmin_v4f32_fast_olt:
+; CHECK: .functype pmin_v4f32_fast_olt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: f32x4.relaxed_min
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast olt <4 x float> %y, %x
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+; For setle
+define <4 x float> @test_pmin_v4f32_fast_ole(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmin_v4f32_fast_ole:
+; CHECK: .functype test_pmin_v4f32_fast_ole (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast ole <4 x float> %y, %x
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+; For setgt
+define <4 x float> @test_pmin_v4f32_fast_ogt(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmin_v4f32_fast_ogt:
+; CHECK: .functype test_pmin_v4f32_fast_ogt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.relaxed_min
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast ogt <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+; For setge
+define <4 x float> @test_pmin_v4f32_fast_oge(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: test_pmin_v4f32_fast_oge:
+; CHECK: .functype test_pmin_v4f32_fast_oge (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast oge <4 x float> %x, %y
+ %a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
+ ret <4 x float> %a
+}
+
+define <4 x i32> @test_pmin_int_v4f32(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: test_pmin_int_v4f32:
+; CHECK: .functype test_pmin_int_v4f32 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: # fallthrough-return
+ %fx = bitcast <4 x i32> %x to <4 x float>
+ %fy = bitcast <4 x i32> %y to <4 x float>
+ %c = fcmp olt <4 x float> %fy, %fx
+ %a = select <4 x i1> %c, <4 x i32> %y, <4 x i32> %x
+ ret <4 x i32> %a
+}
+
+define <2 x double> @test_pmin_v2f64_olt(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmin_v2f64_olt:
+; CHECK: .functype test_pmin_v2f64_olt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp olt <2 x double> %y, %x
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+define <2 x double> @test_pmin_v2f64_ole(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmin_v2f64_ole:
+; CHECK: .functype test_pmin_v2f64_ole (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp ole <2 x double> %y, %x
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+define <2 x double> @test_pmin_v2f64_ogt(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmin_v2f64_ogt:
+; CHECK: .functype test_pmin_v2f64_ogt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp ogt <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+define <2 x double> @test_pmin_v2f64_oge(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmin_v2f64_oge:
+; CHECK: .functype test_pmin_v2f64_oge (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp oge <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+; For setlt
+define <2 x double> @pmin_v2f64_fast_olt(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: pmin_v2f64_fast_olt:
+; CHECK: .functype pmin_v2f64_fast_olt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: f64x2.relaxed_min
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast olt <2 x double> %y, %x
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+; For setle
+define <2 x double> @test_pmin_v2f64_fast_ole(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmin_v2f64_fast_ole:
+; CHECK: .functype test_pmin_v2f64_fast_ole (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast ole <2 x double> %y, %x
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+; For setgt
+define <2 x double> @test_pmin_v2f64_fast_ogt(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmin_v2f64_fast_ogt:
+; CHECK: .functype test_pmin_v2f64_fast_ogt (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.relaxed_min
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast ogt <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+; For setge
+define <2 x double> @test_pmin_v2f64_fast_oge(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: test_pmin_v2f64_fast_oge:
+; CHECK: .functype test_pmin_v2f64_fast_oge (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: # fallthrough-return
+ %c = fcmp fast oge <2 x double> %x, %y
+ %a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
+ ret <2 x double> %a
+}
+
+define <2 x i64> @test_pmin_int_v2f64(<2 x i64> %x, <2 x i64> %y) {
+; CHECK-LABEL: test_pmin_int_v2f64:
+; CHECK: .functype test_pmin_int_v2f64 (v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: # fallthrough-return
+ %fx = bitcast <2 x i64> %x to <2 x double>
+ %fy = bitcast <2 x i64> %y to <2 x double>
+ %c = fcmp olt <2 x double> %fy, %fx
+ %a = select <2 x i1> %c, <2 x i64> %y, <2 x i64> %x
+ ret <2 x i64> %a
+}
+
declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>)
declare <4 x float> @llvm.fminimumnum.v4f32(<4 x float>, <4 x float>)
declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)
>From a531eba42e53231029213bf334e2ac7676bfb908 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 21 Oct 2025 12:57:06 -0700
Subject: [PATCH 7/8] Added pmin pmax based patterns
---
.../WebAssembly/WebAssemblyInstrSIMD.td | 19 +++++++++++++
.../CodeGen/WebAssembly/simd-relaxed-fmax.ll | 28 +++++++++----------
.../CodeGen/WebAssembly/simd-relaxed-fmin.ll | 28 +++++++++----------
3 files changed, 47 insertions(+), 28 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index 19bafaf85ba8f..156ac44f119a6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -1706,6 +1706,25 @@ let Predicates = [HasRelaxedSIMD] in {
(relaxed_max V128:$lhs, V128:$rhs)>;
def : Pat<(vec.vt (fmaximumnum (vec.vt V128:$lhs), (vec.vt V128:$rhs))),
(relaxed_max V128:$lhs, V128:$rhs)>;
+
+ // Transform pmin/max-supposed patterns to relaxed min max
+ let AddedComplexity = 1 in {
+ def : Pat<(vec.vt (pmin (vec.vt V128:$lhs), (vec.vt V128:$rhs))),
+ (relaxed_min $lhs, $rhs)>;
+ def : Pat<(vec.vt (pmax (vec.vt V128:$lhs), (vec.vt V128:$rhs))),
+ (relaxed_max $lhs, $rhs)>;
+
+ def : Pat<(vec.int_vt (vselect
+ (setolt (vec.vt (bitconvert V128:$rhs)),
+ (vec.vt (bitconvert V128:$lhs))),
+ V128:$rhs, V128:$lhs)),
+ (relaxed_min $lhs, $rhs)>;
+ def : Pat<(vec.int_vt (vselect
+ (setolt (vec.vt (bitconvert V128:$lhs)),
+ (vec.vt (bitconvert V128:$rhs))),
+ V128:$rhs, V128:$lhs)),
+ (relaxed_max $lhs, $rhs)>;
+ }
}
}
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
index 80699f2543fc5..f224a0dc21136 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmax.ll
@@ -60,7 +60,7 @@ define <4 x float> @test_pmax_v4f32_olt(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp olt <4 x float> %x, %y
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -73,7 +73,7 @@ define <4 x float> @test_pmax_v4f32_ole(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp ole <4 x float> %x, %y
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -86,7 +86,7 @@ define <4 x float> @test_pmax_v4f32_ogt(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp ogt <4 x float> %y, %x
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -99,7 +99,7 @@ define <4 x float> @test_pmax_v4f32_oge(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp oge <4 x float> %y, %x
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -127,7 +127,7 @@ define <4 x float> @test_pmax_v4f32_fast_ole(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp fast ole <4 x float> %x, %y
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -155,7 +155,7 @@ define <4 x float> @test_pmax_v4f32_fast_oge(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp fast oge <4 x float> %x, %y
%a = select <4 x i1> %c, <4 x float> %x, <4 x float> %y
@@ -168,7 +168,7 @@ define <4 x i32> @test_pmax_int_v4f32(<4 x i32> %x, <4 x i32> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: f32x4.pmax
+; CHECK-NEXT: f32x4.relaxed_max
; CHECK-NEXT: # fallthrough-return
%fx = bitcast <4 x i32> %x to <4 x float>
%fy = bitcast <4 x i32> %y to <4 x float>
@@ -183,7 +183,7 @@ define <2 x double> @test_pmax_v2f64_olt(<2 x double> %x, <2 x double> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp olt <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -196,7 +196,7 @@ define <2 x double> @test_pmax_v2f64_ole(<2 x double> %x, <2 x double> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp ole <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -209,7 +209,7 @@ define <2 x double> @test_pmax_v2f64_ogt(<2 x double> %x, <2 x double> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp ogt <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %x, <2 x double> %y
@@ -221,7 +221,7 @@ define <2 x double> @test_pmax_v2f64_oge(<2 x double> %x, <2 x double> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp oge <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %x, <2 x double> %y
@@ -249,7 +249,7 @@ define <2 x double> @test_pmax_v2f64_fast_ole(<2 x double> %x, <2 x double> %y)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp fast ole <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -276,7 +276,7 @@ define <2 x double> @test_pmax_v2f64_fast_oge(<2 x double> %x, <2 x double> %y)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
%c = fcmp fast oge <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %x, <2 x double> %y
@@ -289,7 +289,7 @@ define <2 x i64> @test_pmax_int_v2f64(<2 x i64> %x, <2 x i64> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: f64x2.pmax
+; CHECK-NEXT: f64x2.relaxed_max
; CHECK-NEXT: # fallthrough-return
%fx = bitcast <2 x i64> %x to <2 x double>
%fy = bitcast <2 x i64> %y to <2 x double>
diff --git a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
index 2bfa665a136dc..460446574ecfb 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-relaxed-fmin.ll
@@ -59,7 +59,7 @@ define <4 x float> @test_pmin_v4f32_olt(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp olt <4 x float> %y, %x
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -72,7 +72,7 @@ define <4 x float> @test_pmin_v4f32_ole(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp ole <4 x float> %y, %x
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -85,7 +85,7 @@ define <4 x float> @test_pmin_v4f32_ogt(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp ogt <4 x float> %x, %y
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -98,7 +98,7 @@ define <4 x float> @test_pmin_v4f32_oge(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp oge <4 x float> %x, %y
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -126,7 +126,7 @@ define <4 x float> @test_pmin_v4f32_fast_ole(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp fast ole <4 x float> %y, %x
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -154,7 +154,7 @@ define <4 x float> @test_pmin_v4f32_fast_oge(<4 x float> %x, <4 x float> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp fast oge <4 x float> %x, %y
%a = select <4 x i1> %c, <4 x float> %y, <4 x float> %x
@@ -167,7 +167,7 @@ define <4 x i32> @test_pmin_int_v4f32(<4 x i32> %x, <4 x i32> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f32x4.pmin
+; CHECK-NEXT: f32x4.relaxed_min
; CHECK-NEXT: # fallthrough-return
%fx = bitcast <4 x i32> %x to <4 x float>
%fy = bitcast <4 x i32> %y to <4 x float>
@@ -182,7 +182,7 @@ define <2 x double> @test_pmin_v2f64_olt(<2 x double> %x, <2 x double> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp olt <2 x double> %y, %x
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -195,7 +195,7 @@ define <2 x double> @test_pmin_v2f64_ole(<2 x double> %x, <2 x double> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp ole <2 x double> %y, %x
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -208,7 +208,7 @@ define <2 x double> @test_pmin_v2f64_ogt(<2 x double> %x, <2 x double> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp ogt <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -221,7 +221,7 @@ define <2 x double> @test_pmin_v2f64_oge(<2 x double> %x, <2 x double> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp oge <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -249,7 +249,7 @@ define <2 x double> @test_pmin_v2f64_fast_ole(<2 x double> %x, <2 x double> %y)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp fast ole <2 x double> %y, %x
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -277,7 +277,7 @@ define <2 x double> @test_pmin_v2f64_fast_oge(<2 x double> %x, <2 x double> %y)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
%c = fcmp fast oge <2 x double> %x, %y
%a = select <2 x i1> %c, <2 x double> %y, <2 x double> %x
@@ -290,7 +290,7 @@ define <2 x i64> @test_pmin_int_v2f64(<2 x i64> %x, <2 x i64> %y) {
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: f64x2.pmin
+; CHECK-NEXT: f64x2.relaxed_min
; CHECK-NEXT: # fallthrough-return
%fx = bitcast <2 x i64> %x to <2 x double>
%fy = bitcast <2 x i64> %y to <2 x double>
>From 7bbc917717659162c53b6e867bcd7bab8e40ddcd Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Wed, 22 Oct 2025 03:00:09 -0700
Subject: [PATCH 8/8] Refactor pmin max int patterns
---
.../WebAssembly/WebAssemblyInstrSIMD.td | 39 ++++++++-----------
1 file changed, 16 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index 156ac44f119a6..8d0958922c3d7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -1315,22 +1315,25 @@ def pmax : PatFrags<(ops node:$lhs, node:$rhs), [
]>;
defm PMAX : SIMDBinaryFP<pmax, "pmax", 235>;
+multiclass PMinMaxInt<Vec vec, NI baseMinInst, NI baseMaxInst> {
+ def : Pat<(vec.int_vt (vselect
+ (setolt (vec.vt (bitconvert V128:$rhs)),
+ (vec.vt (bitconvert V128:$lhs))),
+ V128:$rhs, V128:$lhs)),
+ (baseMinInst $lhs, $rhs)>;
+ def : Pat<(vec.int_vt (vselect
+ (setolt (vec.vt (bitconvert V128:$lhs)),
+ (vec.vt (bitconvert V128:$rhs))),
+ V128:$rhs, V128:$lhs)),
+ (baseMaxInst $lhs, $rhs)>;
+}
// Also match the pmin/pmax cases where the operands are int vectors (but the
// comparison is still a floating point comparison). This can happen when using
// the wasm_simd128.h intrinsics because v128_t is an integer vector.
foreach vec = [F32x4, F64x2, F16x8] in {
-defvar pmin = !cast<NI>("PMIN_"#vec);
-defvar pmax = !cast<NI>("PMAX_"#vec);
-def : Pat<(vec.int_vt (vselect
- (setolt (vec.vt (bitconvert V128:$rhs)),
- (vec.vt (bitconvert V128:$lhs))),
- V128:$rhs, V128:$lhs)),
- (pmin $lhs, $rhs)>;
-def : Pat<(vec.int_vt (vselect
- (setolt (vec.vt (bitconvert V128:$lhs)),
- (vec.vt (bitconvert V128:$rhs))),
- V128:$rhs, V128:$lhs)),
- (pmax $lhs, $rhs)>;
+ defvar pmin = !cast<NI>("PMIN_"#vec);
+ defvar pmax = !cast<NI>("PMAX_"#vec);
+ defm : PMinMaxInt<vec, pmin, pmax>;
}
// And match the pmin/pmax LLVM intrinsics as well
@@ -1713,17 +1716,7 @@ let Predicates = [HasRelaxedSIMD] in {
(relaxed_min $lhs, $rhs)>;
def : Pat<(vec.vt (pmax (vec.vt V128:$lhs), (vec.vt V128:$rhs))),
(relaxed_max $lhs, $rhs)>;
-
- def : Pat<(vec.int_vt (vselect
- (setolt (vec.vt (bitconvert V128:$rhs)),
- (vec.vt (bitconvert V128:$lhs))),
- V128:$rhs, V128:$lhs)),
- (relaxed_min $lhs, $rhs)>;
- def : Pat<(vec.int_vt (vselect
- (setolt (vec.vt (bitconvert V128:$lhs)),
- (vec.vt (bitconvert V128:$rhs))),
- V128:$rhs, V128:$lhs)),
- (relaxed_max $lhs, $rhs)>;
+ defm : PMinMaxInt<vec, relaxed_min, relaxed_max>;
}
}
}
More information about the llvm-commits
mailing list