[clang] [CIR] Implement elementwise min/max/minimum/maximum/minnum/maxnum/etc (PR #222481)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 11 20:50:53 PDT 2026
https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/222481
>From 4627e43498e3ec9f082ee48029109653823fa822 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Wed, 9 Sep 2026 15:52:43 -0700
Subject: [PATCH 1/5] [CIR] Implement elementwise
min/max/minimum/maximum/minnum/maxnum/etc
These ended up being simple translations to llvm intrinsics, so other
than a single small 'magic decoder ring', this is a very trivial
implementation. The tests are taken from classic-codegen with some mild
modifications (as vector types don't work in arguments yet, and we are
testing more appropriately, as those were generated check lines).
This was found in an application we're trying to build.
---
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 41 +-
.../builtin-maximumnum-minimumnum.c | 107 +++
.../CodeGenBuiltins/builtin-maxnum-minnum.c | 107 +++
.../CodeGenBuiltins/builtins-elementwise.c | 607 ++++++++++++++++++
4 files changed, 861 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
create mode 100644 clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index d4c17d3c5f24f..c2ac934c57b16 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -2096,7 +2096,46 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
case Builtin::BI__builtin_elementwise_maximum:
case Builtin::BI__builtin_elementwise_minimum:
case Builtin::BI__builtin_elementwise_maximumnum:
- case Builtin::BI__builtin_elementwise_minimumnum:
+ case Builtin::BI__builtin_elementwise_minimumnum: {
+ mlir::Location loc = getLoc(e->getExprLoc());
+ mlir::Value op0 = emitScalarExpr(e->getArg(0));
+ mlir::Value op1 = emitScalarExpr(e->getArg(1));
+
+ auto getIntrinName = [&](unsigned builtinID) {
+ switch (builtinID) {
+ case Builtin::BI__builtin_elementwise_min:
+ if (cir::isIntOrVectorOfIntType(op0.getType())) {
+ QualType ty = e->getArg(0)->getType();
+ return ty->hasSignedIntegerRepresentation() ? "smin" : "umin";
+ }
+ return "minnum";
+ case Builtin::BI__builtin_elementwise_max:
+ if (cir::isIntOrVectorOfIntType(op0.getType())) {
+ QualType ty = e->getArg(0)->getType();
+ return ty->hasSignedIntegerRepresentation() ? "smax" : "umax";
+ }
+ return "maxnum";
+ case Builtin::BI__builtin_elementwise_minnum:
+ return "minnum";
+ case Builtin::BI__builtin_elementwise_maxnum:
+ return "maxnum";
+ case Builtin::BI__builtin_elementwise_minimum:
+ return "minimum";
+ case Builtin::BI__builtin_elementwise_maximum:
+ return "maximum";
+ case Builtin::BI__builtin_elementwise_minimumnum:
+ return "minimumnum";
+ case Builtin::BI__builtin_elementwise_maximumnum:
+ return "maximumnum";
+ default:
+ llvm_unreachable("Unhandled intrin id?");
+ };
+ };
+
+ return RValue::get(
+ builder.emitIntrinsicCallOp(loc, getIntrinName(builtinIDIfNoAsmLabel),
+ op0.getType(), mlir::ValueRange{op0, op1}));
+ }
case Builtin::BI__builtin_reduce_max:
case Builtin::BI__builtin_reduce_min:
case Builtin::BI__builtin_reduce_add:
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c b/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
new file mode 100644
index 0000000000000..73f5179a73e11
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
@@ -0,0 +1,107 @@
+// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-cir -o %t.cir
+// RUN: FileCheck %s --input-file=%t.cir --check-prefix=CIR
+// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -fclangir -o %t-cir.ll
+// RUN: FileCheck %s --input-file=%t-cir.ll --check-prefix=LLVM
+// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -o %t-ogcg.ll
+// RUN: FileCheck %s --input-file=%t-ogcg.ll --check-prefix=LLVM
+
+typedef _Float16 half8 __attribute__((ext_vector_type(8)));
+typedef __bf16 bf16x8 __attribute__((ext_vector_type(8)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef long double ldouble2 __attribute__((ext_vector_type(2)));
+
+// CIR-LABEL: @_Z7pfmin16Dv8_DF16_S_(
+// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.f16>, !cir.vector<8 x !cir.f16>) -> !cir.vector<8 x !cir.f16>
+//
+// LLVM-LABEL: @_Z7pfmin16Dv8_DF16_S_(
+// LLVM: call <8 x half> @llvm.minimumnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
+//
+half8 pfmin16(half8 a, half8 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+// CIR-LABEL: @_Z8pfmin16bDv8_DF16bS_(
+// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.bf16>, !cir.vector<8 x !cir.bf16>) -> !cir.vector<8 x !cir.bf16>
+//
+// LLVM-LABEL: @_Z8pfmin16bDv8_DF16bS_(
+// LLVM: call <8 x bfloat> @llvm.minimumnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
+//
+bf16x8 pfmin16b(bf16x8 a, bf16x8 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmin32Dv4_fS_(
+// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+//
+// LLVM-LABEL: @_Z7pfmin32Dv4_fS_(
+// LLVM: call <4 x float> @llvm.minimumnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+//
+float4 pfmin32(float4 a, float4 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmin64Dv2_dS_(
+// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
+//
+// LLVM-LABEL: @_Z7pfmin64Dv2_dS_(
+// LLVM: call <2 x double> @llvm.minimumnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+//
+double2 pfmin64(double2 a, double2 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmin80v(
+// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.long_double<!cir.f80>>, !cir.vector<2 x !cir.long_double<!cir.f80>>) -> !cir.vector<2 x !cir.long_double<!cir.f80>>
+//
+// LLVM-LABEL: @_Z7pfmin80v(
+// LLVM: call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
+//
+void pfmin80() {
+ ldouble2 a, b;
+ ldouble2 c = __builtin_elementwise_minimumnum(a, b);
+}
+
+// CIR-LABEL: @_Z7pfmax16Dv8_DF16_S_(
+// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.f16>, !cir.vector<8 x !cir.f16>) -> !cir.vector<8 x !cir.f16>
+//
+// LLVM-LABEL: @_Z7pfmax16Dv8_DF16_S_(
+// LLVM: call <8 x half> @llvm.maximumnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
+//
+half8 pfmax16(half8 a, half8 b) {
+ return __builtin_elementwise_maximumnum(a, b);
+}
+// CIR-LABEL: @_Z8pfmax16bDv8_DF16bS_(
+// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.bf16>, !cir.vector<8 x !cir.bf16>) -> !cir.vector<8 x !cir.bf16>
+//
+// LLVM-LABEL: @_Z8pfmax16bDv8_DF16bS_(
+// LLVM: call <8 x bfloat> @llvm.maximumnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
+//
+bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
+ return __builtin_elementwise_maximumnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmax32Dv4_fS_(
+// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float> loc(#loc93)
+//
+// LLVM-LABEL: @_Z7pfmax32Dv4_fS_(
+// LLVM: call <4 x float> @llvm.maximumnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+//
+float4 pfmax32(float4 a, float4 b) {
+ return __builtin_elementwise_maximumnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmax64Dv2_dS_(
+// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
+//
+// LLVM-LABEL: @_Z7pfmax64Dv2_dS_(
+// LLVM: call <2 x double> @llvm.maximumnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+//
+double2 pfmax64(double2 a, double2 b) {
+ return __builtin_elementwise_maximumnum(a, b);
+}
+
+// CIR-LABEL: @_Z7pfmax80v(
+// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.long_double<!cir.f80>>, !cir.vector<2 x !cir.long_double<!cir.f80>>) -> !cir.vector<2 x !cir.long_double<!cir.f80>>
+//
+// LLVM-LABEL: @_Z7pfmax80v(
+// LLVM: call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
+//
+void pfmax80() {
+ ldouble2 a, b;
+ ldouble2 c = __builtin_elementwise_minimumnum(a, b);
+}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c b/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
new file mode 100644
index 0000000000000..2050a2324e2dc
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
@@ -0,0 +1,107 @@
+// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-cir -o %t.cir
+// RUN: FileCheck %s --input-file=%t.cir --check-prefix=CIR
+// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -fclangir -o %t-cir.ll
+// RUN: FileCheck %s --input-file=%t-cir.ll --check-prefix=LLVM
+// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -o %t-ogcg.ll
+// RUN: FileCheck %s --input-file=%t-ogcg.ll --check-prefix=LLVM
+
+typedef _Float16 half8 __attribute__((ext_vector_type(8)));
+typedef __bf16 bf16x8 __attribute__((ext_vector_type(8)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef long double ldouble2 __attribute__((ext_vector_type(2)));
+
+// CIR-LABEL: @_Z7pfmin16Dv8_DF16_S_(
+// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.f16>, !cir.vector<8 x !cir.f16>) -> !cir.vector<8 x !cir.f16>
+//
+// LLVM-LABEL: @_Z7pfmin16Dv8_DF16_S_(
+// LLVM: call <8 x half> @llvm.minnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
+//
+half8 pfmin16(half8 a, half8 b) {
+ return __builtin_elementwise_minnum(a, b);
+}
+// CIR-LABEL: @_Z8pfmin16bDv8_DF16bS_(
+// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.bf16>, !cir.vector<8 x !cir.bf16>) -> !cir.vector<8 x !cir.bf16>
+//
+// LLVM-LABEL: @_Z8pfmin16bDv8_DF16bS_(
+// LLVM: call <8 x bfloat> @llvm.minnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
+//
+bf16x8 pfmin16b(bf16x8 a, bf16x8 b) {
+ return __builtin_elementwise_minnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmin32Dv4_fS_(
+// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+//
+// LLVM-LABEL: @_Z7pfmin32Dv4_fS_(
+// LLVM: call <4 x float> @llvm.minnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+//
+float4 pfmin32(float4 a, float4 b) {
+ return __builtin_elementwise_minnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmin64Dv2_dS_(
+// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
+//
+// LLVM-LABEL: @_Z7pfmin64Dv2_dS_(
+// LLVM: call <2 x double> @llvm.minnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+//
+double2 pfmin64(double2 a, double2 b) {
+ return __builtin_elementwise_minnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmin80v(
+// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.long_double<!cir.f80>>, !cir.vector<2 x !cir.long_double<!cir.f80>>) -> !cir.vector<2 x !cir.long_double<!cir.f80>>
+//
+// LLVM-LABEL: @_Z7pfmin80v(
+// LLVM: call <2 x x86_fp80> @llvm.minnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
+//
+void pfmin80() {
+ ldouble2 a, b;
+ ldouble2 c = __builtin_elementwise_minnum(a, b);
+}
+
+// CIR-LABEL: @_Z7pfmax16Dv8_DF16_S_(
+// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.f16>, !cir.vector<8 x !cir.f16>) -> !cir.vector<8 x !cir.f16>
+//
+// LLVM-LABEL: @_Z7pfmax16Dv8_DF16_S_(
+// LLVM: call <8 x half> @llvm.maxnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
+//
+half8 pfmax16(half8 a, half8 b) {
+ return __builtin_elementwise_maxnum(a, b);
+}
+// CIR-LABEL: @_Z8pfmax16bDv8_DF16bS_(
+// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.bf16>, !cir.vector<8 x !cir.bf16>) -> !cir.vector<8 x !cir.bf16>
+//
+// LLVM-LABEL: @_Z8pfmax16bDv8_DF16bS_(
+// LLVM: call <8 x bfloat> @llvm.maxnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
+//
+bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
+ return __builtin_elementwise_maxnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmax32Dv4_fS_(
+// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float> loc(#loc93)
+//
+// LLVM-LABEL: @_Z7pfmax32Dv4_fS_(
+// LLVM: call <4 x float> @llvm.maxnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+//
+float4 pfmax32(float4 a, float4 b) {
+ return __builtin_elementwise_maxnum(a, b);
+}
+// CIR-LABEL: @_Z7pfmax64Dv2_dS_(
+// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
+//
+// LLVM-LABEL: @_Z7pfmax64Dv2_dS_(
+// LLVM: call <2 x double> @llvm.maxnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+//
+double2 pfmax64(double2 a, double2 b) {
+ return __builtin_elementwise_maxnum(a, b);
+}
+
+// CIR-LABEL: @_Z7pfmax80v(
+// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.long_double<!cir.f80>>, !cir.vector<2 x !cir.long_double<!cir.f80>>) -> !cir.vector<2 x !cir.long_double<!cir.f80>>
+//
+// LLVM-LABEL: @_Z7pfmax80v(
+// LLVM: call <2 x x86_fp80> @llvm.minnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
+//
+void pfmax80() {
+ ldouble2 a, b;
+ ldouble2 c = __builtin_elementwise_minnum(a, b);
+}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
index f89c9278c082d..56a0f8626cb76 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
@@ -737,3 +737,610 @@ vfloat4 test_builtin_elementwise_fma(vfloat4 a, vfloat4 b, vfloat4 c) {
// LLVM: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
return __builtin_elementwise_fma(a, b, c);
}
+
+typedef _Float16 half;
+typedef half half2 __attribute__((ext_vector_type(2)));
+typedef float float2 __attribute__((ext_vector_type(2)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef short int si8 __attribute__((ext_vector_type(8)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef unsigned int u4 __attribute__((ext_vector_type(4)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef double double3 __attribute__((ext_vector_type(3)));
+__attribute__((address_space(1))) int int_as_one;
+typedef int bar;
+bar b;
+
+void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
+ float4 vf1, float4 vf2, long long int i1,
+ long long int i2, si8 vi1, si8 vi2,
+ unsigned u1, unsigned u2, u4 vu1, u4 vu2,
+ _BitInt(31) bi1, _BitInt(31) bi2,
+ unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {
+ // CIR-LABEL: @test_builtin_elementwise_min
+ // LLVM-LABEL: @test_builtin_elementwise_min(
+
+ // CIR: %[[F1:.*]] = cir.alloca "f1" align(4) init : !cir.ptr<!cir.float>
+ // CIR: %[[F2:.*]] = cir.alloca "f2" align(4) init : !cir.ptr<!cir.float>
+ // CIR: %[[D1:.*]] = cir.alloca "d1" align(8) init : !cir.ptr<!cir.double>
+ // CIR: %[[D2:.*]] = cir.alloca "d2" align(8) init : !cir.ptr<!cir.double>
+ // CIR: %[[VF1:.*]] = cir.alloca "vf1" align(16) init : !cir.ptr<!cir.vector<4 x !cir.float>>
+ // CIR: %[[VF2:.*]] = cir.alloca "vf2" align(16) init : !cir.ptr<!cir.vector<4 x !cir.float>>
+ // CIR: %[[I1:.*]] = cir.alloca "i1" align(8) init : !cir.ptr<!s64i>
+ // CIR: %[[I2:.*]] = cir.alloca "i2" align(8) init : !cir.ptr<!s64i>
+ // CIR: %[[VI1:.*]] = cir.alloca "vi1" align(16) init : !cir.ptr<!cir.vector<8 x !s16i>>
+ // CIR: %[[VI2:.*]] = cir.alloca "vi2" align(16) init : !cir.ptr<!cir.vector<8 x !s16i>>
+ // CIR: %[[U1:.*]] = cir.alloca "u1" align(4) init : !cir.ptr<!u32i>
+ // CIR: %[[U2:.*]] = cir.alloca "u2" align(4) init : !cir.ptr<!u32i>
+ // CIR: %[[VU1:.*]] = cir.alloca "vu1" align(16) init : !cir.ptr<!cir.vector<4 x !u32i>>
+ // CIR: %[[VU2:.*]] = cir.alloca "vu2" align(16) init : !cir.ptr<!cir.vector<4 x !u32i>>
+ // CIR: %[[BI1:.*]] = cir.alloca "bi1" align(4) init : !cir.ptr<!cir.int<s, 31, bitint>>
+ // CIR: %[[BI2:.*]] = cir.alloca "bi2" align(4) init : !cir.ptr<!cir.int<s, 31, bitint>>
+ // CIR: %[[BU1:.*]] = cir.alloca "bu1" align(8) init : !cir.ptr<!cir.int<u, 55, bitint>>
+ // CIR: %[[BU2:.*]] = cir.alloca "bu2" align(8) init : !cir.ptr<!cir.int<u, 55, bitint>>
+ // CIR: %[[CVF1:.*]] = cir.alloca "cvf1" align(16) init const : !cir.ptr<!cir.vector<4 x !cir.float>>
+
+ // LLVM: %[[ADDR_F1:.*]] = alloca float, align 4
+ // LLVM: %[[ADDR_F2:.*]] = alloca float, align 4
+ // LLVM: %[[ADDR_D1:.*]] = alloca double, align 8
+ // LLVM: %[[ADDR_D2:.*]] = alloca double, align 8
+ // LLVM: %[[ADDR_VF1:.*]] = alloca <4 x float>, align 16
+ // LLVM: %[[ADDR_VF2:.*]] = alloca <4 x float>, align 16
+ // LLVM: %[[ADDR_I1:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_I2:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_VI1:.*]] = alloca <8 x i16>, align 16
+ // LLVM: %[[ADDR_VI2:.*]] = alloca <8 x i16>, align 16
+ // LLVM: %[[ADDR_U1:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_U2:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_VU1:.*]] = alloca <4 x i32>, align 16
+ // LLVM: %[[ADDR_VU2:.*]] = alloca <4 x i32>, align 16
+ // LLVM: %[[ADDR_BI1:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_BI2:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_BU1:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_BU2:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_CVF1:.*]] = alloca <4 x float>, align 16
+
+ // CIR: %[[F1_LOAD:.*]] = cir.load align(4) %[[F1]] : !cir.ptr<!cir.float>, !cir.float
+ // CIR-NEXT: %[[F2_LOAD:.*]] = cir.load align(4) %[[F2]] : !cir.ptr<!cir.float>, !cir.float
+ // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[F1_LOAD]], %[[F2_LOAD]] : (!cir.float, !cir.float) -> !cir.float
+
+ // LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
+ // LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
+ // LLVM-NEXT: call float @llvm.minnum.f32(float [[F1]], float [[F2]])
+ f1 = __builtin_elementwise_min(f1, f2);
+
+ // CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[D1_LOAD]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+
+ // LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
+ // LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
+ // LLVM-NEXT: call double @llvm.minnum.f64(double [[D1]], double [[D2]])
+ d1 = __builtin_elementwise_min(d1, d2);
+
+ // CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: %[[TWO:.*]] = cir.const #cir.fp<2.000000e+00> : !cir.double
+ // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[D1_LOAD]], %[[TWO]] : (!cir.double, !cir.double) -> !cir.double
+
+ // LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
+ // LLVM-NEXT: call double @llvm.minnum.f64(double [[D1]], double 2.000000e+00)
+ d1 = __builtin_elementwise_min(d1, 2.0);
+
+ // CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[VF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
+ // LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
+ vf1 = __builtin_elementwise_min(vf1, vf2);
+
+ // CIR: %[[I1_LOAD:.*]] = cir.load align(8) %[[I1]] : !cir.ptr<!s64i>, !s64i
+ // CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
+ // CIR-NEXT: cir.call_llvm_intrinsic "smin" %31, %32 : (!s64i, !s64i) -> !s64i
+
+ // LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
+ // LLVM-NEXT: [[I2:%.+]] = load i64, ptr %[[ADDR_I2]], align 8
+ // LLVM-NEXT: call i64 @llvm.smin.i64(i64 [[I1]], i64 [[I2]])
+ i1 = __builtin_elementwise_min(i1, i2);
+
+ // CIR: %[[NEG_11:.*]] = cir.const #cir.int<-11> : !s64i
+ // CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
+ // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[NEG_11]], %[[I2_LOAD]] : (!s64i, !s64i) -> !s64i
+
+ // LLVM: [[I2:%.+]] = load i64, ptr %[[ADDR_I2]], align 8
+ // LLVM-NEXT: call i64 @llvm.smin.i64(i64 -11, i64 [[I2]])
+ i1 = __builtin_elementwise_min(-11ll, i2);
+
+ // CIR: %[[I1_LOAD:.*]] = cir.load align(8) %[[I1]] : !cir.ptr<!s64i>, !s64i
+ // CIR-NEXT: %[[I1_TRUNC:.*]] = cir.cast integral %[[I1_LOAD]] : !s64i -> !s16i
+ // CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
+ // CIR-NEXT: %[[I2_TRUNC:.*]] = cir.cast integral %[[I2_LOAD]] : !s64i -> !s16i
+ // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[I1_TRUNC]], %[[I2_TRUNC]] : (!s16i, !s16i) -> !s16i
+
+ // LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
+ // LLVM: [[S1:%.+]] = trunc i64 [[I1]] to i16
+ // LLVM-NEXT: [[I2:%.+]] = load i64, ptr %[[ADDR_I2]], align 8
+ // LLVM: [[S2:%.+]] = trunc i64 [[I2]] to i16
+ // LLVM-NEXT: call i16 @llvm.smin.i16(i16 [[S1]], i16 [[S2]])
+ i1 = __builtin_elementwise_min((short)i1, (short)i2);
+
+ // CIR: %[[VI1_LOAD:.*]] = cir.load align(16) %[[VI1]] : !cir.ptr<!cir.vector<8 x !s16i>>, !cir.vector<8 x !s16i>
+ // CIR-NEXT: %[[VI2_LOAD:.*]] = cir.load align(16) %[[VI2]] : !cir.ptr<!cir.vector<8 x !s16i>>, !cir.vector<8 x !s16i>
+ // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[VI1_LOAD]], %[[VI2_LOAD]] : (!cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+ // LLVM: [[VI1:%.+]] = load <8 x i16>, ptr %[[ADDR_VI1]], align 16
+ // LLVM-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %[[ADDR_VI2]], align 16
+ // LLVM-NEXT: call <8 x i16> @llvm.smin.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]])
+ vi1 = __builtin_elementwise_min(vi1, vi2);
+
+ // CIR: %[[U1_LOAD:.*]] = cir.load align(4) %[[U1]] : !cir.ptr<!u32i>, !u32i
+ // CIR-NEXT: %[[U2_LOAD:.*]] = cir.load align(4) %[[U2]] : !cir.ptr<!u32i>, !u32i
+ // CIR-NEXT: cir.call_llvm_intrinsic "umin" %[[U1_LOAD]], %[[U2_LOAD]] : (!u32i, !u32i) -> !u32i
+
+ // LLVM: [[U1:%.+]] = load i32, ptr %[[ADDR_U1]], align 4
+ // LLVM-NEXT: [[U2:%.+]] = load i32, ptr %[[ADDR_U2]], align 4
+ // LLVM-NEXT: call i32 @llvm.umin.i32(i32 [[U1]], i32 [[U2]])
+ u1 = __builtin_elementwise_min(u1, u2);
+
+ // CIR: %[[VU1_LOAD:.*]] = cir.load align(16) %[[VU1]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
+ // CIR-NEXT: %[[VU2_LOAD:.*]] = cir.load align(16) %[[VU2]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
+ // CIR-NEXT: cir.call_llvm_intrinsic "umin" %[[VU1_LOAD]], %[[VU2_LOAD]] : (!cir.vector<4 x !u32i>, !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
+
+ // LLVM: [[VU1:%.+]] = load <4 x i32>, ptr %[[ADDR_VU1]], align 16
+ // LLVM-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %[[ADDR_VU2]], align 16
+ // LLVM-NEXT: call <4 x i32> @llvm.umin.v4i32(<4 x i32> [[VU1]], <4 x i32> [[VU2]])
+ vu1 = __builtin_elementwise_min(vu1, vu2);
+
+ // CIR: %[[BI1_LOAD:.*]] = cir.load align(4) %[[BI1]] : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint>
+ // CIR-NEXT: %[[BI2_LOAD:.*]] = cir.load align(4) %[[BI2]] : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint>
+ // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[BI1_LOAD]], %[[BI2_LOAD]] : (!cir.int<s, 31, bitint>, !cir.int<s, 31, bitint>) -> !cir.int<s, 31, bitint>
+
+ // LLVM: [[BI1:%.+]] = load i32, ptr %[[ADDR_BI1]], align 4
+ // LLVM-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31
+ // LLVM-NEXT: [[BI2:%.+]] = load i32, ptr %[[ADDR_BI2]], align 4
+ // LLVM-NEXT: [[LOADEDV1:%.+]] = trunc i32 [[BI2]] to i31
+ // LLVM-NEXT: call i31 @llvm.smin.i31(i31 [[LOADEDV]], i31 [[LOADEDV1]])
+ bi1 = __builtin_elementwise_min(bi1, bi2);
+
+ // CIR: %[[BU1_LOAD:.*]] = cir.load align(8) %[[BU1]] : !cir.ptr<!cir.int<u, 55, bitint>>, !cir.int<u, 55, bitint>
+ // CIR-NEXT: %[[BU2_LOAD:.*]] = cir.load align(8) %[[BU2]] : !cir.ptr<!cir.int<u, 55, bitint>>, !cir.int<u, 55, bitint>
+ // CIR-NEXT: cir.call_llvm_intrinsic "umin" %[[BU1_LOAD]], %[[BU2_LOAD]] : (!cir.int<u, 55, bitint>, !cir.int<u, 55, bitint>) -> !cir.int<u, 55, bitint>
+
+ // LLVM: [[BU1:%.+]] = load i64, ptr %[[ADDR_BU1]], align 8
+ // LLVM-NEXT: [[LOADEDV2:%.+]] = trunc i64 [[BU1]] to i55
+ // LLVM-NEXT: [[BU2:%.+]] = load i64, ptr %[[ADDR_BU2]], align 8
+ // LLVM-NEXT: [[LOADEDV3:%.+]] = trunc i64 [[BU2]] to i55
+ // LLVM-NEXT: call i55 @llvm.umin.i55(i55 [[LOADEDV2]], i55 [[LOADEDV3]])
+ bu1 = __builtin_elementwise_min(bu1, bu2);
+
+ // CIR: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[CVF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
+ // LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
+ const float4 cvf1 = vf1;
+ vf1 = __builtin_elementwise_min(cvf1, vf2);
+
+ // CIR: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[VF2_LOAD]], %[[CVF1_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
+ vf1 = __builtin_elementwise_min(vf2, cvf1);
+
+ // CIR: %[[IAONE:.*]] = cir.get_global @int_as_one : !cir.ptr<!s32i, target_address_space(1)>
+ // CIR-NEXT: %[[IAO_LOAD:.*]] = cir.load align(4) %[[IAONE]] : !cir.ptr<!s32i, target_address_space(1)>, !s32i
+ // CIR-NEXT: %[[B:.*]] = cir.get_global @b : !cir.ptr<!s32i>
+ // CIR-NEXT: %[[B_LOAD:.*]] = cir.load align(4) %[[B]] : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[IAO_LOAD]], %[[B_LOAD]] : (!s32i, !s32i) -> !s32i
+
+ // LLVM: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4
+ // LLVM-NEXT: [[B:%.+]] = load i32, ptr @b, align 4
+ // LLVM-NEXT: call i32 @llvm.smin.i32(i32 [[IAS1]], i32 [[B]])
+ int_as_one = __builtin_elementwise_min(int_as_one, b);
+
+ // CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i
+ // CIR-NEXT: cir.store align(8) %[[TWO]], %[[I1]] : !s64i, !cir.ptr<!s64i>
+
+ // LLVM: store i64 2, ptr [[I1:%.+]], align 8
+ i1 = __builtin_elementwise_min(2, 'b');
+}
+
+void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,
+ float4 vf1, float4 vf2, long long int i1,
+ long long int i2, si8 vi1, si8 vi2,
+ unsigned u1, unsigned u2, u4 vu1, u4 vu2,
+ _BitInt(31) bi1, _BitInt(31) bi2,
+ unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {
+ // CIR-LABEL: @test_builtin_elementwise_minimum(
+ // LLVM-LABEL: @test_builtin_elementwise_minimum(
+
+ // CIR-NEXT: %[[F1:.*]] = cir.alloca "f1" align(4) init : !cir.ptr<!cir.float>
+ // CIR-NEXT: %[[F2:.*]] = cir.alloca "f2" align(4) init : !cir.ptr<!cir.float>
+ // CIR-NEXT: %[[D1:.*]] = cir.alloca "d1" align(8) init : !cir.ptr<!cir.double>
+ // CIR-NEXT: %[[D2:.*]] = cir.alloca "d2" align(8) init : !cir.ptr<!cir.double>
+ // CIR-NEXT: %[[VF1:.*]] = cir.alloca "vf1" align(16) init : !cir.ptr<!cir.vector<4 x !cir.float>>
+ // CIR-NEXT: %[[VF2:.*]] = cir.alloca "vf2" align(16) init : !cir.ptr<!cir.vector<4 x !cir.float>>
+ // CIR-NEXT: %[[I1:.*]] = cir.alloca "i1" align(8) init : !cir.ptr<!s64i>
+ // CIR-NEXT: %[[I1:.*]] = cir.alloca "i2" align(8) init : !cir.ptr<!s64i>
+ // CIR-NEXT: %[[VI1:.*]] = cir.alloca "vi1" align(16) init : !cir.ptr<!cir.vector<8 x !s16i>>
+ // CIR-NEXT: %[[VI2:.*]] = cir.alloca "vi2" align(16) init : !cir.ptr<!cir.vector<8 x !s16i>>
+ // CIR-NEXT: %[[U1:.*]] = cir.alloca "u1" align(4) init : !cir.ptr<!u32i>
+ // CIR-NEXT: %[[U2:.*]] = cir.alloca "u2" align(4) init : !cir.ptr<!u32i>
+ // CIR-NEXT: %[[VU1:.*]] = cir.alloca "vu1" align(16) init : !cir.ptr<!cir.vector<4 x !u32i>>
+ // CIR-NEXT: %[[VU2:.*]] = cir.alloca "vu2" align(16) init : !cir.ptr<!cir.vector<4 x !u32i>>
+ // CIR-NEXT: %[[BI1:.*]] = cir.alloca "bi1" align(4) init : !cir.ptr<!cir.int<s, 31, bitint>>
+ // CIR-NEXT: %[[BI2:.*]] = cir.alloca "bi2" align(4) init : !cir.ptr<!cir.int<s, 31, bitint>>
+ // CIR-NEXT: %[[BU1:.*]] = cir.alloca "bu1" align(8) init : !cir.ptr<!cir.int<u, 55, bitint>>
+ // CIR-NEXT: %[[BU1:.*]] = cir.alloca "bu2" align(8) init : !cir.ptr<!cir.int<u, 55, bitint>>
+ // CIR-NEXT: %[[CVF1:.*]] = cir.alloca "cvf1" align(16) init const : !cir.ptr<!cir.vector<4 x !cir.float>>
+
+ // LLVM: %[[ADDR_F1:.*]] = alloca float, align 4
+ // LLVM: %[[ADDR_F2:.*]] = alloca float, align 4
+ // LLVM: %[[ADDR_D1:.*]] = alloca double, align 8
+ // LLVM: %[[ADDR_D2:.*]] = alloca double, align 8
+ // LLVM: %[[ADDR_VF1:.*]] = alloca <4 x float>, align 16
+ // LLVM: %[[ADDR_VF2:.*]] = alloca <4 x float>, align 16
+ // LLVM: %[[ADDR_I1:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_I2:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_VI1:.*]] = alloca <8 x i16>, align 16
+ // LLVM: %[[ADDR_VI2:.*]] = alloca <8 x i16>, align 16
+ // LLVM: %[[ADDR_U1:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_U2:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_VU1:.*]] = alloca <4 x i32>, align 16
+ // LLVM: %[[ADDR_VU2:.*]] = alloca <4 x i32>, align 16
+ // LLVM: %[[ADDR_BI1:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_BI2:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_BU1:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_BU2:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_CVF1:.*]] = alloca <4 x float>, align 16
+
+ // CIR: %[[F1_LOAD:.*]] = cir.load align(4) %[[F1]] : !cir.ptr<!cir.float>, !cir.float
+ // CIR-NEXT: %[[F2_LOAD:.*]] = cir.load align(4) %[[F2]] : !cir.ptr<!cir.float>, !cir.float
+ // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[F1_LOAD]], %[[F2_LOAD]] : (!cir.float, !cir.float) -> !cir.float
+
+ // LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
+ // LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
+ // LLVM-NEXT: call float @llvm.minimum.f32(float [[F1]], float [[F2]])
+ f1 = __builtin_elementwise_minimum(f1, f2);
+
+ // CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[D1_LOAD]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+
+ // LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
+ // LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
+ // LLVM-NEXT: call double @llvm.minimum.f64(double [[D1]], double [[D2]])
+ d1 = __builtin_elementwise_minimum(d1, d2);
+
+ // CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: %[[TWO:.*]] = cir.const #cir.fp<2.000000e+00> : !cir.double
+ // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[D1_LOAD]], %[[TWO]] : (!cir.double, !cir.double) -> !cir.double
+
+ // LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
+ // LLVM-NEXT: call double @llvm.minimum.f64(double [[D1]], double 2.000000e+00)
+ d1 = __builtin_elementwise_minimum(d1, 2.0);
+
+ // CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[VF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
+ // LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
+ vf1 = __builtin_elementwise_minimum(vf1, vf2);
+
+ // CIR: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[CVF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
+ // LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
+ const float4 cvf1 = vf1;
+ vf1 = __builtin_elementwise_minimum(cvf1, vf2);
+
+ // CIR: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[VF2_LOAD]], %[[CVF1_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
+ vf1 = __builtin_elementwise_minimum(vf2, cvf1);
+}
+
+void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
+ float4 vf1, float4 vf2, long long int i1,
+ long long int i2, si8 vi1, si8 vi2,
+ unsigned u1, unsigned u2, u4 vu1, u4 vu2,
+ _BitInt(31) bi1, _BitInt(31) bi2,
+ unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {
+ // CIR-LABEL: @test_builtin_elementwise_max
+ // LLVM-LABEL: @test_builtin_elementwise_max(
+
+ // CIR: %[[F1:.*]] = cir.alloca "f1" align(4) init : !cir.ptr<!cir.float>
+ // CIR: %[[F2:.*]] = cir.alloca "f2" align(4) init : !cir.ptr<!cir.float>
+ // CIR: %[[D1:.*]] = cir.alloca "d1" align(8) init : !cir.ptr<!cir.double>
+ // CIR: %[[D2:.*]] = cir.alloca "d2" align(8) init : !cir.ptr<!cir.double>
+ // CIR: %[[VF1:.*]] = cir.alloca "vf1" align(16) init : !cir.ptr<!cir.vector<4 x !cir.float>>
+ // CIR: %[[VF2:.*]] = cir.alloca "vf2" align(16) init : !cir.ptr<!cir.vector<4 x !cir.float>>
+ // CIR: %[[I1:.*]] = cir.alloca "i1" align(8) init : !cir.ptr<!s64i>
+ // CIR: %[[I2:.*]] = cir.alloca "i2" align(8) init : !cir.ptr<!s64i>
+ // CIR: %[[VI1:.*]] = cir.alloca "vi1" align(16) init : !cir.ptr<!cir.vector<8 x !s16i>>
+ // CIR: %[[VI2:.*]] = cir.alloca "vi2" align(16) init : !cir.ptr<!cir.vector<8 x !s16i>>
+ // CIR: %[[U1:.*]] = cir.alloca "u1" align(4) init : !cir.ptr<!u32i>
+ // CIR: %[[U2:.*]] = cir.alloca "u2" align(4) init : !cir.ptr<!u32i>
+ // CIR: %[[VU1:.*]] = cir.alloca "vu1" align(16) init : !cir.ptr<!cir.vector<4 x !u32i>>
+ // CIR: %[[VU2:.*]] = cir.alloca "vu2" align(16) init : !cir.ptr<!cir.vector<4 x !u32i>>
+ // CIR: %[[BI1:.*]] = cir.alloca "bi1" align(4) init : !cir.ptr<!cir.int<s, 31, bitint>>
+ // CIR: %[[BI2:.*]] = cir.alloca "bi2" align(4) init : !cir.ptr<!cir.int<s, 31, bitint>>
+ // CIR: %[[BU1:.*]] = cir.alloca "bu1" align(8) init : !cir.ptr<!cir.int<u, 55, bitint>>
+ // CIR: %[[BU2:.*]] = cir.alloca "bu2" align(8) init : !cir.ptr<!cir.int<u, 55, bitint>>
+ // CIR: %[[CVF1:.*]] = cir.alloca "cvf1" align(16) init const : !cir.ptr<!cir.vector<4 x !cir.float>>
+
+ // LLVM: %[[ADDR_F1:.*]] = alloca float, align 4
+ // LLVM: %[[ADDR_F2:.*]] = alloca float, align 4
+ // LLVM: %[[ADDR_D1:.*]] = alloca double, align 8
+ // LLVM: %[[ADDR_D2:.*]] = alloca double, align 8
+ // LLVM: %[[ADDR_VF1:.*]] = alloca <4 x float>, align 16
+ // LLVM: %[[ADDR_VF2:.*]] = alloca <4 x float>, align 16
+ // LLVM: %[[ADDR_I1:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_I2:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_VI1:.*]] = alloca <8 x i16>, align 16
+ // LLVM: %[[ADDR_VI2:.*]] = alloca <8 x i16>, align 16
+ // LLVM: %[[ADDR_U1:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_U2:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_VU1:.*]] = alloca <4 x i32>, align 16
+ // LLVM: %[[ADDR_VU2:.*]] = alloca <4 x i32>, align 16
+ // LLVM: %[[ADDR_BI1:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_BI2:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_BU1:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_BU2:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_CVF1:.*]] = alloca <4 x float>, align 16
+
+ // CIR: %[[F1_LOAD:.*]] = cir.load align(4) %[[F1]] : !cir.ptr<!cir.float>, !cir.float
+ // CIR-NEXT: %[[F2_LOAD:.*]] = cir.load align(4) %[[F2]] : !cir.ptr<!cir.float>, !cir.float
+ // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[F1_LOAD]], %[[F2_LOAD]] : (!cir.float, !cir.float) -> !cir.float
+
+ // LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
+ // LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
+ // LLVM-NEXT: call float @llvm.maxnum.f32(float [[F1]], float [[F2]])
+ f1 = __builtin_elementwise_max(f1, f2);
+
+ // CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[D1_LOAD]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+
+ // LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
+ // LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
+ // LLVM-NEXT: call double @llvm.maxnum.f64(double [[D1]], double [[D2]])
+ d1 = __builtin_elementwise_max(d1, d2);
+
+ // CIR: %[[TWENTY:.*]] = cir.const #cir.fp<2.000000e+01> : !cir.double
+ // CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[TWENTY]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+
+ // LLVM: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
+ // LLVM-NEXT: call double @llvm.maxnum.f64(double 2.000000e+01, double [[D2]])
+ d1 = __builtin_elementwise_max(20.0, d2);
+
+ // CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[VF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
+ // LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
+ vf1 = __builtin_elementwise_max(vf1, vf2);
+
+ // CIR: %[[I1_LOAD:.*]] = cir.load align(8) %[[I1]] : !cir.ptr<!s64i>, !s64i
+ // CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
+ // CIR-NEXT: cir.call_llvm_intrinsic "smax" %31, %32 : (!s64i, !s64i) -> !s64i
+
+ // LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
+ // LLVM-NEXT: [[I2:%.+]] = load i64, ptr %[[ADDR_I2]], align 8
+ // LLVM-NEXT: call i64 @llvm.smax.i64(i64 [[I1]], i64 [[I2]])
+ i1 = __builtin_elementwise_max(i1, i2);
+
+ // CIR: %[[I1_LOAD:.*]] = cir.load align(8) %[[I1]] : !cir.ptr<!s64i>, !s64i
+ // CIR-NEXT: %[[TEN:.*]] = cir.const #cir.int<10> : !s64i
+ // CIR-NEXT: cir.call_llvm_intrinsic "smax" %[[I1_LOAD]], %[[TEN]] : (!s64i, !s64i) -> !s64i
+
+ // LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
+ // LLVM-NEXT: call i64 @llvm.smax.i64(i64 [[I1]], i64 10)
+ i1 = __builtin_elementwise_max(i1, 10ll);
+
+ // CIR: %[[VI1_LOAD:.*]] = cir.load align(16) %[[VI1]] : !cir.ptr<!cir.vector<8 x !s16i>>, !cir.vector<8 x !s16i>
+ // CIR-NEXT: %[[VI2_LOAD:.*]] = cir.load align(16) %[[VI2]] : !cir.ptr<!cir.vector<8 x !s16i>>, !cir.vector<8 x !s16i>
+ // CIR-NEXT: cir.call_llvm_intrinsic "smax" %[[VI1_LOAD]], %[[VI2_LOAD]] : (!cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+
+ // LLVM: [[VI1:%.+]] = load <8 x i16>, ptr %[[ADDR_VI1]], align 16
+ // LLVM-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %[[ADDR_VI2]], align 16
+ // LLVM-NEXT: call <8 x i16> @llvm.smax.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]])
+ vi1 = __builtin_elementwise_max(vi1, vi2);
+
+ // CIR: %[[U1_LOAD:.*]] = cir.load align(4) %[[U1]] : !cir.ptr<!u32i>, !u32i
+ // CIR-NEXT: %[[U2_LOAD:.*]] = cir.load align(4) %[[U2]] : !cir.ptr<!u32i>, !u32i
+ // CIR-NEXT: cir.call_llvm_intrinsic "umax" %[[U1_LOAD]], %[[U2_LOAD]] : (!u32i, !u32i) -> !u32i
+
+ // LLVM: [[U1:%.+]] = load i32, ptr %[[ADDR_U1]], align 4
+ // LLVM-NEXT: [[U2:%.+]] = load i32, ptr %[[ADDR_U2]], align 4
+ // LLVM-NEXT: call i32 @llvm.umax.i32(i32 [[U1]], i32 [[U2]])
+ u1 = __builtin_elementwise_max(u1, u2);
+
+ // CIR: %[[VU1_LOAD:.*]] = cir.load align(16) %[[VU1]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
+ // CIR-NEXT: %[[VU2_LOAD:.*]] = cir.load align(16) %[[VU2]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
+ // CIR-NEXT: cir.call_llvm_intrinsic "umax" %[[VU1_LOAD]], %[[VU2_LOAD]] : (!cir.vector<4 x !u32i>, !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
+
+ // LLVM: [[VU1:%.+]] = load <4 x i32>, ptr %[[ADDR_VU1]], align 16
+ // LLVM-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %[[ADDR_VU2]], align 16
+ // LLVM-NEXT: call <4 x i32> @llvm.umax.v4i32(<4 x i32> [[VU1]], <4 x i32> [[VU2]])
+ vu1 = __builtin_elementwise_max(vu1, vu2);
+
+ // CIR: %[[BI1_LOAD:.*]] = cir.load align(4) %[[BI1]] : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint>
+ // CIR-NEXT: %[[BI2_LOAD:.*]] = cir.load align(4) %[[BI2]] : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint>
+ // CIR-NEXT: cir.call_llvm_intrinsic "smax" %[[BI1_LOAD]], %[[BI2_LOAD]] : (!cir.int<s, 31, bitint>, !cir.int<s, 31, bitint>) -> !cir.int<s, 31, bitint>
+
+ // LLVM: [[BI1:%.+]] = load i32, ptr %[[ADDR_BI1]], align 4
+ // LLVM-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31
+ // LLVM-NEXT: [[BI2:%.+]] = load i32, ptr %[[ADDR_BI2]], align 4
+ // LLVM-NEXT: [[LOADEDV1:%.+]] = trunc i32 [[BI2]] to i31
+ // LLVM-NEXT: call i31 @llvm.smax.i31(i31 [[LOADEDV]], i31 [[LOADEDV1]])
+ bi1 = __builtin_elementwise_max(bi1, bi2);
+
+ // CIR: %[[BU1_LOAD:.*]] = cir.load align(8) %[[BU1]] : !cir.ptr<!cir.int<u, 55, bitint>>, !cir.int<u, 55, bitint>
+ // CIR-NEXT: %[[BU2_LOAD:.*]] = cir.load align(8) %[[BU2]] : !cir.ptr<!cir.int<u, 55, bitint>>, !cir.int<u, 55, bitint>
+ // CIR-NEXT: cir.call_llvm_intrinsic "umax" %[[BU1_LOAD]], %[[BU2_LOAD]] : (!cir.int<u, 55, bitint>, !cir.int<u, 55, bitint>) -> !cir.int<u, 55, bitint>
+
+ // LLVM: [[BU1:%.+]] = load i64, ptr %[[ADDR_BU1]], align 8
+ // LLVM-NEXT: [[LOADEDV2:%.+]] = trunc i64 [[BU1]] to i55
+ // LLVM-NEXT: [[BU2:%.+]] = load i64, ptr %[[ADDR_BU2]], align 8
+ // LLVM-NEXT: [[LOADEDV3:%.+]] = trunc i64 [[BU2]] to i55
+ // LLVM-NEXT: call i55 @llvm.umax.i55(i55 [[LOADEDV2]], i55 [[LOADEDV3]])
+ bu1 = __builtin_elementwise_max(bu1, bu2);
+
+ // CIR: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[CVF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
+ // LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
+ const float4 cvf1 = vf1;
+ vf1 = __builtin_elementwise_max(cvf1, vf2);
+
+ // CIR: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[VF2_LOAD]], %[[CVF1_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
+ vf1 = __builtin_elementwise_max(vf2, cvf1);
+
+ // CIR: %[[IAONE:.*]] = cir.get_global @int_as_one : !cir.ptr<!s32i, target_address_space(1)>
+ // CIR-NEXT: %[[IAO_LOAD:.*]] = cir.load align(4) %[[IAONE]] : !cir.ptr<!s32i, target_address_space(1)>, !s32i
+ // CIR-NEXT: %[[B:.*]] = cir.get_global @b : !cir.ptr<!s32i>
+ // CIR-NEXT: %[[B_LOAD:.*]] = cir.load align(4) %[[B]] : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.call_llvm_intrinsic "smax" %[[IAO_LOAD]], %[[B_LOAD]] : (!s32i, !s32i) -> !s32i
+
+ // LLVM: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4
+ // LLVM-NEXT: [[B:%.+]] = load i32, ptr @b, align 4
+ // LLVM-NEXT: call i32 @llvm.smax.i32(i32 [[IAS1]], i32 [[B]])
+ int_as_one = __builtin_elementwise_max(int_as_one, b);
+
+ // CIR: %[[A_CONST:.*]] = cir.const #cir.int<97> : !s64i
+ // CIR-NEXT: cir.store align(8) %[[A_CONST]], %[[I1]] : !s64i, !cir.ptr<!s64i>
+
+ // LLVM: store i64 97, ptr [[I1:%.+]], align 8
+ i1 = __builtin_elementwise_max(1, 'a');
+}
+
+void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,
+ float4 vf1, float4 vf2, long long int i1,
+ long long int i2, si8 vi1, si8 vi2,
+ unsigned u1, unsigned u2, u4 vu1, u4 vu2,
+ _BitInt(31) bi1, _BitInt(31) bi2,
+ unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {
+ // CIR-LABEL: test_builtin_elementwise_maximum(
+ // LLVM-LABEL: @test_builtin_elementwise_maximum(
+
+ // CIR-NEXT: %[[F1:.*]] = cir.alloca "f1" align(4) init : !cir.ptr<!cir.float>
+ // CIR-NEXT: %[[F2:.*]] = cir.alloca "f2" align(4) init : !cir.ptr<!cir.float>
+ // CIR-NEXT: %[[D1:.*]] = cir.alloca "d1" align(8) init : !cir.ptr<!cir.double>
+ // CIR-NEXT: %[[D2:.*]] = cir.alloca "d2" align(8) init : !cir.ptr<!cir.double>
+ // CIR-NEXT: %[[VF1:.*]] = cir.alloca "vf1" align(16) init : !cir.ptr<!cir.vector<4 x !cir.float>>
+ // CIR-NEXT: %[[VF2:.*]] = cir.alloca "vf2" align(16) init : !cir.ptr<!cir.vector<4 x !cir.float>>
+ // CIR-NEXT: %[[I1:.*]] = cir.alloca "i1" align(8) init : !cir.ptr<!s64i>
+ // CIR-NEXT: %[[I1:.*]] = cir.alloca "i2" align(8) init : !cir.ptr<!s64i>
+ // CIR-NEXT: %[[VI1:.*]] = cir.alloca "vi1" align(16) init : !cir.ptr<!cir.vector<8 x !s16i>>
+ // CIR-NEXT: %[[VI2:.*]] = cir.alloca "vi2" align(16) init : !cir.ptr<!cir.vector<8 x !s16i>>
+ // CIR-NEXT: %[[U1:.*]] = cir.alloca "u1" align(4) init : !cir.ptr<!u32i>
+ // CIR-NEXT: %[[U2:.*]] = cir.alloca "u2" align(4) init : !cir.ptr<!u32i>
+ // CIR-NEXT: %[[VU1:.*]] = cir.alloca "vu1" align(16) init : !cir.ptr<!cir.vector<4 x !u32i>>
+ // CIR-NEXT: %[[VU2:.*]] = cir.alloca "vu2" align(16) init : !cir.ptr<!cir.vector<4 x !u32i>>
+ // CIR-NEXT: %[[BI1:.*]] = cir.alloca "bi1" align(4) init : !cir.ptr<!cir.int<s, 31, bitint>>
+ // CIR-NEXT: %[[BI2:.*]] = cir.alloca "bi2" align(4) init : !cir.ptr<!cir.int<s, 31, bitint>>
+ // CIR-NEXT: %[[BU1:.*]] = cir.alloca "bu1" align(8) init : !cir.ptr<!cir.int<u, 55, bitint>>
+ // CIR-NEXT: %[[BU2:.*]] = cir.alloca "bu2" align(8) init : !cir.ptr<!cir.int<u, 55, bitint>>
+ // CIR-NEXT: %[[CVF1:.*]] = cir.alloca "cvf1" align(16) init const : !cir.ptr<!cir.vector<4 x !cir.float>>
+
+ // LLVM: %[[ADDR_F1:.*]] = alloca float, align 4
+ // LLVM: %[[ADDR_F2:.*]] = alloca float, align 4
+ // LLVM: %[[ADDR_D1:.*]] = alloca double, align 8
+ // LLVM: %[[ADDR_D2:.*]] = alloca double, align 8
+ // LLVM: %[[ADDR_VF1:.*]] = alloca <4 x float>, align 16
+ // LLVM: %[[ADDR_VF2:.*]] = alloca <4 x float>, align 16
+ // LLVM: %[[ADDR_I1:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_I2:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_VI1:.*]] = alloca <8 x i16>, align 16
+ // LLVM: %[[ADDR_VI2:.*]] = alloca <8 x i16>, align 16
+ // LLVM: %[[ADDR_U1:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_U2:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_VU1:.*]] = alloca <4 x i32>, align 16
+ // LLVM: %[[ADDR_VU2:.*]] = alloca <4 x i32>, align 16
+ // LLVM: %[[ADDR_BI1:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_BI2:.*]] = alloca i32, align 4
+ // LLVM: %[[ADDR_BU1:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_BU2:.*]] = alloca i64, align 8
+ // LLVM: %[[ADDR_CVF1:.*]] = alloca <4 x float>, align 16
+
+ // CIR: %[[F1_LOAD:.*]] = cir.load align(4) %[[F1]] : !cir.ptr<!cir.float>, !cir.float
+ // CIR-NEXT: %[[F2_LOAD:.*]] = cir.load align(4) %[[F2]] : !cir.ptr<!cir.float>, !cir.float
+ // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[F1_LOAD]], %[[F2_LOAD]] : (!cir.float, !cir.float) -> !cir.float
+
+ // LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
+ // LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
+ // LLVM-NEXT: call float @llvm.maximum.f32(float [[F1]], float [[F2]])
+ f1 = __builtin_elementwise_maximum(f1, f2);
+
+ // CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[D1_LOAD]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+
+ // LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
+ // LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
+ // LLVM-NEXT: call double @llvm.maximum.f64(double [[D1]], double [[D2]])
+ d1 = __builtin_elementwise_maximum(d1, d2);
+
+ // CIR: %[[TWENTY:.*]] = cir.const #cir.fp<2.000000e+01> : !cir.double
+ // CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
+ // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[TWENTY]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+
+ // LLVM: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
+ // LLVM-NEXT: call double @llvm.maximum.f64(double 2.000000e+01, double [[D2]])
+ d1 = __builtin_elementwise_maximum(20.0, d2);
+
+ // CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[VF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
+ // LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
+ vf1 = __builtin_elementwise_maximum(vf1, vf2);
+
+ // CIR: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[CVF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
+ // LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
+ const float4 cvf1 = vf1;
+ vf1 = __builtin_elementwise_maximum(cvf1, vf2);
+
+ // CIR: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[VF2_LOAD]], %[[CVF1_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+
+ // LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
+ // LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
+ // LLVM-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
+ vf1 = __builtin_elementwise_maximum(vf2, cvf1);
+}
>From 10ad435daf0158c746d6a679bafe8080bb7613db Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Sep 2026 06:48:47 -0700
Subject: [PATCH 2/5] Fix test suggestions
---
clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c | 2 +-
clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c | 2 +-
clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c b/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
index 73f5179a73e11..c13c90d77986e 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
@@ -77,7 +77,7 @@ bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
return __builtin_elementwise_maximumnum(a, b);
}
// CIR-LABEL: @_Z7pfmax32Dv4_fS_(
-// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float> loc(#loc93)
+// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
//
// LLVM-LABEL: @_Z7pfmax32Dv4_fS_(
// LLVM: call <4 x float> @llvm.maximumnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c b/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
index 2050a2324e2dc..5a05d701bc573 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
@@ -77,7 +77,7 @@ bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
return __builtin_elementwise_maxnum(a, b);
}
// CIR-LABEL: @_Z7pfmax32Dv4_fS_(
-// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float> loc(#loc93)
+// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
//
// LLVM-LABEL: @_Z7pfmax32Dv4_fS_(
// LLVM: call <4 x float> @llvm.maxnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
index 56a0f8626cb76..636a8c574e864 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
@@ -837,7 +837,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[I1_LOAD:.*]] = cir.load align(8) %[[I1]] : !cir.ptr<!s64i>, !s64i
// CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
- // CIR-NEXT: cir.call_llvm_intrinsic "smin" %31, %32 : (!s64i, !s64i) -> !s64i
+ // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[I1_LOAD]], %[[I2_LOAD]] : (!s64i, !s64i) -> !s64i
// LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
// LLVM-NEXT: [[I2:%.+]] = load i64, ptr %[[ADDR_I2]], align 8
>From de35402621d0e384304897d092b58a2b58b1e8c9 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Sep 2026 12:38:51 -0700
Subject: [PATCH 3/5] Remove minimumnum/maximumnum, switch to existing ops, add
fast math flags
---
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 26 +++++
clang/include/clang/CIR/Dialect/IR/CIROps.td | 8 +-
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 99 ++++++++--------
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 47 ++++++--
.../builtin-maximumnum-minimumnum.c | 107 ------------------
.../CodeGenBuiltins/builtin-maxnum-minnum.c | 20 ++--
.../CodeGenBuiltins/builtins-elementwise.c | 48 ++++----
.../CodeGenBuiltins/builtins-floating-point.c | 32 +++---
8 files changed, 165 insertions(+), 222 deletions(-)
delete mode 100644 clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index f263cd30eb458..8cc7b449c1bac 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -848,6 +848,32 @@ def CIR_CmpThreeWayInfoAttr : CIR_Attr<"CmpThreeWayInfo", "cmp3way_info"> {
let canHaveIllegalCXXABIType = 0;
}
+//===----------------------------------------------------------------------===//
+// FastMathFlagsAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_FMFnone : I32BitEnumAttrCaseNone<"none">;
+def CIR_FMFnsz : I32BitEnumAttrCaseBit<"nsz", 0>;
+def CIR_FMFnnan : I32BitEnumAttrCaseBit<"nnan", 1>;
+def CIR_FMFninf : I32BitEnumAttrCaseBit<"ninf", 2>;
+def CIR_FMFarcp : I32BitEnumAttrCaseBit<"arcp", 3>;
+def CIR_FMFcontract : I32BitEnumAttrCaseBit<"contract", 4>;
+def CIR_FMFafn : I32BitEnumAttrCaseBit<"afn", 5>;
+def CIR_FMFreassoc : I32BitEnumAttrCaseBit<"reassoc", 6>;
+def CIR_FMFfast : I32BitEnumAttrCaseGroup<"fast", [
+ CIR_FMFnsz, CIR_FMFnnan, CIR_FMFninf, CIR_FMFarcp,
+ CIR_FMFcontract, CIR_FMFafn, CIR_FMFreassoc]>;
+
+def CIR_FastMathFlags : CIR_I32BitEnum<"FastMathFlags",
+ "Floating-point fast-math flags", [
+ CIR_FMFnone, CIR_FMFnsz, CIR_FMFnnan, CIR_FMFninf, CIR_FMFarcp,
+ CIR_FMFcontract, CIR_FMFafn, CIR_FMFreassoc, CIR_FMFfast
+]> {
+ let printBitEnumPrimaryGroups = 1;
+}
+
+def CIR_FastMathAttr : CIR_EnumAttr<CIR_FastMathFlags, "fastmath">;
+
//===----------------------------------------------------------------------===//
// FenvAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 449af063cf9ac..56c07f99026b5 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -7689,7 +7689,8 @@ class CIR_BinaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
let arguments = (ins
CIR_AnyFloatOrVecOfFloatType:$lhs,
CIR_AnyFloatOrVecOfFloatType:$rhs,
- OptionalAttr<CIR_FenvAttr>:$fenv
+ OptionalAttr<CIR_FenvAttr>:$fenv,
+ OptionalAttr<CIR_FastMathAttr>:$fastmath
);
let results = (outs CIR_AnyFloatOrVecOfFloatType:$result);
@@ -7701,7 +7702,8 @@ class CIR_BinaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
let builders = [
OpBuilder<(ins "mlir::Type":$result, "mlir::Value":$lhs,
"mlir::Value":$rhs), [{
- build($_builder, $_state, result, lhs, rhs, cir::FenvAttr{});
+ build($_builder, $_state, result, lhs, rhs, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>
];
@@ -7725,7 +7727,6 @@ def CIR_FMaxNumOp : CIR_BinaryFPToFPBuiltinOp<"fmaxnum", "MaxNumOp"> {
`cir.fmaxnum` returns the larger of its two operands. If one operand is
NaN, the other operand is returned.
}];
- // Needs custom lowering for FastmathFlags::nsz.
let llvmOp = "";
}
@@ -7746,7 +7747,6 @@ def CIR_FMinNumOp : CIR_BinaryFPToFPBuiltinOp<"fminnum", "MinNumOp"> {
`cir.fminnum` returns the smaller of its two operands. If one operand is
NaN, the other operand is returned.
}];
- // Needs custom lowering for FastmathFlags::nsz.
let llvmOp = "";
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index fb2f5b0d9461e..b409b15d58910 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -24,6 +24,7 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/OperatorKinds.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/STLExtras.h"
@@ -614,8 +615,9 @@ static RValue emitTernaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
}
template <typename Op>
-static mlir::Value emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
- const CallExpr &e) {
+static mlir::Value
+emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf, const CallExpr &e,
+ cir::FastMathFlagsAttr fmf = {}) {
mlir::Value arg0 = cgf.emitScalarExpr(e.getArg(0));
mlir::Value arg1 = cgf.emitScalarExpr(e.getArg(1));
@@ -625,7 +627,7 @@ static mlir::Value emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
mlir::Type ty = cgf.convertType(e.getType());
auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1,
- cgf.getBuilder().getConstrainedFPAttr());
+ cgf.getBuilder().getConstrainedFPAttr(), fmf);
return call->getResult(0);
}
@@ -877,8 +879,10 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e,
case Builtin::BI__builtin_fmaxf16:
case Builtin::BI__builtin_fmaxl:
case Builtin::BI__builtin_fmaxf128:
- return RValue::get(
- emitBinaryMaybeConstrainedFPBuiltin<cir::FMaxNumOp>(cgf, *e));
+ return RValue::get(emitBinaryMaybeConstrainedFPBuiltin<cir::FMaxNumOp>(
+ cgf, *e,
+ cir::FastMathFlagsAttr::get(cgf.getBuilder().getContext(),
+ cir::FastMathFlags::nsz)));
case Builtin::BIfmin:
case Builtin::BIfminf:
case Builtin::BIfminl:
@@ -887,8 +891,10 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e,
case Builtin::BI__builtin_fminf16:
case Builtin::BI__builtin_fminl:
case Builtin::BI__builtin_fminf128:
- return RValue::get(
- emitBinaryMaybeConstrainedFPBuiltin<cir::FMinNumOp>(cgf, *e));
+ return RValue::get(emitBinaryMaybeConstrainedFPBuiltin<cir::FMinNumOp>(
+ cgf, *e,
+ cir::FastMathFlagsAttr::get(cgf.getBuilder().getContext(),
+ cir::FastMathFlags::nsz)));
case Builtin::BIfmaximum_num:
case Builtin::BIfmaximum_numf:
case Builtin::BIfmaximum_numl:
@@ -2090,53 +2096,48 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
cir::OverflowBehavior::Saturated);
return RValue::get(val);
}
- case Builtin::BI__builtin_elementwise_max:
- case Builtin::BI__builtin_elementwise_min:
+ case Builtin::BI__builtin_elementwise_max: {
+ if (cir::isIntOrVectorOfIntType(convertType(e->getArg(0)->getType()))) {
+ mlir::Location loc = getLoc(e->getExprLoc());
+ mlir::Value op0 = emitScalarExpr(e->getArg(0));
+ mlir::Value op1 = emitScalarExpr(e->getArg(1));
+
+ QualType ty = e->getArg(0)->getType();
+ return RValue::get(builder.emitIntrinsicCallOp(
+ loc, (ty->hasSignedIntegerRepresentation() ? "smax" : "umax"),
+ op0.getType(), mlir::ValueRange{op0, op1}));
+ }
+ return RValue::get(
+ emitBinaryMaybeConstrainedFPBuiltin<cir::FMaxNumOp>(*this, *e));
+ }
+ case Builtin::BI__builtin_elementwise_min: {
+ if (cir::isIntOrVectorOfIntType(convertType(e->getArg(0)->getType()))) {
+ mlir::Location loc = getLoc(e->getExprLoc());
+ mlir::Value op0 = emitScalarExpr(e->getArg(0));
+ mlir::Value op1 = emitScalarExpr(e->getArg(1));
+ QualType ty = e->getArg(0)->getType();
+ return RValue::get(builder.emitIntrinsicCallOp(
+ loc, (ty->hasSignedIntegerRepresentation() ? "smin" : "umin"),
+ op0.getType(), mlir::ValueRange{op0, op1}));
+ }
+ return RValue::get(
+ emitBinaryMaybeConstrainedFPBuiltin<cir::FMinNumOp>(*this, *e));
+ }
case Builtin::BI__builtin_elementwise_maxnum:
+ return RValue::get(
+ emitBinaryMaybeConstrainedFPBuiltin<cir::FMaxNumOp>(*this, *e));
case Builtin::BI__builtin_elementwise_minnum:
+ return RValue::get(
+ emitBinaryMaybeConstrainedFPBuiltin<cir::FMinNumOp>(*this, *e));
case Builtin::BI__builtin_elementwise_maximum:
+ return RValue::get(
+ emitBinaryMaybeConstrainedFPBuiltin<cir::FMaximumOp>(*this, *e));
case Builtin::BI__builtin_elementwise_minimum:
- case Builtin::BI__builtin_elementwise_maximumnum:
- case Builtin::BI__builtin_elementwise_minimumnum: {
- mlir::Location loc = getLoc(e->getExprLoc());
- mlir::Value op0 = emitScalarExpr(e->getArg(0));
- mlir::Value op1 = emitScalarExpr(e->getArg(1));
-
- auto getIntrinName = [&](unsigned builtinID) {
- switch (builtinID) {
- case Builtin::BI__builtin_elementwise_min:
- if (cir::isIntOrVectorOfIntType(op0.getType())) {
- QualType ty = e->getArg(0)->getType();
- return ty->hasSignedIntegerRepresentation() ? "smin" : "umin";
- }
- return "minnum";
- case Builtin::BI__builtin_elementwise_max:
- if (cir::isIntOrVectorOfIntType(op0.getType())) {
- QualType ty = e->getArg(0)->getType();
- return ty->hasSignedIntegerRepresentation() ? "smax" : "umax";
- }
- return "maxnum";
- case Builtin::BI__builtin_elementwise_minnum:
- return "minnum";
- case Builtin::BI__builtin_elementwise_maxnum:
- return "maxnum";
- case Builtin::BI__builtin_elementwise_minimum:
- return "minimum";
- case Builtin::BI__builtin_elementwise_maximum:
- return "maximum";
- case Builtin::BI__builtin_elementwise_minimumnum:
- return "minimumnum";
- case Builtin::BI__builtin_elementwise_maximumnum:
- return "maximumnum";
- default:
- llvm_unreachable("Unhandled intrin id?");
- };
- };
-
return RValue::get(
- builder.emitIntrinsicCallOp(loc, getIntrinName(builtinIDIfNoAsmLabel),
- op0.getType(), mlir::ValueRange{op0, op1}));
- }
+ emitBinaryMaybeConstrainedFPBuiltin<cir::FMinimumOp>(*this, *e));
+
+ case Builtin::BI__builtin_elementwise_maximumnum:
+ case Builtin::BI__builtin_elementwise_minimumnum:
case Builtin::BI__builtin_reduce_max:
case Builtin::BI__builtin_reduce_min:
case Builtin::BI__builtin_reduce_add:
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6761da8be6491..ec378c78d2665 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -462,6 +462,29 @@ void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow,
noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
}
+static mlir::LLVM::FastmathFlags
+convertCIRFastMathFlags(cir::FastMathFlagsAttr fmfAttr) {
+ if (!fmfAttr)
+ return {};
+ cir::FastMathFlags src = fmfAttr.getValue();
+ mlir::LLVM::FastmathFlags result = {};
+ if (bitEnumContainsAll(src, cir::FastMathFlags::nsz))
+ result = result | mlir::LLVM::nsz;
+ if (bitEnumContainsAll(src, cir::FastMathFlags::nnan))
+ result = result | mlir::LLVM::nnan;
+ if (bitEnumContainsAll(src, cir::FastMathFlags::ninf))
+ result = result | mlir::LLVM::ninf;
+ if (bitEnumContainsAll(src, cir::FastMathFlags::arcp))
+ result = result | mlir::LLVM::arcp;
+ if (bitEnumContainsAll(src, cir::FastMathFlags::contract))
+ result = result | mlir::LLVM::contract;
+ if (bitEnumContainsAll(src, cir::FastMathFlags::afn))
+ result = result | mlir::LLVM::afn;
+ if (bitEnumContainsAll(src, cir::FastMathFlags::reassoc))
+ result = result | mlir::LLVM::reassoc;
+ return result;
+}
+
static mlir::LLVM::CallIntrinsicOp
createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter,
mlir::Location loc, const llvm::Twine &intrinsicName,
@@ -2033,13 +2056,13 @@ mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
cir::FMaxNumOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::Type resTy = typeConverter->convertType(op.getType());
+ mlir::LLVM::FastmathFlags fmf = convertCIRFastMathFlags(op.getFastmathAttr());
if (cir::FenvAttr fenv = op.getFenvAttr())
- return lowerToConstrainedFPIntrinsic(
- op, adaptor.getOperands(), fenv, resTy, rewriter, "maxnum",
- /*hasRoundingMode=*/false, mlir::LLVM::FastmathFlags::nsz);
- rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
- op, resTy, adaptor.getLhs(), adaptor.getRhs(),
- mlir::LLVM::FastmathFlags::nsz);
+ return lowerToConstrainedFPIntrinsic(op, adaptor.getOperands(), fenv, resTy,
+ rewriter, "maxnum",
+ /*hasRoundingMode=*/false, fmf);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(op, resTy, adaptor.getLhs(),
+ adaptor.getRhs(), fmf);
return mlir::success();
}
@@ -2047,13 +2070,13 @@ mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
cir::FMinNumOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::Type resTy = typeConverter->convertType(op.getType());
+ mlir::LLVM::FastmathFlags fmf = convertCIRFastMathFlags(op.getFastmathAttr());
if (cir::FenvAttr fenv = op.getFenvAttr())
- return lowerToConstrainedFPIntrinsic(
- op, adaptor.getOperands(), fenv, resTy, rewriter, "minnum",
- /*hasRoundingMode=*/false, mlir::LLVM::FastmathFlags::nsz);
- rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
- op, resTy, adaptor.getLhs(), adaptor.getRhs(),
- mlir::LLVM::FastmathFlags::nsz);
+ return lowerToConstrainedFPIntrinsic(op, adaptor.getOperands(), fenv, resTy,
+ rewriter, "minnum",
+ /*hasRoundingMode=*/false, fmf);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(op, resTy, adaptor.getLhs(),
+ adaptor.getRhs(), fmf);
return mlir::success();
}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c b/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
deleted file mode 100644
index c13c90d77986e..0000000000000
--- a/clang/test/CIR/CodeGenBuiltins/builtin-maximumnum-minimumnum.c
+++ /dev/null
@@ -1,107 +0,0 @@
-// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-cir -o %t.cir
-// RUN: FileCheck %s --input-file=%t.cir --check-prefix=CIR
-// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -fclangir -o %t-cir.ll
-// RUN: FileCheck %s --input-file=%t-cir.ll --check-prefix=LLVM
-// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -o %t-ogcg.ll
-// RUN: FileCheck %s --input-file=%t-ogcg.ll --check-prefix=LLVM
-
-typedef _Float16 half8 __attribute__((ext_vector_type(8)));
-typedef __bf16 bf16x8 __attribute__((ext_vector_type(8)));
-typedef float float4 __attribute__((ext_vector_type(4)));
-typedef double double2 __attribute__((ext_vector_type(2)));
-typedef long double ldouble2 __attribute__((ext_vector_type(2)));
-
-// CIR-LABEL: @_Z7pfmin16Dv8_DF16_S_(
-// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.f16>, !cir.vector<8 x !cir.f16>) -> !cir.vector<8 x !cir.f16>
-//
-// LLVM-LABEL: @_Z7pfmin16Dv8_DF16_S_(
-// LLVM: call <8 x half> @llvm.minimumnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
-//
-half8 pfmin16(half8 a, half8 b) {
- return __builtin_elementwise_minimumnum(a, b);
-}
-// CIR-LABEL: @_Z8pfmin16bDv8_DF16bS_(
-// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.bf16>, !cir.vector<8 x !cir.bf16>) -> !cir.vector<8 x !cir.bf16>
-//
-// LLVM-LABEL: @_Z8pfmin16bDv8_DF16bS_(
-// LLVM: call <8 x bfloat> @llvm.minimumnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
-//
-bf16x8 pfmin16b(bf16x8 a, bf16x8 b) {
- return __builtin_elementwise_minimumnum(a, b);
-}
-// CIR-LABEL: @_Z7pfmin32Dv4_fS_(
-// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
-//
-// LLVM-LABEL: @_Z7pfmin32Dv4_fS_(
-// LLVM: call <4 x float> @llvm.minimumnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
-//
-float4 pfmin32(float4 a, float4 b) {
- return __builtin_elementwise_minimumnum(a, b);
-}
-// CIR-LABEL: @_Z7pfmin64Dv2_dS_(
-// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
-//
-// LLVM-LABEL: @_Z7pfmin64Dv2_dS_(
-// LLVM: call <2 x double> @llvm.minimumnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
-//
-double2 pfmin64(double2 a, double2 b) {
- return __builtin_elementwise_minimumnum(a, b);
-}
-// CIR-LABEL: @_Z7pfmin80v(
-// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.long_double<!cir.f80>>, !cir.vector<2 x !cir.long_double<!cir.f80>>) -> !cir.vector<2 x !cir.long_double<!cir.f80>>
-//
-// LLVM-LABEL: @_Z7pfmin80v(
-// LLVM: call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
-//
-void pfmin80() {
- ldouble2 a, b;
- ldouble2 c = __builtin_elementwise_minimumnum(a, b);
-}
-
-// CIR-LABEL: @_Z7pfmax16Dv8_DF16_S_(
-// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.f16>, !cir.vector<8 x !cir.f16>) -> !cir.vector<8 x !cir.f16>
-//
-// LLVM-LABEL: @_Z7pfmax16Dv8_DF16_S_(
-// LLVM: call <8 x half> @llvm.maximumnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
-//
-half8 pfmax16(half8 a, half8 b) {
- return __builtin_elementwise_maximumnum(a, b);
-}
-// CIR-LABEL: @_Z8pfmax16bDv8_DF16bS_(
-// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.bf16>, !cir.vector<8 x !cir.bf16>) -> !cir.vector<8 x !cir.bf16>
-//
-// LLVM-LABEL: @_Z8pfmax16bDv8_DF16bS_(
-// LLVM: call <8 x bfloat> @llvm.maximumnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
-//
-bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
- return __builtin_elementwise_maximumnum(a, b);
-}
-// CIR-LABEL: @_Z7pfmax32Dv4_fS_(
-// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
-//
-// LLVM-LABEL: @_Z7pfmax32Dv4_fS_(
-// LLVM: call <4 x float> @llvm.maximumnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
-//
-float4 pfmax32(float4 a, float4 b) {
- return __builtin_elementwise_maximumnum(a, b);
-}
-// CIR-LABEL: @_Z7pfmax64Dv2_dS_(
-// CIR: cir.call_llvm_intrinsic "maximumnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
-//
-// LLVM-LABEL: @_Z7pfmax64Dv2_dS_(
-// LLVM: call <2 x double> @llvm.maximumnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
-//
-double2 pfmax64(double2 a, double2 b) {
- return __builtin_elementwise_maximumnum(a, b);
-}
-
-// CIR-LABEL: @_Z7pfmax80v(
-// CIR: cir.call_llvm_intrinsic "minimumnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.long_double<!cir.f80>>, !cir.vector<2 x !cir.long_double<!cir.f80>>) -> !cir.vector<2 x !cir.long_double<!cir.f80>>
-//
-// LLVM-LABEL: @_Z7pfmax80v(
-// LLVM: call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
-//
-void pfmax80() {
- ldouble2 a, b;
- ldouble2 c = __builtin_elementwise_minimumnum(a, b);
-}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c b/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
index 5a05d701bc573..463504ce8e5c4 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
@@ -12,7 +12,7 @@ typedef double double2 __attribute__((ext_vector_type(2)));
typedef long double ldouble2 __attribute__((ext_vector_type(2)));
// CIR-LABEL: @_Z7pfmin16Dv8_DF16_S_(
-// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.f16>, !cir.vector<8 x !cir.f16>) -> !cir.vector<8 x !cir.f16>
+// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.f16>
//
// LLVM-LABEL: @_Z7pfmin16Dv8_DF16_S_(
// LLVM: call <8 x half> @llvm.minnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
@@ -21,7 +21,7 @@ half8 pfmin16(half8 a, half8 b) {
return __builtin_elementwise_minnum(a, b);
}
// CIR-LABEL: @_Z8pfmin16bDv8_DF16bS_(
-// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.bf16>, !cir.vector<8 x !cir.bf16>) -> !cir.vector<8 x !cir.bf16>
+// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.bf16>
//
// LLVM-LABEL: @_Z8pfmin16bDv8_DF16bS_(
// LLVM: call <8 x bfloat> @llvm.minnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
@@ -30,7 +30,7 @@ bf16x8 pfmin16b(bf16x8 a, bf16x8 b) {
return __builtin_elementwise_minnum(a, b);
}
// CIR-LABEL: @_Z7pfmin32Dv4_fS_(
-// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float>
//
// LLVM-LABEL: @_Z7pfmin32Dv4_fS_(
// LLVM: call <4 x float> @llvm.minnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
@@ -39,7 +39,7 @@ float4 pfmin32(float4 a, float4 b) {
return __builtin_elementwise_minnum(a, b);
}
// CIR-LABEL: @_Z7pfmin64Dv2_dS_(
-// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
+// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.double>
//
// LLVM-LABEL: @_Z7pfmin64Dv2_dS_(
// LLVM: call <2 x double> @llvm.minnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
@@ -48,7 +48,7 @@ double2 pfmin64(double2 a, double2 b) {
return __builtin_elementwise_minnum(a, b);
}
// CIR-LABEL: @_Z7pfmin80v(
-// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.long_double<!cir.f80>>, !cir.vector<2 x !cir.long_double<!cir.f80>>) -> !cir.vector<2 x !cir.long_double<!cir.f80>>
+// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.long_double<!cir.f80>>
//
// LLVM-LABEL: @_Z7pfmin80v(
// LLVM: call <2 x x86_fp80> @llvm.minnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
@@ -59,7 +59,7 @@ void pfmin80() {
}
// CIR-LABEL: @_Z7pfmax16Dv8_DF16_S_(
-// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.f16>, !cir.vector<8 x !cir.f16>) -> !cir.vector<8 x !cir.f16>
+// CIR: cir.fmaxnum %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.f16>
//
// LLVM-LABEL: @_Z7pfmax16Dv8_DF16_S_(
// LLVM: call <8 x half> @llvm.maxnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
@@ -68,7 +68,7 @@ half8 pfmax16(half8 a, half8 b) {
return __builtin_elementwise_maxnum(a, b);
}
// CIR-LABEL: @_Z8pfmax16bDv8_DF16bS_(
-// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.bf16>, !cir.vector<8 x !cir.bf16>) -> !cir.vector<8 x !cir.bf16>
+// CIR: cir.fmaxnum %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.bf16>
//
// LLVM-LABEL: @_Z8pfmax16bDv8_DF16bS_(
// LLVM: call <8 x bfloat> @llvm.maxnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
@@ -77,7 +77,7 @@ bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
return __builtin_elementwise_maxnum(a, b);
}
// CIR-LABEL: @_Z7pfmax32Dv4_fS_(
-// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// CIR: cir.fmaxnum %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float>
//
// LLVM-LABEL: @_Z7pfmax32Dv4_fS_(
// LLVM: call <4 x float> @llvm.maxnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
@@ -86,7 +86,7 @@ float4 pfmax32(float4 a, float4 b) {
return __builtin_elementwise_maxnum(a, b);
}
// CIR-LABEL: @_Z7pfmax64Dv2_dS_(
-// CIR: cir.call_llvm_intrinsic "maxnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
+// CIR: cir.fmaxnum %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.double>
//
// LLVM-LABEL: @_Z7pfmax64Dv2_dS_(
// LLVM: call <2 x double> @llvm.maxnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
@@ -96,7 +96,7 @@ double2 pfmax64(double2 a, double2 b) {
}
// CIR-LABEL: @_Z7pfmax80v(
-// CIR: cir.call_llvm_intrinsic "minnum" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.long_double<!cir.f80>>, !cir.vector<2 x !cir.long_double<!cir.f80>>) -> !cir.vector<2 x !cir.long_double<!cir.f80>>
+// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.long_double<!cir.f80>>
//
// LLVM-LABEL: @_Z7pfmax80v(
// LLVM: call <2 x x86_fp80> @llvm.minnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
index 636a8c574e864..70defd9ae7f72 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
@@ -802,7 +802,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[F1_LOAD:.*]] = cir.load align(4) %[[F1]] : !cir.ptr<!cir.float>, !cir.float
// CIR-NEXT: %[[F2_LOAD:.*]] = cir.load align(4) %[[F2]] : !cir.ptr<!cir.float>, !cir.float
- // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[F1_LOAD]], %[[F2_LOAD]] : (!cir.float, !cir.float) -> !cir.float
+ // CIR-NEXT: cir.fminnum %[[F1_LOAD]], %[[F2_LOAD]] : !cir.float
// LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
// LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
@@ -811,7 +811,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
// CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
- // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[D1_LOAD]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+ // CIR-NEXT: cir.fminnum %[[D1_LOAD]], %[[D2_LOAD]] : !cir.double
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
// LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
@@ -820,7 +820,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
// CIR-NEXT: %[[TWO:.*]] = cir.const #cir.fp<2.000000e+00> : !cir.double
- // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[D1_LOAD]], %[[TWO]] : (!cir.double, !cir.double) -> !cir.double
+ // CIR-NEXT: cir.fminnum %[[D1_LOAD]], %[[TWO]] : !cir.double
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
// LLVM-NEXT: call double @llvm.minnum.f64(double [[D1]], double 2.000000e+00)
@@ -828,7 +828,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[VF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fminnum %[[VF1_LOAD]], %[[VF2_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
@@ -915,7 +915,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[CVF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fminnum %[[CVF1_LOAD]], %[[VF2_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
@@ -925,7 +925,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "minnum" %[[VF2_LOAD]], %[[CVF1_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fminnum %[[VF2_LOAD]], %[[CVF1_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
// LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
@@ -1001,7 +1001,7 @@ void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,
// CIR: %[[F1_LOAD:.*]] = cir.load align(4) %[[F1]] : !cir.ptr<!cir.float>, !cir.float
// CIR-NEXT: %[[F2_LOAD:.*]] = cir.load align(4) %[[F2]] : !cir.ptr<!cir.float>, !cir.float
- // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[F1_LOAD]], %[[F2_LOAD]] : (!cir.float, !cir.float) -> !cir.float
+ // CIR-NEXT: cir.fminimum %[[F1_LOAD]], %[[F2_LOAD]] : !cir.float
// LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
// LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
@@ -1010,7 +1010,7 @@ void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
// CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
- // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[D1_LOAD]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+ // CIR-NEXT: cir.fminimum %[[D1_LOAD]], %[[D2_LOAD]] : !cir.double
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
// LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
@@ -1019,7 +1019,7 @@ void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
// CIR-NEXT: %[[TWO:.*]] = cir.const #cir.fp<2.000000e+00> : !cir.double
- // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[D1_LOAD]], %[[TWO]] : (!cir.double, !cir.double) -> !cir.double
+ // CIR-NEXT: cir.fminimum %[[D1_LOAD]], %[[TWO]] : !cir.double
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
// LLVM-NEXT: call double @llvm.minimum.f64(double [[D1]], double 2.000000e+00)
@@ -1027,7 +1027,7 @@ void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,
// CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[VF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fminimum %[[VF1_LOAD]], %[[VF2_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
@@ -1036,7 +1036,7 @@ void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,
// CIR: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[CVF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fminimum %[[CVF1_LOAD]], %[[VF2_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
@@ -1046,7 +1046,7 @@ void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,
// CIR: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "minimum" %[[VF2_LOAD]], %[[CVF1_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fminimum %[[VF2_LOAD]], %[[CVF1_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
// LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
@@ -1105,7 +1105,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[F1_LOAD:.*]] = cir.load align(4) %[[F1]] : !cir.ptr<!cir.float>, !cir.float
// CIR-NEXT: %[[F2_LOAD:.*]] = cir.load align(4) %[[F2]] : !cir.ptr<!cir.float>, !cir.float
- // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[F1_LOAD]], %[[F2_LOAD]] : (!cir.float, !cir.float) -> !cir.float
+ // CIR-NEXT: cir.fmaxnum %[[F1_LOAD]], %[[F2_LOAD]] : !cir.float
// LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
// LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
@@ -1114,7 +1114,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
// CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
- // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[D1_LOAD]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+ // CIR-NEXT: cir.fmaxnum %[[D1_LOAD]], %[[D2_LOAD]] : !cir.double
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
// LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
@@ -1123,7 +1123,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[TWENTY:.*]] = cir.const #cir.fp<2.000000e+01> : !cir.double
// CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
- // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[TWENTY]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+ // CIR-NEXT: cir.fmaxnum %[[TWENTY]], %[[D2_LOAD]] : !cir.double
// LLVM: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
// LLVM-NEXT: call double @llvm.maxnum.f64(double 2.000000e+01, double [[D2]])
@@ -1131,7 +1131,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[VF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fmaxnum %[[VF1_LOAD]], %[[VF2_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
@@ -1206,7 +1206,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[CVF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fmaxnum %[[CVF1_LOAD]], %[[VF2_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
@@ -1216,7 +1216,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "maxnum" %[[VF2_LOAD]], %[[CVF1_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fmaxnum %[[VF2_LOAD]], %[[CVF1_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
// LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
@@ -1292,7 +1292,7 @@ void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,
// CIR: %[[F1_LOAD:.*]] = cir.load align(4) %[[F1]] : !cir.ptr<!cir.float>, !cir.float
// CIR-NEXT: %[[F2_LOAD:.*]] = cir.load align(4) %[[F2]] : !cir.ptr<!cir.float>, !cir.float
- // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[F1_LOAD]], %[[F2_LOAD]] : (!cir.float, !cir.float) -> !cir.float
+ // CIR-NEXT: cir.fmaximum %[[F1_LOAD]], %[[F2_LOAD]] : !cir.float
// LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
// LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
@@ -1301,7 +1301,7 @@ void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
// CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
- // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[D1_LOAD]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+ // CIR-NEXT: cir.fmaximum %[[D1_LOAD]], %[[D2_LOAD]] : !cir.double
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
// LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
@@ -1310,7 +1310,7 @@ void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,
// CIR: %[[TWENTY:.*]] = cir.const #cir.fp<2.000000e+01> : !cir.double
// CIR-NEXT: %[[D2_LOAD:.*]] = cir.load align(8) %[[D2]] : !cir.ptr<!cir.double>, !cir.double
- // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[TWENTY]], %[[D2_LOAD]] : (!cir.double, !cir.double) -> !cir.double
+ // CIR-NEXT: cir.fmaximum %[[TWENTY]], %[[D2_LOAD]] : !cir.double
// LLVM: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
// LLVM-NEXT: call double @llvm.maximum.f64(double 2.000000e+01, double [[D2]])
@@ -1318,7 +1318,7 @@ void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,
// CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[VF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fmaximum %[[VF1_LOAD]], %[[VF2_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
@@ -1327,7 +1327,7 @@ void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,
// CIR: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[CVF1_LOAD]], %[[VF2_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fmaximum %[[CVF1_LOAD]], %[[VF2_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
@@ -1337,7 +1337,7 @@ void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,
// CIR: %[[VF2_LOAD:.*]] = cir.load align(16) %[[VF2]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
// CIR-NEXT: %[[CVF1_LOAD:.*]] = cir.load align(16) %[[CVF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
- // CIR-NEXT: cir.call_llvm_intrinsic "maximum" %[[VF2_LOAD]], %[[CVF1_LOAD]] : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+ // CIR-NEXT: cir.fmaximum %[[VF2_LOAD]], %[[CVF1_LOAD]] : !cir.vector<4 x !cir.float>
// LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
// LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
index 47f01bebfe90c..cac0d6a3a02d3 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
@@ -1944,7 +1944,7 @@ long double call_copysignl(long double x, long double y) {
float my_fmaxf(float x, float y) {
return __builtin_fmaxf(x, y);
// CIR: cir.func no_inline dso_local @my_fmaxf
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.float
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.float {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local float @my_fmaxf
// LLVM: call nsz float @llvm.maxnum.f32(float %{{.+}}, float %{{.+}})
@@ -1957,7 +1957,7 @@ float my_fmaxf(float x, float y) {
double my_fmax(double x, double y) {
return __builtin_fmax(x, y);
// CIR: cir.func no_inline dso_local @my_fmax
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.double
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.double {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local double @my_fmax
// LLVM: call nsz double @llvm.maxnum.f64(double %{{.+}}, double %{{.+}})
@@ -1970,8 +1970,8 @@ double my_fmax(double x, double y) {
long double my_fmaxl(long double x, long double y) {
return __builtin_fmaxl(x, y);
// CIR: cir.func no_inline dso_local @my_fmaxl
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80>
- // AARCH64: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double>
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80> {fastmath = #cir.fastmath<nsz>}
+ // AARCH64: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double> {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local x86_fp80 @my_fmaxl
// LLVM: call nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
@@ -1988,7 +1988,7 @@ long double fmaxl(long double, long double);
float call_fmaxf(float x, float y) {
return fmaxf(x, y);
// CIR: cir.func no_inline dso_local @call_fmaxf
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.float
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.float {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local float @call_fmaxf
// LLVM: call nsz float @llvm.maxnum.f32(float %{{.+}}, float %{{.+}})
@@ -2001,7 +2001,7 @@ float call_fmaxf(float x, float y) {
double call_fmax(double x, double y) {
return fmax(x, y);
// CIR: cir.func no_inline dso_local @call_fmax
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.double
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.double {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local double @call_fmax
// LLVM: call nsz double @llvm.maxnum.f64(double %{{.+}}, double %{{.+}})
@@ -2014,8 +2014,8 @@ double call_fmax(double x, double y) {
long double call_fmaxl(long double x, long double y) {
return fmaxl(x, y);
// CIR: cir.func no_inline dso_local @call_fmaxl
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80>
- // AARCH64: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double>
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80> {fastmath = #cir.fastmath<nsz>}
+ // AARCH64: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double> {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local x86_fp80 @call_fmaxl
// LLVM: call nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
@@ -2030,7 +2030,7 @@ long double call_fmaxl(long double x, long double y) {
float my_fminf(float x, float y) {
return __builtin_fminf(x, y);
// CIR: cir.func no_inline dso_local @my_fminf
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.float
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.float {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local float @my_fminf
// LLVM: call nsz float @llvm.minnum.f32(float %{{.+}}, float %{{.+}})
@@ -2043,7 +2043,7 @@ float my_fminf(float x, float y) {
double my_fmin(double x, double y) {
return __builtin_fmin(x, y);
// CIR: cir.func no_inline dso_local @my_fmin
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.double
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.double {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local double @my_fmin
// LLVM: call nsz double @llvm.minnum.f64(double %{{.+}}, double %{{.+}})
@@ -2056,8 +2056,8 @@ double my_fmin(double x, double y) {
long double my_fminl(long double x, long double y) {
return __builtin_fminl(x, y);
// CIR: cir.func no_inline dso_local @my_fminl
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80>
- // AARCH64: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double>
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80> {fastmath = #cir.fastmath<nsz>}
+ // AARCH64: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double> {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local x86_fp80 @my_fminl
// LLVM: call nsz x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
@@ -2074,7 +2074,7 @@ long double fminl(long double, long double);
float call_fminf(float x, float y) {
return fminf(x, y);
// CIR: cir.func no_inline dso_local @call_fminf
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.float
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.float {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local float @call_fminf
// LLVM: call nsz float @llvm.minnum.f32(float %{{.+}}, float %{{.+}})
@@ -2087,7 +2087,7 @@ float call_fminf(float x, float y) {
double call_fmin(double x, double y) {
return fmin(x, y);
// CIR: cir.func no_inline dso_local @call_fmin
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.double
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.double {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local double @call_fmin
// LLVM: call nsz double @llvm.minnum.f64(double %{{.+}}, double %{{.+}})
@@ -2100,8 +2100,8 @@ double call_fmin(double x, double y) {
long double call_fminl(long double x, long double y) {
return fminl(x, y);
// CIR: cir.func no_inline dso_local @call_fminl
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80>
- // AARCH64: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double>
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80> {fastmath = #cir.fastmath<nsz>}
+ // AARCH64: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double> {fastmath = #cir.fastmath<nsz>}
// LLVM: define dso_local x86_fp80 @call_fminl
// LLVM: call nsz x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
>From 7cac606d86c2da673370333986f53a44d80d9e42 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Sep 2026 14:03:44 -0700
Subject: [PATCH 4/5] Fix build by getting enum name right
---
.../lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index a53748630c3e6..b2fe9ce2f1796 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -469,19 +469,19 @@ convertCIRFastMathFlags(cir::FastMathFlagsAttr fmfAttr) {
cir::FastMathFlags src = fmfAttr.getValue();
mlir::LLVM::FastmathFlags result = {};
if (bitEnumContainsAll(src, cir::FastMathFlags::nsz))
- result = result | mlir::LLVM::nsz;
+ result = result | mlir::LLVM::FastmathFlags::nsz;
if (bitEnumContainsAll(src, cir::FastMathFlags::nnan))
- result = result | mlir::LLVM::nnan;
+ result = result | mlir::LLVM::FastmathFlags::nnan;
if (bitEnumContainsAll(src, cir::FastMathFlags::ninf))
- result = result | mlir::LLVM::ninf;
+ result = result | mlir::LLVM::FastmathFlags::ninf;
if (bitEnumContainsAll(src, cir::FastMathFlags::arcp))
- result = result | mlir::LLVM::arcp;
+ result = result | mlir::LLVM::FastmathFlags::arcp;
if (bitEnumContainsAll(src, cir::FastMathFlags::contract))
- result = result | mlir::LLVM::contract;
+ result = result | mlir::LLVM::FastmathFlags::contract;
if (bitEnumContainsAll(src, cir::FastMathFlags::afn))
- result = result | mlir::LLVM::afn;
+ result = result | mlir::LLVM::FastmathFlags::afn;
if (bitEnumContainsAll(src, cir::FastMathFlags::reassoc))
- result = result | mlir::LLVM::reassoc;
+ result = result | mlir::LLVM::FastmathFlags::reassoc;
return result;
}
>From 4172eac0f0747a582bfa077b74e73d926d8f664a Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Sep 2026 20:27:59 -0700
Subject: [PATCH 5/5] Reverted fast-math-flags, set MinOp and MaxOp to emit
correctly
---
.../CIR/Dialect/Builder/CIRBaseBuilder.h | 4 ++
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 26 ---------
clang/include/clang/CIR/Dialect/IR/CIROps.td | 23 ++------
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 34 ++++-------
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 51 +++++-----------
.../CodeGenBuiltins/builtin-maxnum-minnum.c | 21 +++----
.../CodeGenBuiltins/builtins-elementwise.c | 58 +++++++++----------
.../CodeGenBuiltins/builtins-floating-point.c | 32 +++++-----
8 files changed, 88 insertions(+), 161 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index b5920492f1800..3a52960000a14 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -892,6 +892,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::MaxOp::create(*this, loc, lhs, rhs);
}
+ mlir::Value createMin(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ return cir::MinOp::create(*this, loc, lhs, rhs);
+ }
+
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
mlir::Value lhs, mlir::Value rhs) {
cir::FenvAttr fenv;
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 8cc7b449c1bac..f263cd30eb458 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -848,32 +848,6 @@ def CIR_CmpThreeWayInfoAttr : CIR_Attr<"CmpThreeWayInfo", "cmp3way_info"> {
let canHaveIllegalCXXABIType = 0;
}
-//===----------------------------------------------------------------------===//
-// FastMathFlagsAttr
-//===----------------------------------------------------------------------===//
-
-def CIR_FMFnone : I32BitEnumAttrCaseNone<"none">;
-def CIR_FMFnsz : I32BitEnumAttrCaseBit<"nsz", 0>;
-def CIR_FMFnnan : I32BitEnumAttrCaseBit<"nnan", 1>;
-def CIR_FMFninf : I32BitEnumAttrCaseBit<"ninf", 2>;
-def CIR_FMFarcp : I32BitEnumAttrCaseBit<"arcp", 3>;
-def CIR_FMFcontract : I32BitEnumAttrCaseBit<"contract", 4>;
-def CIR_FMFafn : I32BitEnumAttrCaseBit<"afn", 5>;
-def CIR_FMFreassoc : I32BitEnumAttrCaseBit<"reassoc", 6>;
-def CIR_FMFfast : I32BitEnumAttrCaseGroup<"fast", [
- CIR_FMFnsz, CIR_FMFnnan, CIR_FMFninf, CIR_FMFarcp,
- CIR_FMFcontract, CIR_FMFafn, CIR_FMFreassoc]>;
-
-def CIR_FastMathFlags : CIR_I32BitEnum<"FastMathFlags",
- "Floating-point fast-math flags", [
- CIR_FMFnone, CIR_FMFnsz, CIR_FMFnnan, CIR_FMFninf, CIR_FMFarcp,
- CIR_FMFcontract, CIR_FMFafn, CIR_FMFreassoc, CIR_FMFfast
-]> {
- let printBitEnumPrimaryGroups = 1;
-}
-
-def CIR_FastMathAttr : CIR_EnumAttr<CIR_FastMathFlags, "fastmath">;
-
//===----------------------------------------------------------------------===//
// FenvAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6119e0839c8b6..449af063cf9ac 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -844,21 +844,6 @@ def CIR_LoadOp : CIR_Op<"load", [
$addr `:` qualified(type($addr)) `,` type($result) attr-dict
}];
- let builders = [
- OpBuilder<(ins "mlir::Value":$addr), [{
- build($_builder, $_state, addr, /*isDeref=*/false,
- /*is_volatile=*/false, /*is_nontemporal=*/false,
- /*alignment=*/mlir::IntegerAttr{}, cir::SyncScopeKindAttr{},
- cir::MemOrderAttr{}, /*invariant=*/false);
- }]>,
- OpBuilder<(ins "mlir::Type":$result, "mlir::Value":$addr), [{
- build($_builder, $_state, result, addr, /*isDeref=*/false,
- /*is_volatile=*/false, /*is_nontemporal=*/false,
- /*alignment=*/mlir::IntegerAttr{}, cir::SyncScopeKindAttr{},
- cir::MemOrderAttr{}, /*invariant=*/false);
- }]>
- ];
-
// FIXME: add verifier.
}
@@ -7704,8 +7689,7 @@ class CIR_BinaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
let arguments = (ins
CIR_AnyFloatOrVecOfFloatType:$lhs,
CIR_AnyFloatOrVecOfFloatType:$rhs,
- OptionalAttr<CIR_FenvAttr>:$fenv,
- OptionalAttr<CIR_FastMathAttr>:$fastmath
+ OptionalAttr<CIR_FenvAttr>:$fenv
);
let results = (outs CIR_AnyFloatOrVecOfFloatType:$result);
@@ -7717,8 +7701,7 @@ class CIR_BinaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
let builders = [
OpBuilder<(ins "mlir::Type":$result, "mlir::Value":$lhs,
"mlir::Value":$rhs), [{
- build($_builder, $_state, result, lhs, rhs, cir::FenvAttr{},
- cir::FastMathFlagsAttr{});
+ build($_builder, $_state, result, lhs, rhs, cir::FenvAttr{});
}]>
];
@@ -7742,6 +7725,7 @@ def CIR_FMaxNumOp : CIR_BinaryFPToFPBuiltinOp<"fmaxnum", "MaxNumOp"> {
`cir.fmaxnum` returns the larger of its two operands. If one operand is
NaN, the other operand is returned.
}];
+ // Needs custom lowering for FastmathFlags::nsz.
let llvmOp = "";
}
@@ -7762,6 +7746,7 @@ def CIR_FMinNumOp : CIR_BinaryFPToFPBuiltinOp<"fminnum", "MinNumOp"> {
`cir.fminnum` returns the smaller of its two operands. If one operand is
NaN, the other operand is returned.
}];
+ // Needs custom lowering for FastmathFlags::nsz.
let llvmOp = "";
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 70eb0c70e37f1..fc697a487c45b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -24,7 +24,6 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/OperatorKinds.h"
-#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/STLExtras.h"
@@ -567,7 +566,8 @@ static RValue emitUnaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
template <class Operation>
static RValue emitUnaryFPBuiltin(CIRGenFunction &cgf, const CallExpr &e) {
mlir::Value arg = cgf.emitScalarExpr(e.getArg(0));
- auto call = Operation::create(cgf.getBuilder(), arg.getLoc(), arg);
+ auto call =
+ Operation::create(cgf.getBuilder(), arg.getLoc(), arg.getType(), arg);
return RValue::get(call->getResult(0));
}
@@ -614,9 +614,8 @@ static RValue emitTernaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
}
template <typename Op>
-static mlir::Value
-emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf, const CallExpr &e,
- cir::FastMathFlagsAttr fmf = {}) {
+static mlir::Value emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
+ const CallExpr &e) {
mlir::Value arg0 = cgf.emitScalarExpr(e.getArg(0));
mlir::Value arg1 = cgf.emitScalarExpr(e.getArg(1));
@@ -626,7 +625,7 @@ emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf, const CallExpr &e,
mlir::Type ty = cgf.convertType(e.getType());
auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1,
- cgf.getBuilder().getConstrainedFPAttr(), fmf);
+ cgf.getBuilder().getConstrainedFPAttr());
return call->getResult(0);
}
@@ -878,10 +877,8 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e,
case Builtin::BI__builtin_fmaxf16:
case Builtin::BI__builtin_fmaxl:
case Builtin::BI__builtin_fmaxf128:
- return RValue::get(emitBinaryMaybeConstrainedFPBuiltin<cir::FMaxNumOp>(
- cgf, *e,
- cir::FastMathFlagsAttr::get(cgf.getBuilder().getContext(),
- cir::FastMathFlags::nsz)));
+ return RValue::get(
+ emitBinaryMaybeConstrainedFPBuiltin<cir::FMaxNumOp>(cgf, *e));
case Builtin::BIfmin:
case Builtin::BIfminf:
case Builtin::BIfminl:
@@ -890,10 +887,8 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e,
case Builtin::BI__builtin_fminf16:
case Builtin::BI__builtin_fminl:
case Builtin::BI__builtin_fminf128:
- return RValue::get(emitBinaryMaybeConstrainedFPBuiltin<cir::FMinNumOp>(
- cgf, *e,
- cir::FastMathFlagsAttr::get(cgf.getBuilder().getContext(),
- cir::FastMathFlags::nsz)));
+ return RValue::get(
+ emitBinaryMaybeConstrainedFPBuiltin<cir::FMinNumOp>(cgf, *e));
case Builtin::BIfmaximum_num:
case Builtin::BIfmaximum_numf:
case Builtin::BIfmaximum_numl:
@@ -2100,11 +2095,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
mlir::Location loc = getLoc(e->getExprLoc());
mlir::Value op0 = emitScalarExpr(e->getArg(0));
mlir::Value op1 = emitScalarExpr(e->getArg(1));
-
- QualType ty = e->getArg(0)->getType();
- return RValue::get(builder.emitIntrinsicCallOp(
- loc, (ty->hasSignedIntegerRepresentation() ? "smax" : "umax"),
- op0.getType(), mlir::ValueRange{op0, op1}));
+ return RValue::get(builder.createMax(loc, op0, op1));
}
return RValue::get(
emitBinaryMaybeConstrainedFPBuiltin<cir::FMaxNumOp>(*this, *e));
@@ -2114,10 +2105,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
mlir::Location loc = getLoc(e->getExprLoc());
mlir::Value op0 = emitScalarExpr(e->getArg(0));
mlir::Value op1 = emitScalarExpr(e->getArg(1));
- QualType ty = e->getArg(0)->getType();
- return RValue::get(builder.emitIntrinsicCallOp(
- loc, (ty->hasSignedIntegerRepresentation() ? "smin" : "umin"),
- op0.getType(), mlir::ValueRange{op0, op1}));
+ return RValue::get(builder.createMin(loc, op0, op1));
}
return RValue::get(
emitBinaryMaybeConstrainedFPBuiltin<cir::FMinNumOp>(*this, *e));
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index b2fe9ce2f1796..6761da8be6491 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -462,29 +462,6 @@ void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow,
noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
}
-static mlir::LLVM::FastmathFlags
-convertCIRFastMathFlags(cir::FastMathFlagsAttr fmfAttr) {
- if (!fmfAttr)
- return {};
- cir::FastMathFlags src = fmfAttr.getValue();
- mlir::LLVM::FastmathFlags result = {};
- if (bitEnumContainsAll(src, cir::FastMathFlags::nsz))
- result = result | mlir::LLVM::FastmathFlags::nsz;
- if (bitEnumContainsAll(src, cir::FastMathFlags::nnan))
- result = result | mlir::LLVM::FastmathFlags::nnan;
- if (bitEnumContainsAll(src, cir::FastMathFlags::ninf))
- result = result | mlir::LLVM::FastmathFlags::ninf;
- if (bitEnumContainsAll(src, cir::FastMathFlags::arcp))
- result = result | mlir::LLVM::FastmathFlags::arcp;
- if (bitEnumContainsAll(src, cir::FastMathFlags::contract))
- result = result | mlir::LLVM::FastmathFlags::contract;
- if (bitEnumContainsAll(src, cir::FastMathFlags::afn))
- result = result | mlir::LLVM::FastmathFlags::afn;
- if (bitEnumContainsAll(src, cir::FastMathFlags::reassoc))
- result = result | mlir::LLVM::FastmathFlags::reassoc;
- return result;
-}
-
static mlir::LLVM::CallIntrinsicOp
createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter,
mlir::Location loc, const llvm::Twine &intrinsicName,
@@ -584,9 +561,7 @@ mlir::LogicalResult lowerConstrainableFPOp(
return op->emitError("expected LLVM result type for floating-point op");
if (!fenv) {
- rewriter.replaceOpWithNewOp<LLVMOp>(
- op, mlir::TypeRange{llvmResTy}, operands,
- cir::getDefaultProperties<LLVMOp>(op->getContext()));
+ rewriter.replaceOpWithNewOp<LLVMOp>(op, llvmResTy, operands);
return mlir::success();
}
@@ -2058,13 +2033,13 @@ mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
cir::FMaxNumOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::Type resTy = typeConverter->convertType(op.getType());
- mlir::LLVM::FastmathFlags fmf = convertCIRFastMathFlags(op.getFastmathAttr());
if (cir::FenvAttr fenv = op.getFenvAttr())
- return lowerToConstrainedFPIntrinsic(op, adaptor.getOperands(), fenv, resTy,
- rewriter, "maxnum",
- /*hasRoundingMode=*/false, fmf);
- rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(op, resTy, adaptor.getLhs(),
- adaptor.getRhs(), fmf);
+ return lowerToConstrainedFPIntrinsic(
+ op, adaptor.getOperands(), fenv, resTy, rewriter, "maxnum",
+ /*hasRoundingMode=*/false, mlir::LLVM::FastmathFlags::nsz);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
+ op, resTy, adaptor.getLhs(), adaptor.getRhs(),
+ mlir::LLVM::FastmathFlags::nsz);
return mlir::success();
}
@@ -2072,13 +2047,13 @@ mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
cir::FMinNumOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::Type resTy = typeConverter->convertType(op.getType());
- mlir::LLVM::FastmathFlags fmf = convertCIRFastMathFlags(op.getFastmathAttr());
if (cir::FenvAttr fenv = op.getFenvAttr())
- return lowerToConstrainedFPIntrinsic(op, adaptor.getOperands(), fenv, resTy,
- rewriter, "minnum",
- /*hasRoundingMode=*/false, fmf);
- rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(op, resTy, adaptor.getLhs(),
- adaptor.getRhs(), fmf);
+ return lowerToConstrainedFPIntrinsic(
+ op, adaptor.getOperands(), fenv, resTy, rewriter, "minnum",
+ /*hasRoundingMode=*/false, mlir::LLVM::FastmathFlags::nsz);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
+ op, resTy, adaptor.getLhs(), adaptor.getRhs(),
+ mlir::LLVM::FastmathFlags::nsz);
return mlir::success();
}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c b/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
index 463504ce8e5c4..cc8b6dfe2efbd 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-maxnum-minnum.c
@@ -15,7 +15,8 @@ typedef long double ldouble2 __attribute__((ext_vector_type(2)));
// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.f16>
//
// LLVM-LABEL: @_Z7pfmin16Dv8_DF16_S_(
-// LLVM: call <8 x half> @llvm.minnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
+// FIXME(cir): Classic codegen doesn't emit a nsz for all of these.
+// LLVM: call {{.*}}<8 x half> @llvm.minnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
//
half8 pfmin16(half8 a, half8 b) {
return __builtin_elementwise_minnum(a, b);
@@ -24,7 +25,7 @@ half8 pfmin16(half8 a, half8 b) {
// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.bf16>
//
// LLVM-LABEL: @_Z8pfmin16bDv8_DF16bS_(
-// LLVM: call <8 x bfloat> @llvm.minnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
+// LLVM: call {{.*}}<8 x bfloat> @llvm.minnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
//
bf16x8 pfmin16b(bf16x8 a, bf16x8 b) {
return __builtin_elementwise_minnum(a, b);
@@ -33,7 +34,7 @@ bf16x8 pfmin16b(bf16x8 a, bf16x8 b) {
// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float>
//
// LLVM-LABEL: @_Z7pfmin32Dv4_fS_(
-// LLVM: call <4 x float> @llvm.minnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+// LLVM: call {{.*}}<4 x float> @llvm.minnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
//
float4 pfmin32(float4 a, float4 b) {
return __builtin_elementwise_minnum(a, b);
@@ -42,7 +43,7 @@ float4 pfmin32(float4 a, float4 b) {
// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.double>
//
// LLVM-LABEL: @_Z7pfmin64Dv2_dS_(
-// LLVM: call <2 x double> @llvm.minnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+// LLVM: call {{.*}}<2 x double> @llvm.minnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
//
double2 pfmin64(double2 a, double2 b) {
return __builtin_elementwise_minnum(a, b);
@@ -51,7 +52,7 @@ double2 pfmin64(double2 a, double2 b) {
// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.long_double<!cir.f80>>
//
// LLVM-LABEL: @_Z7pfmin80v(
-// LLVM: call <2 x x86_fp80> @llvm.minnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
+// LLVM: call {{.*}}<2 x x86_fp80> @llvm.minnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
//
void pfmin80() {
ldouble2 a, b;
@@ -62,7 +63,7 @@ void pfmin80() {
// CIR: cir.fmaxnum %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.f16>
//
// LLVM-LABEL: @_Z7pfmax16Dv8_DF16_S_(
-// LLVM: call <8 x half> @llvm.maxnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
+// LLVM: call {{.*}}<8 x half> @llvm.maxnum.v8f16(<8 x half> %{{.*}}, <8 x half> %{{.*}})
//
half8 pfmax16(half8 a, half8 b) {
return __builtin_elementwise_maxnum(a, b);
@@ -71,7 +72,7 @@ half8 pfmax16(half8 a, half8 b) {
// CIR: cir.fmaxnum %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.bf16>
//
// LLVM-LABEL: @_Z8pfmax16bDv8_DF16bS_(
-// LLVM: call <8 x bfloat> @llvm.maxnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
+// LLVM: call {{.*}}<8 x bfloat> @llvm.maxnum.v8bf16(<8 x bfloat> %{{.*}}, <8 x bfloat> %{{.*}})
//
bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
return __builtin_elementwise_maxnum(a, b);
@@ -80,7 +81,7 @@ bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
// CIR: cir.fmaxnum %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float>
//
// LLVM-LABEL: @_Z7pfmax32Dv4_fS_(
-// LLVM: call <4 x float> @llvm.maxnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+// LLVM: call {{.*}}<4 x float> @llvm.maxnum.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
//
float4 pfmax32(float4 a, float4 b) {
return __builtin_elementwise_maxnum(a, b);
@@ -89,7 +90,7 @@ float4 pfmax32(float4 a, float4 b) {
// CIR: cir.fmaxnum %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.double>
//
// LLVM-LABEL: @_Z7pfmax64Dv2_dS_(
-// LLVM: call <2 x double> @llvm.maxnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+// LLVM: call {{.*}}<2 x double> @llvm.maxnum.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}})
//
double2 pfmax64(double2 a, double2 b) {
return __builtin_elementwise_maxnum(a, b);
@@ -99,7 +100,7 @@ double2 pfmax64(double2 a, double2 b) {
// CIR: cir.fminnum %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.long_double<!cir.f80>>
//
// LLVM-LABEL: @_Z7pfmax80v(
-// LLVM: call <2 x x86_fp80> @llvm.minnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
+// LLVM: call {{.*}}<2 x x86_fp80> @llvm.minnum.v2f80(<2 x x86_fp80> %{{.*}}, <2 x x86_fp80> %{{.*}})
//
void pfmax80() {
ldouble2 a, b;
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
index 70defd9ae7f72..701f9c94d5240 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
@@ -806,7 +806,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
// LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
- // LLVM-NEXT: call float @llvm.minnum.f32(float [[F1]], float [[F2]])
+ // LLVM-NEXT: call {{.*}}float @llvm.minnum.f32(float [[F1]], float [[F2]])
f1 = __builtin_elementwise_min(f1, f2);
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
@@ -815,7 +815,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
// LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
- // LLVM-NEXT: call double @llvm.minnum.f64(double [[D1]], double [[D2]])
+ // LLVM-NEXT: call {{.*}}double @llvm.minnum.f64(double [[D1]], double [[D2]])
d1 = __builtin_elementwise_min(d1, d2);
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
@@ -823,7 +823,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR-NEXT: cir.fminnum %[[D1_LOAD]], %[[TWO]] : !cir.double
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
- // LLVM-NEXT: call double @llvm.minnum.f64(double [[D1]], double 2.000000e+00)
+ // LLVM-NEXT: call {{.*}}double @llvm.minnum.f64(double [[D1]], double 2.000000e+00)
d1 = __builtin_elementwise_min(d1, 2.0);
// CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
@@ -832,12 +832,12 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
- // LLVM-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
+ // LLVM-NEXT: call {{.*}}<4 x float> @llvm.minnum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
vf1 = __builtin_elementwise_min(vf1, vf2);
// CIR: %[[I1_LOAD:.*]] = cir.load align(8) %[[I1]] : !cir.ptr<!s64i>, !s64i
// CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
- // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[I1_LOAD]], %[[I2_LOAD]] : (!s64i, !s64i) -> !s64i
+ // CIR-NEXT: cir.min %[[I1_LOAD]], %[[I2_LOAD]] : !s64i
// LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
// LLVM-NEXT: [[I2:%.+]] = load i64, ptr %[[ADDR_I2]], align 8
@@ -846,7 +846,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[NEG_11:.*]] = cir.const #cir.int<-11> : !s64i
// CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
- // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[NEG_11]], %[[I2_LOAD]] : (!s64i, !s64i) -> !s64i
+ // CIR-NEXT: cir.min %[[I2_LOAD]], %[[NEG_11]] : !s64i
// LLVM: [[I2:%.+]] = load i64, ptr %[[ADDR_I2]], align 8
// LLVM-NEXT: call i64 @llvm.smin.i64(i64 -11, i64 [[I2]])
@@ -856,7 +856,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR-NEXT: %[[I1_TRUNC:.*]] = cir.cast integral %[[I1_LOAD]] : !s64i -> !s16i
// CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
// CIR-NEXT: %[[I2_TRUNC:.*]] = cir.cast integral %[[I2_LOAD]] : !s64i -> !s16i
- // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[I1_TRUNC]], %[[I2_TRUNC]] : (!s16i, !s16i) -> !s16i
+ // CIR-NEXT: cir.min %[[I1_TRUNC]], %[[I2_TRUNC]] : !s16i
// LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
// LLVM: [[S1:%.+]] = trunc i64 [[I1]] to i16
@@ -867,7 +867,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[VI1_LOAD:.*]] = cir.load align(16) %[[VI1]] : !cir.ptr<!cir.vector<8 x !s16i>>, !cir.vector<8 x !s16i>
// CIR-NEXT: %[[VI2_LOAD:.*]] = cir.load align(16) %[[VI2]] : !cir.ptr<!cir.vector<8 x !s16i>>, !cir.vector<8 x !s16i>
- // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[VI1_LOAD]], %[[VI2_LOAD]] : (!cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+ // CIR-NEXT: cir.min %[[VI1_LOAD]], %[[VI2_LOAD]] : !cir.vector<8 x !s16i>
// LLVM: [[VI1:%.+]] = load <8 x i16>, ptr %[[ADDR_VI1]], align 16
// LLVM-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %[[ADDR_VI2]], align 16
// LLVM-NEXT: call <8 x i16> @llvm.smin.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]])
@@ -875,7 +875,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[U1_LOAD:.*]] = cir.load align(4) %[[U1]] : !cir.ptr<!u32i>, !u32i
// CIR-NEXT: %[[U2_LOAD:.*]] = cir.load align(4) %[[U2]] : !cir.ptr<!u32i>, !u32i
- // CIR-NEXT: cir.call_llvm_intrinsic "umin" %[[U1_LOAD]], %[[U2_LOAD]] : (!u32i, !u32i) -> !u32i
+ // CIR-NEXT: cir.min %[[U1_LOAD]], %[[U2_LOAD]] : !u32i
// LLVM: [[U1:%.+]] = load i32, ptr %[[ADDR_U1]], align 4
// LLVM-NEXT: [[U2:%.+]] = load i32, ptr %[[ADDR_U2]], align 4
@@ -884,7 +884,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[VU1_LOAD:.*]] = cir.load align(16) %[[VU1]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
// CIR-NEXT: %[[VU2_LOAD:.*]] = cir.load align(16) %[[VU2]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
- // CIR-NEXT: cir.call_llvm_intrinsic "umin" %[[VU1_LOAD]], %[[VU2_LOAD]] : (!cir.vector<4 x !u32i>, !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
+ // CIR-NEXT: cir.min %[[VU1_LOAD]], %[[VU2_LOAD]] : !cir.vector<4 x !u32i>
// LLVM: [[VU1:%.+]] = load <4 x i32>, ptr %[[ADDR_VU1]], align 16
// LLVM-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %[[ADDR_VU2]], align 16
@@ -893,7 +893,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[BI1_LOAD:.*]] = cir.load align(4) %[[BI1]] : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint>
// CIR-NEXT: %[[BI2_LOAD:.*]] = cir.load align(4) %[[BI2]] : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint>
- // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[BI1_LOAD]], %[[BI2_LOAD]] : (!cir.int<s, 31, bitint>, !cir.int<s, 31, bitint>) -> !cir.int<s, 31, bitint>
+ // CIR-NEXT: cir.min %[[BI1_LOAD]], %[[BI2_LOAD]] : !cir.int<s, 31, bitint>
// LLVM: [[BI1:%.+]] = load i32, ptr %[[ADDR_BI1]], align 4
// LLVM-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31
@@ -904,7 +904,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// CIR: %[[BU1_LOAD:.*]] = cir.load align(8) %[[BU1]] : !cir.ptr<!cir.int<u, 55, bitint>>, !cir.int<u, 55, bitint>
// CIR-NEXT: %[[BU2_LOAD:.*]] = cir.load align(8) %[[BU2]] : !cir.ptr<!cir.int<u, 55, bitint>>, !cir.int<u, 55, bitint>
- // CIR-NEXT: cir.call_llvm_intrinsic "umin" %[[BU1_LOAD]], %[[BU2_LOAD]] : (!cir.int<u, 55, bitint>, !cir.int<u, 55, bitint>) -> !cir.int<u, 55, bitint>
+ // CIR-NEXT: cir.min %[[BU1_LOAD]], %[[BU2_LOAD]] : !cir.int<u, 55, bitint>
// LLVM: [[BU1:%.+]] = load i64, ptr %[[ADDR_BU1]], align 8
// LLVM-NEXT: [[LOADEDV2:%.+]] = trunc i64 [[BU1]] to i55
@@ -919,7 +919,7 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
- // LLVM-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
+ // LLVM-NEXT: call {{.*}}<4 x float> @llvm.minnum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
const float4 cvf1 = vf1;
vf1 = __builtin_elementwise_min(cvf1, vf2);
@@ -929,14 +929,14 @@ void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,
// LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
// LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
- // LLVM-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
+ // LLVM-NEXT: call {{.*}}<4 x float> @llvm.minnum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
vf1 = __builtin_elementwise_min(vf2, cvf1);
// CIR: %[[IAONE:.*]] = cir.get_global @int_as_one : !cir.ptr<!s32i, target_address_space(1)>
// CIR-NEXT: %[[IAO_LOAD:.*]] = cir.load align(4) %[[IAONE]] : !cir.ptr<!s32i, target_address_space(1)>, !s32i
// CIR-NEXT: %[[B:.*]] = cir.get_global @b : !cir.ptr<!s32i>
// CIR-NEXT: %[[B_LOAD:.*]] = cir.load align(4) %[[B]] : !cir.ptr<!s32i>, !s32i
- // CIR-NEXT: cir.call_llvm_intrinsic "smin" %[[IAO_LOAD]], %[[B_LOAD]] : (!s32i, !s32i) -> !s32i
+ // CIR-NEXT: cir.min %[[IAO_LOAD]], %[[B_LOAD]] : !s32i
// LLVM: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4
// LLVM-NEXT: [[B:%.+]] = load i32, ptr @b, align 4
@@ -1109,7 +1109,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// LLVM: [[F1:%.+]] = load float, ptr %[[ADDR_F1]], align 4
// LLVM-NEXT: [[F2:%.+]] = load float, ptr %[[ADDR_F2]], align 4
- // LLVM-NEXT: call float @llvm.maxnum.f32(float [[F1]], float [[F2]])
+ // LLVM-NEXT: call {{.*}}float @llvm.maxnum.f32(float [[F1]], float [[F2]])
f1 = __builtin_elementwise_max(f1, f2);
// CIR: %[[D1_LOAD:.*]] = cir.load align(8) %[[D1]] : !cir.ptr<!cir.double>, !cir.double
@@ -1118,7 +1118,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// LLVM: [[D1:%.+]] = load double, ptr %[[ADDR_D1]], align 8
// LLVM-NEXT: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
- // LLVM-NEXT: call double @llvm.maxnum.f64(double [[D1]], double [[D2]])
+ // LLVM-NEXT: call {{.*}}double @llvm.maxnum.f64(double [[D1]], double [[D2]])
d1 = __builtin_elementwise_max(d1, d2);
// CIR: %[[TWENTY:.*]] = cir.const #cir.fp<2.000000e+01> : !cir.double
@@ -1126,7 +1126,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR-NEXT: cir.fmaxnum %[[TWENTY]], %[[D2_LOAD]] : !cir.double
// LLVM: [[D2:%.+]] = load double, ptr %[[ADDR_D2]], align 8
- // LLVM-NEXT: call double @llvm.maxnum.f64(double 2.000000e+01, double [[D2]])
+ // LLVM-NEXT: call {{.*}}double @llvm.maxnum.f64(double 2.000000e+01, double [[D2]])
d1 = __builtin_elementwise_max(20.0, d2);
// CIR: %[[VF1_LOAD:.*]] = cir.load align(16) %[[VF1]] : !cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
@@ -1135,12 +1135,12 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// LLVM: [[VF1:%.+]] = load <4 x float>, ptr %[[ADDR_VF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
- // LLVM-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
+ // LLVM-NEXT: call {{.*}}<4 x float> @llvm.maxnum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
vf1 = __builtin_elementwise_max(vf1, vf2);
// CIR: %[[I1_LOAD:.*]] = cir.load align(8) %[[I1]] : !cir.ptr<!s64i>, !s64i
// CIR-NEXT: %[[I2_LOAD:.*]] = cir.load align(8) %[[I2]] : !cir.ptr<!s64i>, !s64i
- // CIR-NEXT: cir.call_llvm_intrinsic "smax" %31, %32 : (!s64i, !s64i) -> !s64i
+ // CIR-NEXT: cir.max %[[I1_LOAD]], %[[I2_LOAD]] : !s64i
// LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
// LLVM-NEXT: [[I2:%.+]] = load i64, ptr %[[ADDR_I2]], align 8
@@ -1149,7 +1149,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[I1_LOAD:.*]] = cir.load align(8) %[[I1]] : !cir.ptr<!s64i>, !s64i
// CIR-NEXT: %[[TEN:.*]] = cir.const #cir.int<10> : !s64i
- // CIR-NEXT: cir.call_llvm_intrinsic "smax" %[[I1_LOAD]], %[[TEN]] : (!s64i, !s64i) -> !s64i
+ // CIR-NEXT: cir.max %[[I1_LOAD]], %[[TEN]] : !s64i
// LLVM: [[I1:%.+]] = load i64, ptr %[[ADDR_I1]], align 8
// LLVM-NEXT: call i64 @llvm.smax.i64(i64 [[I1]], i64 10)
@@ -1157,7 +1157,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[VI1_LOAD:.*]] = cir.load align(16) %[[VI1]] : !cir.ptr<!cir.vector<8 x !s16i>>, !cir.vector<8 x !s16i>
// CIR-NEXT: %[[VI2_LOAD:.*]] = cir.load align(16) %[[VI2]] : !cir.ptr<!cir.vector<8 x !s16i>>, !cir.vector<8 x !s16i>
- // CIR-NEXT: cir.call_llvm_intrinsic "smax" %[[VI1_LOAD]], %[[VI2_LOAD]] : (!cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+ // CIR-NEXT: cir.max %[[VI1_LOAD]], %[[VI2_LOAD]] : !cir.vector<8 x !s16i>
// LLVM: [[VI1:%.+]] = load <8 x i16>, ptr %[[ADDR_VI1]], align 16
// LLVM-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %[[ADDR_VI2]], align 16
@@ -1166,7 +1166,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[U1_LOAD:.*]] = cir.load align(4) %[[U1]] : !cir.ptr<!u32i>, !u32i
// CIR-NEXT: %[[U2_LOAD:.*]] = cir.load align(4) %[[U2]] : !cir.ptr<!u32i>, !u32i
- // CIR-NEXT: cir.call_llvm_intrinsic "umax" %[[U1_LOAD]], %[[U2_LOAD]] : (!u32i, !u32i) -> !u32i
+ // CIR-NEXT: cir.max %[[U1_LOAD]], %[[U2_LOAD]] : !u32i
// LLVM: [[U1:%.+]] = load i32, ptr %[[ADDR_U1]], align 4
// LLVM-NEXT: [[U2:%.+]] = load i32, ptr %[[ADDR_U2]], align 4
@@ -1175,7 +1175,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[VU1_LOAD:.*]] = cir.load align(16) %[[VU1]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
// CIR-NEXT: %[[VU2_LOAD:.*]] = cir.load align(16) %[[VU2]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
- // CIR-NEXT: cir.call_llvm_intrinsic "umax" %[[VU1_LOAD]], %[[VU2_LOAD]] : (!cir.vector<4 x !u32i>, !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
+ // CIR-NEXT: cir.max %[[VU1_LOAD]], %[[VU2_LOAD]] : !cir.vector<4 x !u32i>
// LLVM: [[VU1:%.+]] = load <4 x i32>, ptr %[[ADDR_VU1]], align 16
// LLVM-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %[[ADDR_VU2]], align 16
@@ -1184,7 +1184,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[BI1_LOAD:.*]] = cir.load align(4) %[[BI1]] : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint>
// CIR-NEXT: %[[BI2_LOAD:.*]] = cir.load align(4) %[[BI2]] : !cir.ptr<!cir.int<s, 31, bitint>>, !cir.int<s, 31, bitint>
- // CIR-NEXT: cir.call_llvm_intrinsic "smax" %[[BI1_LOAD]], %[[BI2_LOAD]] : (!cir.int<s, 31, bitint>, !cir.int<s, 31, bitint>) -> !cir.int<s, 31, bitint>
+ // CIR-NEXT: cir.max %[[BI1_LOAD]], %[[BI2_LOAD]] : !cir.int<s, 31, bitint>
// LLVM: [[BI1:%.+]] = load i32, ptr %[[ADDR_BI1]], align 4
// LLVM-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31
@@ -1195,7 +1195,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// CIR: %[[BU1_LOAD:.*]] = cir.load align(8) %[[BU1]] : !cir.ptr<!cir.int<u, 55, bitint>>, !cir.int<u, 55, bitint>
// CIR-NEXT: %[[BU2_LOAD:.*]] = cir.load align(8) %[[BU2]] : !cir.ptr<!cir.int<u, 55, bitint>>, !cir.int<u, 55, bitint>
- // CIR-NEXT: cir.call_llvm_intrinsic "umax" %[[BU1_LOAD]], %[[BU2_LOAD]] : (!cir.int<u, 55, bitint>, !cir.int<u, 55, bitint>) -> !cir.int<u, 55, bitint>
+ // CIR-NEXT: cir.max %[[BU1_LOAD]], %[[BU2_LOAD]] : !cir.int<u, 55, bitint>
// LLVM: [[BU1:%.+]] = load i64, ptr %[[ADDR_BU1]], align 8
// LLVM-NEXT: [[LOADEDV2:%.+]] = trunc i64 [[BU1]] to i55
@@ -1210,7 +1210,7 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// LLVM: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
// LLVM-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
- // LLVM-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
+ // LLVM-NEXT: call {{.*}}<4 x float> @llvm.maxnum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
const float4 cvf1 = vf1;
vf1 = __builtin_elementwise_max(cvf1, vf2);
@@ -1220,14 +1220,14 @@ void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
// LLVM: [[VF2:%.+]] = load <4 x float>, ptr %[[ADDR_VF2]], align 16
// LLVM-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %[[ADDR_CVF1]], align 16
- // LLVM-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
+ // LLVM-NEXT: call {{.*}}<4 x float> @llvm.maxnum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
vf1 = __builtin_elementwise_max(vf2, cvf1);
// CIR: %[[IAONE:.*]] = cir.get_global @int_as_one : !cir.ptr<!s32i, target_address_space(1)>
// CIR-NEXT: %[[IAO_LOAD:.*]] = cir.load align(4) %[[IAONE]] : !cir.ptr<!s32i, target_address_space(1)>, !s32i
// CIR-NEXT: %[[B:.*]] = cir.get_global @b : !cir.ptr<!s32i>
// CIR-NEXT: %[[B_LOAD:.*]] = cir.load align(4) %[[B]] : !cir.ptr<!s32i>, !s32i
- // CIR-NEXT: cir.call_llvm_intrinsic "smax" %[[IAO_LOAD]], %[[B_LOAD]] : (!s32i, !s32i) -> !s32i
+ // CIR-NEXT: cir.max %[[IAO_LOAD]], %[[B_LOAD]] : !s32i
// LLVM: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4
// LLVM-NEXT: [[B:%.+]] = load i32, ptr @b, align 4
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
index cac0d6a3a02d3..47f01bebfe90c 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-floating-point.c
@@ -1944,7 +1944,7 @@ long double call_copysignl(long double x, long double y) {
float my_fmaxf(float x, float y) {
return __builtin_fmaxf(x, y);
// CIR: cir.func no_inline dso_local @my_fmaxf
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.float {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.float
// LLVM: define dso_local float @my_fmaxf
// LLVM: call nsz float @llvm.maxnum.f32(float %{{.+}}, float %{{.+}})
@@ -1957,7 +1957,7 @@ float my_fmaxf(float x, float y) {
double my_fmax(double x, double y) {
return __builtin_fmax(x, y);
// CIR: cir.func no_inline dso_local @my_fmax
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.double {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.double
// LLVM: define dso_local double @my_fmax
// LLVM: call nsz double @llvm.maxnum.f64(double %{{.+}}, double %{{.+}})
@@ -1970,8 +1970,8 @@ double my_fmax(double x, double y) {
long double my_fmaxl(long double x, long double y) {
return __builtin_fmaxl(x, y);
// CIR: cir.func no_inline dso_local @my_fmaxl
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80> {fastmath = #cir.fastmath<nsz>}
- // AARCH64: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double> {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80>
+ // AARCH64: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double>
// LLVM: define dso_local x86_fp80 @my_fmaxl
// LLVM: call nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
@@ -1988,7 +1988,7 @@ long double fmaxl(long double, long double);
float call_fmaxf(float x, float y) {
return fmaxf(x, y);
// CIR: cir.func no_inline dso_local @call_fmaxf
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.float {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.float
// LLVM: define dso_local float @call_fmaxf
// LLVM: call nsz float @llvm.maxnum.f32(float %{{.+}}, float %{{.+}})
@@ -2001,7 +2001,7 @@ float call_fmaxf(float x, float y) {
double call_fmax(double x, double y) {
return fmax(x, y);
// CIR: cir.func no_inline dso_local @call_fmax
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.double {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.double
// LLVM: define dso_local double @call_fmax
// LLVM: call nsz double @llvm.maxnum.f64(double %{{.+}}, double %{{.+}})
@@ -2014,8 +2014,8 @@ double call_fmax(double x, double y) {
long double call_fmaxl(long double x, long double y) {
return fmaxl(x, y);
// CIR: cir.func no_inline dso_local @call_fmaxl
- // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80> {fastmath = #cir.fastmath<nsz>}
- // AARCH64: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double> {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80>
+ // AARCH64: cir.fmaxnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double>
// LLVM: define dso_local x86_fp80 @call_fmaxl
// LLVM: call nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
@@ -2030,7 +2030,7 @@ long double call_fmaxl(long double x, long double y) {
float my_fminf(float x, float y) {
return __builtin_fminf(x, y);
// CIR: cir.func no_inline dso_local @my_fminf
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.float {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.float
// LLVM: define dso_local float @my_fminf
// LLVM: call nsz float @llvm.minnum.f32(float %{{.+}}, float %{{.+}})
@@ -2043,7 +2043,7 @@ float my_fminf(float x, float y) {
double my_fmin(double x, double y) {
return __builtin_fmin(x, y);
// CIR: cir.func no_inline dso_local @my_fmin
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.double {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.double
// LLVM: define dso_local double @my_fmin
// LLVM: call nsz double @llvm.minnum.f64(double %{{.+}}, double %{{.+}})
@@ -2056,8 +2056,8 @@ double my_fmin(double x, double y) {
long double my_fminl(long double x, long double y) {
return __builtin_fminl(x, y);
// CIR: cir.func no_inline dso_local @my_fminl
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80> {fastmath = #cir.fastmath<nsz>}
- // AARCH64: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double> {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80>
+ // AARCH64: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double>
// LLVM: define dso_local x86_fp80 @my_fminl
// LLVM: call nsz x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
@@ -2074,7 +2074,7 @@ long double fminl(long double, long double);
float call_fminf(float x, float y) {
return fminf(x, y);
// CIR: cir.func no_inline dso_local @call_fminf
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.float {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.float
// LLVM: define dso_local float @call_fminf
// LLVM: call nsz float @llvm.minnum.f32(float %{{.+}}, float %{{.+}})
@@ -2087,7 +2087,7 @@ float call_fminf(float x, float y) {
double call_fmin(double x, double y) {
return fmin(x, y);
// CIR: cir.func no_inline dso_local @call_fmin
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.double {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.double
// LLVM: define dso_local double @call_fmin
// LLVM: call nsz double @llvm.minnum.f64(double %{{.+}}, double %{{.+}})
@@ -2100,8 +2100,8 @@ double call_fmin(double x, double y) {
long double call_fminl(long double x, long double y) {
return fminl(x, y);
// CIR: cir.func no_inline dso_local @call_fminl
- // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80> {fastmath = #cir.fastmath<nsz>}
- // AARCH64: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double> {fastmath = #cir.fastmath<nsz>}
+ // CIR: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.f80>
+ // AARCH64: cir.fminnum %{{.+}}, %{{.+}} : !cir.long_double<!cir.double>
// LLVM: define dso_local x86_fp80 @call_fminl
// LLVM: call nsz x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
More information about the cfe-commits
mailing list