https://github.com/borysperski updated https://github.com/llvm/llvm-project/pull/215787
>From df49b7b85f79003a47f126a3cd30ca67b723b73f Mon Sep 17 00:00:00 2001 From: Borys Perski <[email protected]> Date: Wed, 12 Aug 2026 14:12:55 +0200 Subject: [PATCH 1/2] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 91 +++++++ .../CIR/CodeGenBuiltins/X86/avx-builtins.c | 120 +++++++++ .../CIR/CodeGenBuiltins/X86/sse41-builtins.c | 253 ++++++++++++++++++ 3 files changed, 464 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 9228367fdd44f..e1ce2e99e67b6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -86,6 +86,26 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, return maskVec; } +static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder, + mlir::Location loc, mlir::Value x, + unsigned roundingControl) { + constexpr unsigned roundingMask = 0b11; + unsigned roundingMode = roundingControl & roundingMask; + + switch (roundingMode) { + default: + llvm_unreachable("Invalid rounding mode"); + case 0b00: + return cir::RoundEvenOp::create(builder, loc, x); + case 0b01: + return cir::FloorOp::create(builder, loc, x); + case 0b10: + return cir::CeilOp::create(builder, loc, x); + case 0b11: + return cir::TruncOp::create(builder, loc, x); + } +} + static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder, mlir::Location loc, ArrayRef<mlir::Value> ops) { @@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { // Return timestamp (element 0 of the returned struct) return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0); } + case X86::BI__builtin_ia32_roundps: + case X86::BI__builtin_ia32_roundpd: + case X86::BI__builtin_ia32_roundps256: + case X86::BI__builtin_ia32_roundpd256: { + unsigned m = + ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue(); + constexpr unsigned mxcsrMask = 0b100; + constexpr unsigned fRoundNoExcMask = 0b1000; + unsigned useMXCSR = mxcsrMask & m; + unsigned fRoundNoExc = fRoundNoExcMask & m; + + mlir::Location loc = getLoc(expr->getExprLoc()); + + if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: + llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundps: + intrinsicName = "x86.sse41.round.ps"; + break; + case X86::BI__builtin_ia32_roundpd: + intrinsicName = "x86.sse41.round.pd"; + break; + case X86::BI__builtin_ia32_roundps256: + intrinsicName = "x86.avx.round.ps.256"; + break; + case X86::BI__builtin_ia32_roundpd256: + intrinsicName = "x86.avx.round.pd.256"; + break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); + } + + return emitX86RoundImmediate(builder, loc, ops[0], m); + } + case X86::BI__builtin_ia32_roundss: + case X86::BI__builtin_ia32_roundsd: { + unsigned m = + ops[2].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue(); + constexpr unsigned mxcsrMask = 0b100; + constexpr unsigned fRoundNoExcMask = 0b1000; + unsigned useMXCSR = mxcsrMask & m; + unsigned fRoundNoExc = fRoundNoExcMask & m; + + mlir::Location loc = getLoc(expr->getExprLoc()); + + if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: + llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundss: + intrinsicName = "x86.sse41.round.ss"; + break; + case X86::BI__builtin_ia32_roundsd: + intrinsicName = "x86.sse41.round.sd"; + break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); + } + + mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0); + mlir::Value roundedAt0 = emitX86RoundImmediate(builder, loc, valAt0, m); + + return builder.createInsertElement(loc, ops[0], roundedAt0, 0); + } case X86::BI__builtin_ia32_lzcnt_u16: case X86::BI__builtin_ia32_lzcnt_u32: case X86::BI__builtin_ia32_lzcnt_u64: { diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c index 174fcbc7b0080..773702af5ea25 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c @@ -30,6 +30,54 @@ #include <immintrin.h> +__m256d test_mm256_ceil_pd(__m256d x) { + // CIR-LABEL: test_mm256_ceil_pd + // CIR: cir.call_llvm_intrinsic "x86.avx.round.pd.256" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.double>, !s32i) -> !cir.vector<4 x !cir.double> + + // LLVM-LABEL: test_mm256_ceil_pd + // LLVM: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 2) + + // OGCG-LABEL: test_mm256_ceil_pd + // OGCG: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 2) + return _mm256_ceil_pd(x); +} + +__m256 test_mm_ceil_ps(__m256 x) { + // CIR-LABEL: test_mm_ceil_ps + // CIR: cir.call_llvm_intrinsic "x86.avx.round.ps.256" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.float>, !s32i) -> !cir.vector<8 x !cir.float> + + // LLVM-LABEL: test_mm_ceil_ps + // LLVM: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 2) + + // OGCG-LABEL: test_mm_ceil_ps + // OGCG: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 2) + return _mm256_ceil_ps(x); +} + +__m256d test_mm256_floor_pd(__m256d x) { + // CIR-LABEL: test_mm256_floor_pd + // CIR: cir.call_llvm_intrinsic "x86.avx.round.pd.256" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.double>, !s32i) -> !cir.vector<4 x !cir.double> + + // LLVM-LABEL: test_mm256_floor_pd + // LLVM: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 1) + + // OGCG-LABEL: test_mm256_floor_pd + // OGCG: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 1) + return _mm256_floor_pd(x); +} + +__m256 test_mm_floor_ps(__m256 x) { + // CIR-LABEL: test_mm_floor_ps + // CIR: cir.call_llvm_intrinsic "x86.avx.round.ps.256" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.float>, !s32i) -> !cir.vector<8 x !cir.float> + + // LLVM-LABEL: test_mm_floor_ps + // LLVM: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 1) + + // OGCG-LABEL: test_mm_floor_ps + // OGCG: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 1) + return _mm256_floor_ps(x); +} + __m256 test_mm256_undefined_ps(void) { // CIR-LABEL: _mm256_undefined_ps // CIR: %[[A:.*]] = cir.const #cir.zero : !cir.vector<4 x !cir.double> @@ -253,3 +301,75 @@ __m256i test_mm256_permute2f128_si256(__m256i A, __m256i B) { // OGCG: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> return _mm256_permute2f128_si256(A, B, 0x20); } + +__m256d test_mm256_round_pd(__m256d x) { + // CIR-LABEL: test_mm256_round_pd + // CIR: cir.roundeven %{{.*}} : !cir.vector<4 x !cir.double> + + // LLVM-LABEL: test_mm256_round_pd + // LLVM: call <4 x double> @llvm.roundeven.v4f64(<4 x double> %{{.*}}) + + // OGCG-LABEL: test_mm256_round_pd + // OGCG: call <4 x double> @llvm.roundeven.v4f64(<4 x double> %{{.*}}) + return _mm256_round_pd(x, 0b1000); +} + +__m256d test_mm256_round_pd_mxcsr(__m256d x) { + // CIR-LABEL: test_mm256_round_pd_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.avx.round.pd.256" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.double>, !s32i) -> !cir.vector<4 x !cir.double> + + // LLVM-LABEL: test_mm256_round_pd_mxcsr + // LLVM: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm256_round_pd_mxcsr + // OGCG: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 12) + return _mm256_round_pd(x, 0b1100); +} + +__m256d test_mm256_round_pd_fround_no_exc(__m256d x) { + // CIR-LABEL: test_mm256_round_pd_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.avx.round.pd.256" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.double>, !s32i) -> !cir.vector<4 x !cir.double> + + // LLVM-LABEL: test_mm256_round_pd_fround_no_exc + // LLVM: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm256_round_pd_fround_no_exc + // OGCG: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 0) + return _mm256_round_pd(x, 0b0000); +} + +__m256 test_mm256_round_ps(__m256 x) { + // CIR-LABEL: test_mm256_round_ps + // CIR: cir.roundeven %{{.*}} : !cir.vector<8 x !cir.float> + + // LLVM-LABEL: test_mm256_round_ps + // LLVM: call <8 x float> @llvm.roundeven.v8f32(<8 x float> %{{.*}}) + + // OGCG-LABEL: test_mm256_round_ps + // OGCG: call <8 x float> @llvm.roundeven.v8f32(<8 x float> %{{.*}}) + return _mm256_round_ps(x, 0b1000); +} + +__m256 test_mm256_round_ps_mxcsr(__m256 x) { + // CIR-LABEL: test_mm256_round_ps_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.avx.round.ps.256" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.float>, !s32i) -> !cir.vector<8 x !cir.float> + + // LLVM-LABEL: test_mm256_round_ps_mxcsr + // LLVM: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm256_round_ps_mxcsr + // OGCG: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 12) + return _mm256_round_ps(x, 0b1100); +} + +__m256 test_mm256_round_ps_fround_no_exc(__m256 x) { + // CIR-LABEL: test_mm256_round_ps_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.avx.round.ps.256" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.float>, !s32i) -> !cir.vector<8 x !cir.float> + + // LLVM-LABEL: test_mm256_round_ps_fround_no_exc + // LLVM: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm256_round_ps_fround_no_exc + // OGCG: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 0) + return _mm256_round_ps(x, 0b0000); +} diff --git a/clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins.c index 7542782bbe0c5..17638834d827a 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins.c @@ -92,3 +92,256 @@ __m128 test_mm_blend_ps(__m128 V1, __m128 V2) { // OGCG: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 0, i32 5, i32 6, i32 3> return _mm_blend_ps(V1, V2, 6); } + +__m128d test_mm_ceil_pd(__m128d x) { + // CIR-LABEL: test_mm_ceil_pd + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.pd" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_ceil_pd + // LLVM: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 2) + + // OGCG-LABEL: test_mm_ceil_pd + // OGCG: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 2) + return _mm_ceil_pd(x); +} + +__m128 test_mm_ceil_ps(__m128 x) { + // CIR-LABEL: test_mm_ceil_ps + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ps" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_ceil_ps + // LLVM: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 2) + + // OGCG-LABEL: test_mm_ceil_ps + // OGCG: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 2) + return _mm_ceil_ps(x); +} + +__m128d test_mm_ceil_sd(__m128d x, __m128d y) { + // CIR-LABEL: test_mm_ceil_sd + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.sd" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_ceil_sd + // LLVM: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 2) + + // OGCG-LABEL: test_mm_ceil_sd + // OGCG: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 2) + return _mm_ceil_sd(x, y); +} + +__m128 test_mm_ceil_ss(__m128 x, __m128 y) { + // CIR-LABEL: test_mm_ceil_ss + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ss" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_ceil_ss + // LLVM: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 2) + + // OGCG-LABEL: test_mm_ceil_ss + // OGCG: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 2) + return _mm_ceil_ss(x, y); +} + +__m128d test_mm_floor_pd(__m128d x) { + // CIR-LABEL: test_mm_floor_pd + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.pd" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_floor_pd + // LLVM: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 1) + + // OGCG-LABEL: test_mm_floor_pd + // OGCG: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 1) + return _mm_floor_pd(x); +} + +__m128 test_mm_floor_ps(__m128 x) { + // CIR-LABEL: test_mm_floor_ps + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ps" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_floor_ps + // LLVM: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 1) + + // OGCG-LABEL: test_mm_floor_ps + // OGCG: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 1) + return _mm_floor_ps(x); +} + +__m128d test_mm_floor_sd(__m128d x, __m128d y) { + // CIR-LABEL: test_mm_floor_sd + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.sd" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_floor_sd + // LLVM: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 1) + + // OGCG-LABEL: test_mm_floor_sd + // OGCG: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 1) + return _mm_floor_sd(x, y); +} + +__m128 test_mm_floor_ss(__m128 x, __m128 y) { + // CIR-LABEL: test_mm_floor_ss + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ss" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_floor_ss + // LLVM: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 1) + + // OGCG-LABEL: test_mm_floor_ss + // OGCG: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 1) + return _mm_floor_ss(x, y); +} + +__m128d test_mm_round_pd(__m128d x) { + // CIR-LABEL: test_mm_round_pd + // CIR: cir.roundeven %{{.*}} : !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_pd + // LLVM: call <2 x double> @llvm.roundeven.v2f64(<2 x double> %{{.*}}) + + // OGCG-LABEL: test_mm_round_pd + // OGCG: call <2 x double> @llvm.roundeven.v2f64(<2 x double> %{{.*}}) + return _mm_round_pd(x, 0b1000); +} + +__m128d test_mm_round_pd_mxcsr(__m128d x) { + // CIR-LABEL: test_mm_round_pd_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.pd" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_pd_mxcsr + // LLVM: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm_round_pd_mxcsr + // OGCG: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 12) + return _mm_round_pd(x, 0b1100); +} + +__m128d test_mm_round_pd_fround_no_exc(__m128d x) { + // CIR-LABEL: test_mm_round_pd_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.pd" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_pd_fround_no_exc + // LLVM: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm_round_pd_fround_no_exc + // OGCG: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 0) + return _mm_round_pd(x, 0b0000); +} + +__m128 test_mm_round_ps(__m128 x) { + // CIR-LABEL: test_mm_round_ps + // CIR: cir.floor %{{.*}} : !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ps + // LLVM: call <4 x float> @llvm.floor.v4f32(<4 x float> %{{.*}}) + + // OGCG-LABEL: test_mm_round_ps + // OGCG: call <4 x float> @llvm.floor.v4f32(<4 x float> %{{.*}}) + return _mm_round_ps(x, 0b1001); +} + +__m128 test_mm_round_ps_mxcsr(__m128 x) { + // CIR-LABEL: test_mm_round_ps_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ps" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ps_mxcsr + // LLVM: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm_round_ps_mxcsr + // OGCG: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 12) + return _mm_round_ps(x, 0b1100); +} + +__m128 test_mm_round_ps_fround_no_exc(__m128 x) { + // CIR-LABEL: test_mm_round_ps_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ps" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ps_fround_no_exc + // LLVM: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm_round_ps_fround_no_exc + // OGCG: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 0) + return _mm_round_ps(x, 0b0000); +} + +__m128d test_mm_round_sd(__m128d x, __m128d y) { + // CIR-LABEL: test_mm_round_sd + // %[[A:.*]] = cir.vec.extract = %{{.*}}[%{{.*}} : !u64] : !cir.vector<2 x !cir.double> + // %[[B:.*]] = cir.roundeven %[[A]] : !cir.double + // cir.vec.insert = %[[B]], %{{.*}}[%{{.*}} : !u64] : !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_sd + // LLVM: %[[A:.*]] = extractelement <2 x double> %{{.*}}, i64 0 + // LLVM: %[[B:.*]] = call double @llvm.roundeven.f64(double %[[A]]) + // LLVM: insertelement <2 x double> %{{.*}}, double %[[B]], i64 0 + + // OGCG-LABEL: test_mm_round_sd + // OGCG: %[[A:.*]] = extractelement <2 x double> %{{.*}}, i32 0 + // OGCG: %[[B:.*]] = call double @llvm.roundeven.f64(double %[[A]]) + // OGCG: insertelement <2 x double> %0, double %[[B]], i32 0 + return _mm_round_sd(x, y, 0b1000); +} + +__m128d test_mm_round_sd_mxcsr(__m128d x, __m128d y) { + // CIR-LABEL: test_mm_round_sd_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.sd" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_sd_mxcsr + // LLVM: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm_round_sd_mxcsr + // OGCG: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 12) + return _mm_round_sd(x, y, 0b1100); +} + + +__m128d test_mm_round_sd_fround_no_exc(__m128d x, __m128d y) { + // CIR-LABEL: test_mm_round_sd_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.sd" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_sd_fround_no_exc + // LLVM: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm_round_sd_fround_no_exc + // OGCG: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 0) + return _mm_round_sd(x, y, 0b0000); +} + +__m128 test_mm_round_ss(__m128 x, __m128 y) { + // CIR-LABEL: test_mm_round_ss + // %[[A:.*]] = cir.vec.extract = %{{.*}}[%{{.*}} : !u64] : !cir.vector<4 x !cir.float> + // %[[B:.*]] = cir.trunc %[[A]] : !cir.float + // cir.vec.insert = %[[B]], %{{.*}}[%{{.*}} : !u64] : !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ss + // LLVM: %[[A:.*]] = extractelement <4 x float> %{{.*}}, i64 0 + // LLVM: %[[B:.*]] = call float @llvm.trunc.f32(float %[[A]]) + // LLVM: insertelement <4 x float> %{{.*}}, float %[[B]], i64 0 + + // OGCG-LABEL: test_mm_round_ss + // OGCG: %[[A:.*]] = extractelement <4 x float> %{{.*}}, i32 0 + // OGCG: %[[B:.*]] = call float @llvm.trunc.f32(float %[[A]]) + // OGCG: insertelement <4 x float> %{{.*}}, float %[[B]], i32 0 + return _mm_round_ss(x, y, 0b1011); +} + +__m128 test_mm_round_ss_mxcsr(__m128 x, __m128 y) { + // CIR-LABEL: test_mm_round_ss_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ss" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ss_mxcsr + // LLVM: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm_round_ss_mxcsr + // OGCG: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 12) + return _mm_round_ss(x, y, 0b1100); +} + +__m128 test_mm_round_ss_fround_no_exc(__m128 x, __m128 y) { + // CIR-LABEL: test_mm_round_ss_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ss" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ss_fround_no_exc + // LLVM: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm_round_ss_fround_no_exc + // OGCG: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 0) + return _mm_round_ss(x, y, 0b0000); +} >From c33cb022600b6fbdf2f8b7f7147af6ca1dc497aa Mon Sep 17 00:00:00 2001 From: Borys Perski <[email protected]> Date: Sat, 19 Sep 2026 19:46:33 +0200 Subject: [PATCH 2/2] [CIR][X86] Add support for constrained roundpd, roundps, roundsd, roundss builtins --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 175 +++++++++--------- .../X86/avx-builtins-constrained.c | 80 ++++++++ .../X86/sse41-builtins-constrained.c | 164 ++++++++++++++++ 3 files changed, 336 insertions(+), 83 deletions(-) create mode 100644 clang/test/CIR/CodeGenBuiltins/X86/avx-builtins-constrained.c create mode 100644 clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins-constrained.c diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 76bfe209011bf..73c1f5fe06c09 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -86,24 +86,97 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, return maskVec; } -static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder, - mlir::Location loc, mlir::Value x, - unsigned roundingControl) { - constexpr unsigned roundingMask = 0b11; - unsigned roundingMode = roundingControl & roundingMask; +static mlir::Value emitX86Round(CIRGenFunction &cgf, unsigned builtinID, + const CallExpr *expr, + SmallVector<mlir::Value> &ops) { + bool isScalar = builtinID == X86::BI__builtin_ia32_roundss || + builtinID == X86::BI__builtin_ia32_roundsd; - switch (roundingMode) { - default: - llvm_unreachable("Invalid rounding mode"); - case 0b00: - return cir::RoundEvenOp::create(builder, loc, x); - case 0b01: - return cir::FloorOp::create(builder, loc, x); - case 0b10: - return cir::CeilOp::create(builder, loc, x); - case 0b11: - return cir::TruncOp::create(builder, loc, x); + unsigned roundingControl = + cgf.getZExtIntValueFromConstOp(isScalar ? ops[2] : ops[1]); + + constexpr unsigned mxcsrMask = 0b100; + constexpr unsigned fRoundNoExcMask = 0b1000; + unsigned useMXCSR = mxcsrMask & roundingControl; + unsigned fRoundNoExc = fRoundNoExcMask & roundingControl; + + CIRGenBuilderTy &builder = cgf.getBuilder(); + mlir::Location loc = cgf.getLoc(expr->getExprLoc()); + + if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: + llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundps: + intrinsicName = "x86.sse41.round.ps"; + break; + case X86::BI__builtin_ia32_roundpd: + intrinsicName = "x86.sse41.round.pd"; + break; + case X86::BI__builtin_ia32_roundps256: + intrinsicName = "x86.avx.round.ps.256"; + break; + case X86::BI__builtin_ia32_roundpd256: + intrinsicName = "x86.avx.round.pd.256"; + break; + case X86::BI__builtin_ia32_roundss: + intrinsicName = "x86.sse41.round.ss"; + break; + case X86::BI__builtin_ia32_roundsd: + intrinsicName = "x86.sse41.round.sd"; + break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); + } + + auto emitRoundOp = [&](mlir::Value x) -> mlir::Value { + constexpr unsigned roundingMask = 0b11; + unsigned roundingMode = roundingControl & roundingMask; + + if (builder.getIsFPConstrained()) { + CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, expr); + + builder.setDefaultConstrainedExcept(clang::LangOptions::FPE_Ignore); + cir::FenvAttr fenv = builder.getConstrainedFPAttr(); + + switch (roundingMode) { + default: + llvm_unreachable("Invalid rounding mode"); + case 0b00: + return cir::RoundEvenOp::create(builder, loc, x, fenv); + case 0b01: + return cir::FloorOp::create(builder, loc, x, fenv); + case 0b10: + return cir::CeilOp::create(builder, loc, x, fenv); + case 0b11: + return cir::TruncOp::create(builder, loc, x, fenv); + } + } + + switch (roundingMode) { + default: + llvm_unreachable("Invalid rounding mode"); + case 0b00: + return cir::RoundEvenOp::create(builder, loc, x); + case 0b01: + return cir::FloorOp::create(builder, loc, x); + case 0b10: + return cir::CeilOp::create(builder, loc, x); + case 0b11: + return cir::TruncOp::create(builder, loc, x); + } + }; + + if (isScalar) { + mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0); + mlir::Value roundedAt0 = emitRoundOp(valAt0); + return builder.createInsertElement(loc, ops[0], roundedAt0, 0); } + + return emitRoundOp(ops[0]); } static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder, @@ -1176,74 +1249,10 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { case X86::BI__builtin_ia32_roundps: case X86::BI__builtin_ia32_roundpd: case X86::BI__builtin_ia32_roundps256: - case X86::BI__builtin_ia32_roundpd256: { - unsigned m = - ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue(); - constexpr unsigned mxcsrMask = 0b100; - constexpr unsigned fRoundNoExcMask = 0b1000; - unsigned useMXCSR = mxcsrMask & m; - unsigned fRoundNoExc = fRoundNoExcMask & m; - - mlir::Location loc = getLoc(expr->getExprLoc()); - - if (useMXCSR || !fRoundNoExc) { - StringRef intrinsicName; - switch (builtinID) { - default: - llvm_unreachable("Unexpected builtin"); - case X86::BI__builtin_ia32_roundps: - intrinsicName = "x86.sse41.round.ps"; - break; - case X86::BI__builtin_ia32_roundpd: - intrinsicName = "x86.sse41.round.pd"; - break; - case X86::BI__builtin_ia32_roundps256: - intrinsicName = "x86.avx.round.ps.256"; - break; - case X86::BI__builtin_ia32_roundpd256: - intrinsicName = "x86.avx.round.pd.256"; - break; - } - - mlir::Type resTy = ops[0].getType(); - return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); - } - - return emitX86RoundImmediate(builder, loc, ops[0], m); - } + case X86::BI__builtin_ia32_roundpd256: case X86::BI__builtin_ia32_roundss: - case X86::BI__builtin_ia32_roundsd: { - unsigned m = - ops[2].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue(); - constexpr unsigned mxcsrMask = 0b100; - constexpr unsigned fRoundNoExcMask = 0b1000; - unsigned useMXCSR = mxcsrMask & m; - unsigned fRoundNoExc = fRoundNoExcMask & m; - - mlir::Location loc = getLoc(expr->getExprLoc()); - - if (useMXCSR || !fRoundNoExc) { - StringRef intrinsicName; - switch (builtinID) { - default: - llvm_unreachable("Unexpected builtin"); - case X86::BI__builtin_ia32_roundss: - intrinsicName = "x86.sse41.round.ss"; - break; - case X86::BI__builtin_ia32_roundsd: - intrinsicName = "x86.sse41.round.sd"; - break; - } - - mlir::Type resTy = ops[0].getType(); - return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); - } - - mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0); - mlir::Value roundedAt0 = emitX86RoundImmediate(builder, loc, valAt0, m); - - return builder.createInsertElement(loc, ops[0], roundedAt0, 0); - } + case X86::BI__builtin_ia32_roundsd: + return emitX86Round(*this, builtinID, expr, ops); case X86::BI__builtin_ia32_lzcnt_u16: case X86::BI__builtin_ia32_lzcnt_u32: case X86::BI__builtin_ia32_lzcnt_u64: diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins-constrained.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins-constrained.c new file mode 100644 index 0000000000000..2e606ced2f53a --- /dev/null +++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins-constrained.c @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -frounding-math -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx -fclangir -emit-cir -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -frounding-math -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx -fclangir -emit-llvm -o %t.ll +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s +// RUN: %clang_cc1 -frounding-math -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx -emit-llvm -o %t.ll +// RUN: FileCheck --check-prefixes=OGCG --input-file=%t.ll %s + +#include <immintrin.h> + +__m256d test_mm256_round_pd_mxcsr(__m256d x) { + // CIR-LABEL: test_mm256_round_pd_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.avx.round.pd.256" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.double>, !s32i) -> !cir.vector<4 x !cir.double> + + // LLVM-LABEL: test_mm256_round_pd_mxcsr + // LLVM: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm256_round_pd_mxcsr + // OGCG: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 12) + return _mm256_round_pd(x, 0b1100); +} + +__m256d test_mm256_round_pd_fround_no_exc(__m256d x) { + // CIR-LABEL: test_mm256_round_pd_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.avx.round.pd.256" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.double>, !s32i) -> !cir.vector<4 x !cir.double> + + // LLVM-LABEL: test_mm256_round_pd_fround_no_exc + // LLVM: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm256_round_pd_fround_no_exc + // OGCG: call <4 x double> @llvm.x86.avx.round.pd.256(<4 x double> %{{.*}}, i32 0) + return _mm256_round_pd(x, 0b0000); +} + +__m256d test_mm256_round_pd_trunc(__m256d x) { + // CIR-LABEL: test_mm256_round_pd_trunc + // CIR: cir.trunc %{{.*}} : !cir.vector<4 x !cir.double> {fenv = #cir.fenv<dynamic_rounding_mode = unknown, except_mode = masked, strict_except = false>} + + // LLVM-LABEL: test_mm256_round_pd_trunc + // LLVM: call <4 x double> @llvm.experimental.constrained.trunc.v4f64(<4 x double> %{{.*}}, metadata !"fpexcept.ignore") + + // OGCG-LABEL: test_mm256_round_pd_trunc + // OGCG: call <4 x double> @llvm.experimental.constrained.trunc.v4f64(<4 x double> %{{.*}}, metadata !"fpexcept.ignore") + return _mm256_round_pd(x, 0b1011); +} + +__m256 test_mm256_round_ps_mxcsr(__m256 x) { + // CIR-LABEL: test_mm256_round_ps_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.avx.round.ps.256" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.float>, !s32i) -> !cir.vector<8 x !cir.float> + + // LLVM-LABEL: test_mm256_round_ps_mxcsr + // LLVM: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm256_round_ps_mxcsr + // OGCG: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 12) + return _mm256_round_ps(x, 0b1100); +} + +__m256 test_mm256_round_ps_fround_no_exc(__m256 x) { + // CIR-LABEL: test_mm256_round_ps_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.avx.round.ps.256" %{{.*}}, %{{.*}} : (!cir.vector<8 x !cir.float>, !s32i) -> !cir.vector<8 x !cir.float> + + // LLVM-LABEL: test_mm256_round_ps_fround_no_exc + // LLVM: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm256_round_ps_fround_no_exc + // OGCG: call <8 x float> @llvm.x86.avx.round.ps.256(<8 x float> %{{.*}}, i32 0) + return _mm256_round_ps(x, 0b0000); +} + +__m256 test_mm256_round_ps_trunc(__m256 x) { + // CIR-LABEL: test_mm256_round_ps_trunc + // CIR: cir.trunc %{{.*}} : !cir.vector<8 x !cir.float> {fenv = #cir.fenv<dynamic_rounding_mode = unknown, except_mode = masked, strict_except = false>} + + // LLVM-LABEL: test_mm256_round_ps_trunc + // LLVM: call <8 x float> @llvm.experimental.constrained.trunc.v8f32(<8 x float> %{{.*}}, metadata !"fpexcept.ignore") + + // OGCG-LABEL: test_mm256_round_ps_trunc + // OGCG: call <8 x float> @llvm.experimental.constrained.trunc.v8f32(<8 x float> %{{.*}}, metadata !"fpexcept.ignore") + return _mm256_round_ps(x, 0b1011); +} diff --git a/clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins-constrained.c b/clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins-constrained.c new file mode 100644 index 0000000000000..7053c1870da7f --- /dev/null +++ b/clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins-constrained.c @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -frounding-math -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse4.1 -fclangir -emit-cir -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -frounding-math -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse4.1 -fclangir -emit-llvm -o %t.ll +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s +// RUN: %clang_cc1 -frounding-math -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse4.1 -emit-llvm -o %t.ll +// RUN: FileCheck --check-prefixes=OGCG --input-file=%t.ll %s + +#include <immintrin.h> + +__m128d test_mm_round_pd_roundeven(__m128d x) { + // CIR-LABEL: test_mm_round_pd_roundeven + // CIR: cir.roundeven %{{.*}} : !cir.vector<2 x !cir.double> {fenv = #cir.fenv<dynamic_rounding_mode = unknown, except_mode = masked, strict_except = false>} + + // LLVM-LABEL: test_mm_round_pd_roundeven + // LLVM: call <2 x double> @llvm.experimental.constrained.roundeven.v2f64(<2 x double> %{{.*}}, metadata !"fpexcept.ignore") + + // OGCG-LABEL: test_mm_round_pd_roundeven + // OGCG: call <2 x double> @llvm.experimental.constrained.roundeven.v2f64(<2 x double> %{{.*}}, metadata !"fpexcept.ignore") + return _mm_round_pd(x, 0b1000); +} + +__m128d test_mm_round_pd_mxcsr(__m128d x) { + // CIR-LABEL: test_mm_round_pd_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.pd" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_pd_mxcsr + // LLVM: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm_round_pd_mxcsr + // OGCG: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 12) + return _mm_round_pd(x, 0b1100); +} + +__m128d test_mm_round_pd_fround_no_exc(__m128d x) { + // CIR-LABEL: test_mm_round_pd_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.pd" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_pd_fround_no_exc + // LLVM: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm_round_pd_fround_no_exc + // OGCG: call <2 x double> @llvm.x86.sse41.round.pd(<2 x double> %{{.*}}, i32 0) + return _mm_round_pd(x, 0b0000); +} + +__m128 test_mm_round_ps_floor(__m128 x) { + // CIR-LABEL: test_mm_round_ps_floor + // CIR: cir.floor %{{.*}} : !cir.vector<4 x !cir.float> {fenv = #cir.fenv<dynamic_rounding_mode = unknown, except_mode = masked, strict_except = false>} + + // LLVM-LABEL: test_mm_round_ps_floor + // LLVM: call <4 x float> @llvm.experimental.constrained.floor.v4f32(<4 x float> %{{.*}}, metadata !"fpexcept.ignore") + + // OGCG-LABEL: test_mm_round_ps_floor + // OGCG: call <4 x float> @llvm.experimental.constrained.floor.v4f32(<4 x float> %{{.*}}, metadata !"fpexcept.ignore") + return _mm_round_ps(x, 0b1001); +} + +__m128 test_mm_round_ps_mxcsr(__m128 x) { + // CIR-LABEL: test_mm_round_ps_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ps" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ps_mxcsr + // LLVM: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm_round_ps_mxcsr + // OGCG: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 12) + return _mm_round_ps(x, 0b1100); +} + +__m128 test_mm_round_ps_fround_no_exc(__m128 x) { + // CIR-LABEL: test_mm_round_ps_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ps" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ps_fround_no_exc + // LLVM: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm_round_ps_fround_no_exc + // OGCG: call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %{{.*}}, i32 0) + return _mm_round_ps(x, 0b0000); +} + +__m128d test_mm_round_sd_ceil(__m128d x, __m128d y) { + // CIR-LABEL: test_mm_round_sd_ceil + // %[[A:.*]] = cir.vec.extract = %{{.*}}[%{{.*}} : !u64] : !cir.vector<2 x !cir.double> + // %[[B:.*]] = cir.ceil %[[A]] : !cir.double {fenv = #cir.fenv<dynamic_rounding_mode = unknown, except_mode = masked, strict_except = false>} + // cir.vec.insert = %[[B]], %{{.*}}[%{{.*}} : !u64] : !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_sd_ceil + // LLVM: %[[A:.*]] = extractelement <2 x double> %{{.*}}, i64 0 + // LLVM: %[[B:.*]] = call double @llvm.experimental.constrained.ceil.f64(double %[[A]], metadata !"fpexcept.ignore") + // LLVM: insertelement <2 x double> %{{.*}}, double %[[B]], i64 0 + + // OGCG-LABEL: test_mm_round_sd_ceil + // OGCG: %[[A:.*]] = extractelement <2 x double> %{{.*}}, i32 0 + // OGCG: %[[B:.*]] = call double @llvm.experimental.constrained.ceil.f64(double %[[A]], metadata !"fpexcept.ignore") + // OGCG: insertelement <2 x double> %{{.*}}, double %[[B]], i32 0 + return _mm_round_sd(x, y, 0b1010); +} + +__m128d test_mm_round_sd_mxcsr(__m128d x, __m128d y) { + // CIR-LABEL: test_mm_round_sd_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.sd" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_sd_mxcsr + // LLVM: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm_round_sd_mxcsr + // OGCG: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 12) + return _mm_round_sd(x, y, 0b1100); +} + +__m128d test_mm_round_sd_fround_no_exc(__m128d x, __m128d y) { + // CIR-LABEL: test_mm_round_sd_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.sd" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>, !s32i) -> !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_sd_fround_no_exc + // LLVM: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm_round_sd_fround_no_exc + // OGCG: call <2 x double> @llvm.x86.sse41.round.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 0) + return _mm_round_sd(x, y, 0b0000); +} + +__m128 test_mm_round_ss_trunc(__m128 x, __m128 y) { + // CIR-LABEL: test_mm_round_ss_trunc + // %[[A:.*]] = cir.vec.extract = %{{.*}}[%{{.*}} : !u64] : !cir.vector<2 x !cir.double> + // %[[B:.*]] = cir.trunc %6 : !cir.float {fenv = #cir.fenv<dynamic_rounding_mode = unknown, except_mode = masked, strict_except = false>} + // cir.vec.insert = %[[B]], %{{.*}}[%{{.*}} : !u64] : !cir.vector<2 x !cir.double> + + // LLVM-LABEL: test_mm_round_ss_trunc + // LLVM: %[[A:.*]] = extractelement <4 x float> %{{.*}}, i64 0 + // LLVM: %[[B:.*]] = call float @llvm.experimental.constrained.trunc.f32(float %[[A]], metadata !"fpexcept.ignore") + // LLVM: insertelement <4 x float> %{{.*}}, float %[[B]], i64 0 + + // OGCG-LABEL: test_mm_round_ss_trunc + // OGCG: %[[A:.*]] = extractelement <4 x float> %{{.*}}, i32 0 + // OGCG: %[[B:.*]] = call float @llvm.experimental.constrained.trunc.f32(float %[[A]], metadata !"fpexcept.ignore") + // OGCG: insertelement <4 x float> %{{.*}}, float %[[B]], i32 0 + return _mm_round_ss(x, y, 0b1011); +} + +__m128 test_mm_round_ss_mxcsr(__m128 x, __m128 y) { + // CIR-LABEL: test_mm_round_ss_mxcsr + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ss" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ss_mxcsr + // LLVM: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 12) + + // OGCG-LABEL: test_mm_round_ss_mxcsr + // OGCG: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 12) + return _mm_round_ss(x, y, 0b1100); +} + +__m128 test_mm_round_ss_fround_no_exc(__m128 x, __m128 y) { + // CIR-LABEL: test_mm_round_ss_fround_no_exc + // CIR: cir.call_llvm_intrinsic "x86.sse41.round.ss" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>, !s32i) -> !cir.vector<4 x !cir.float> + + // LLVM-LABEL: test_mm_round_ss_fround_no_exc + // LLVM: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 0) + + // OGCG-LABEL: test_mm_round_ss_fround_no_exc + // OGCG: call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 0) + return _mm_round_ss(x, y, 0b0000); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
