[clang] Lowering for __builtin_reduce_assoc_fadd (PR #226095)
Kunal Dubey via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 25 02:44:18 PDT 2026
https://github.com/xakep8 updated https://github.com/llvm/llvm-project/pull/226095
>From 0b9738aa9ec01aaa5585a29f59532501031be37f Mon Sep 17 00:00:00 2001
From: Kunal Dubey <xakep8 at protonmail.com>
Date: Sun, 20 Sep 2026 14:31:07 +0530
Subject: [PATCH 1/4] [CIR] Added fast-math flags to LLVM intrinsic calls
Added fast-math flags attribute to CIR which cir.call_llvm_intrinsic now
carries through DirectToLLVM lowering. CIR now preserves fast-math flags
such as reassoc when lowering to llvm.call_intrinsic.
Added test for the same.
---
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 28 +++++++++++++++++++
clang/include/clang/CIR/Dialect/IR/CIROps.td | 9 ++++--
clang/lib/CIR/CodeGen/CIRGenBuilder.h | 9 ++++++
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 26 ++++++++++++++++-
.../test/CIR/Lowering/call-llvm-intrinsic.cir | 11 ++++++++
5 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 57a6237138ac70..840d03e99a11e2 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -947,6 +947,34 @@ def CIR_FenvAttr : CIR_Attr<"Fenv", "fenv"> {
let canHaveIllegalCXXABIType = 0;
}
+//===----------------------------------------------------------------------===//
+// FastMathFlagsAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_FMFnone : I32BitEnumAttrCaseNone<"none">;
+def CIR_FMFnnan : I32BitEnumAttrCaseBit<"nnan", 0>;
+def CIR_FMFninf : I32BitEnumAttrCaseBit<"ninf", 1>;
+def CIR_FMFnsz : I32BitEnumAttrCaseBit<"nsz", 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_FMFnnan, CIR_FMFninf, CIR_FMFnsz, CIR_FMFarcp, CIR_FMFcontract,
+ CIR_FMFafn, CIR_FMFreassoc
+]>;
+
+def CIR_FastMathFlags : CIR_I32BitEnum<
+ "FastMathFlags", "fast-math flags", [
+ CIR_FMFnone, CIR_FMFnnan, CIR_FMFninf, CIR_FMFnsz, CIR_FMFarcp,
+ CIR_FMFcontract, CIR_FMFafn, CIR_FMFreassoc, CIR_FMFfast
+]> {
+ let separator = ", ";
+ let printBitEnumPrimaryGroups = 1;
+}
+
+def CIR_FastMathFlagsAttr : CIR_EnumAttr<CIR_FastMathFlags, "fastmath">;
+
//===----------------------------------------------------------------------===//
// GlobalViewAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 5ebad8b019e2bf..4996037ea5f560 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4520,7 +4520,9 @@ def CIR_LLVMIntrinsicCallOp : CIR_Op<"call_llvm_intrinsic"> {
let results = (outs Optional<CIR_AnyType>:$result);
let arguments = (ins
- StrAttr:$intrinsic_name, Variadic<CIR_AnyType>:$arg_ops);
+ StrAttr:$intrinsic_name,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath_flags,
+ Variadic<CIR_AnyType>:$arg_ops);
let skipDefaultBuilders = 1;
@@ -4530,8 +4532,11 @@ def CIR_LLVMIntrinsicCallOp : CIR_Op<"call_llvm_intrinsic"> {
let builders = [
OpBuilder<(ins "mlir::StringAttr":$intrinsic_name, "mlir::Type":$resType,
- CArg<"mlir::ValueRange", "{}">:$operands), [{
+ CArg<"mlir::ValueRange", "{}">:$operands,
+ CArg<"cir::FastMathFlagsAttr", "{}">:$fastmath), [{
$_state.addAttribute("intrinsic_name", intrinsic_name);
+ if (fastmath)
+ $_state.addAttribute("fastmath_flags", fastmath);
$_state.addOperands(operands);
if (resType)
$_state.addTypes(resType);
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 01d74e1549fa53..c58eee276f0cfa 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -833,6 +833,15 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
std::forward<Operands>(op)...)
.getResult();
}
+
+ mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str,
+ const mlir::Type &resTy,
+ mlir::ValueRange operands,
+ cir::FastMathFlagsAttr fastmath) {
+ return cir::LLVMIntrinsicCallOp::create(
+ *this, loc, this->getStringAttr(str), resTy, operands, fastmath)
+ .getResult();
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 53bffe02590025..4bdbe38df24e8e 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -598,6 +598,27 @@ mlir::LogicalResult lowerConstrainableFPOp(
constrainedMnemonic, hasRoundingMode);
}
+static mlir::LLVM::FastmathFlags
+convertFastMathFlags(cir::FastMathFlags cirFlags) {
+ mlir::LLVM::FastmathFlags llvmFlags{};
+ const std::pair<cir::FastMathFlags, mlir::LLVM::FastmathFlags> flags[] = {
+ {cir::FastMathFlags::nnan, mlir::LLVM::FastmathFlags::nnan},
+ {cir::FastMathFlags::ninf, mlir::LLVM::FastmathFlags::ninf},
+ {cir::FastMathFlags::nsz, mlir::LLVM::FastmathFlags::nsz},
+ {cir::FastMathFlags::arcp, mlir::LLVM::FastmathFlags::arcp},
+ {cir::FastMathFlags::contract, mlir::LLVM::FastmathFlags::contract},
+ {cir::FastMathFlags::afn, mlir::LLVM::FastmathFlags::afn},
+ {cir::FastMathFlags::reassoc, mlir::LLVM::FastmathFlags::reassoc},
+ };
+
+ for (auto [cirFlag, llvmFlag] : flags) {
+ if (bitEnumContainsAny(cirFlags, cirFlag))
+ llvmFlags = llvmFlags | llvmFlag;
+ }
+
+ return llvmFlags;
+}
+
mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
@@ -610,6 +631,9 @@ mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
return op.emitError("expected LLVM result type");
}
StringRef name = op.getIntrinsicName();
+ mlir::LLVM::FastmathFlags fastmathFlags = {};
+ if (std::optional<cir::FastMathFlags> fastmath = op.getFastmathFlags())
+ fastmathFlags = convertFastMathFlags(*fastmath);
// Some LLVM intrinsics require ElementType attribute to be attached to
// the argument of pointer type. That prevents us from generating LLVM IR
@@ -622,7 +646,7 @@ mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
// to set LLVM IR attribute.
assert(!cir::MissingFeatures::intrinsicElementTypeSupport());
replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm." + name, llvmResTy,
- adaptor.getOperands());
+ adaptor.getOperands(), fastmathFlags);
return mlir::success();
}
diff --git a/clang/test/CIR/Lowering/call-llvm-intrinsic.cir b/clang/test/CIR/Lowering/call-llvm-intrinsic.cir
index edd492aa7477ca..643e4db0d7d0c4 100644
--- a/clang/test/CIR/Lowering/call-llvm-intrinsic.cir
+++ b/clang/test/CIR/Lowering/call-llvm-intrinsic.cir
@@ -5,6 +5,8 @@
// 0-result (void) calls in addition to the single-result case.
!s32i = !cir.int<s, 32>
+!f32 = !cir.float
+!v4f32 = !cir.vector<4 x !f32>
module {
// 0-result, 0-operand.
@@ -24,4 +26,13 @@ module {
cir.call_llvm_intrinsic "amdgcn.s.sleep" %arg0 : (!s32i) -> ()
cir.return
}
+
+ // Fast-math flags are preserved on the lowered LLVM intrinsic call.
+ // CHECK-LABEL: llvm.func @fastmath_flags
+ // CHECK: llvm.call_intrinsic "llvm.vector.reduce.fadd"(%{{.*}}, %{{.*}}) {fastmathFlags = #llvm.fastmath<reassoc>} : (f32, vector<4xf32>) -> f32
+ // CHECK: llvm.return
+ cir.func @fastmath_flags(%arg0: !f32, %arg1: !v4f32) -> !f32 {
+ %0 = cir.call_llvm_intrinsic "vector.reduce.fadd" %arg0, %arg1 : (!f32, !v4f32) -> !f32 {fastmath_flags = #cir.fastmath<reassoc>}
+ cir.return %0 : !f32
+ }
}
>From bdbd8af61a4e5d87a2f74038ac88d9308cce2898 Mon Sep 17 00:00:00 2001
From: Kunal Dubey <xakep8 at protonmail.com>
Date: Tue, 22 Sep 2026 00:34:55 +0530
Subject: [PATCH 2/4] [CIR] Added fast-math attr description and tests
---
clang/include/clang/CIR/Dialect/IR/CIRAttrs.td | 6 ++++++
clang/test/CIR/IR/enum-attrs.cir | 8 ++++++++
clang/test/CIR/Lowering/call-llvm-intrinsic.cir | 8 ++++++++
3 files changed, 22 insertions(+)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 840d03e99a11e2..04dc8bb178cb87 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -969,6 +969,12 @@ def CIR_FastMathFlags : CIR_I32BitEnum<
CIR_FMFnone, CIR_FMFnnan, CIR_FMFninf, CIR_FMFnsz, CIR_FMFarcp,
CIR_FMFcontract, CIR_FMFafn, CIR_FMFreassoc, CIR_FMFfast
]> {
+ let description = [{
+ Describes fast-math flags for CIR operations. This attribute is shared by
+ operations with floating-point semantics and is not specific to LLVM intrinsic
+ calls.
+ }];
+
let separator = ", ";
let printBitEnumPrimaryGroups = 1;
}
diff --git a/clang/test/CIR/IR/enum-attrs.cir b/clang/test/CIR/IR/enum-attrs.cir
index 6455564cab7937..e4c4e76a292c75 100644
--- a/clang/test/CIR/IR/enum-attrs.cir
+++ b/clang/test/CIR/IR/enum-attrs.cir
@@ -131,6 +131,14 @@ cir.func @fp_class_attr() {
#cir.fp_class<fcSNan|fcNegInf>]}
}
+// CHECK-LABEL: cir.func @fastmath_attr() {
+cir.func @fastmath_attr() {
+ // CHECK: cir.return {cir.test = [#cir.fastmath<reassoc>, #cir.fastmath<nnan, ninf>, #cir.fastmath<fast>]}
+ cir.return {cir.test = [#cir.fastmath<reassoc>,
+ #cir.fastmath<nnan, ninf>,
+ #cir.fastmath<fast>]}
+}
+
// The operations themselves keep printing a bare keyword.
// CHECK-LABEL: cir.func @mem_order_sync_scope_ops(%arg0: !cir.ptr<!s32i>) {
diff --git a/clang/test/CIR/Lowering/call-llvm-intrinsic.cir b/clang/test/CIR/Lowering/call-llvm-intrinsic.cir
index 643e4db0d7d0c4..cbc2c469697983 100644
--- a/clang/test/CIR/Lowering/call-llvm-intrinsic.cir
+++ b/clang/test/CIR/Lowering/call-llvm-intrinsic.cir
@@ -35,4 +35,12 @@ module {
%0 = cir.call_llvm_intrinsic "vector.reduce.fadd" %arg0, %arg1 : (!f32, !v4f32) -> !f32 {fastmath_flags = #cir.fastmath<reassoc>}
cir.return %0 : !f32
}
+
+ // CHECK-LABEL: llvm.func @fastmath_fast_group
+ // CHECK: llvm.call_intrinsic "llvm.vector.reduce.fadd"(%{{.*}}, %{{.*}}) {fastmathFlags = #llvm.fastmath<fast>} : (f32, vector<4xf32>) -> f32
+ // CHECK: llvm.return
+ cir.func @fastmath_fast_group(%arg0: !f32, %arg1: !v4f32) -> !f32 {
+ %0 = cir.call_llvm_intrinsic "vector.reduce.fadd" %arg0, %arg1 : (!f32, !v4f32) -> !f32 {fastmath_flags = #cir.fastmath<fast>}
+ cir.return %0 : !f32
+ }
}
>From a22980a6cc6a7f4f0d2e259e07f1b8300709bbff Mon Sep 17 00:00:00 2001
From: Kunal Dubey <xakep8 at protonmail.com>
Date: Tue, 22 Sep 2026 13:27:30 +0530
Subject: [PATCH 3/4] [CIR] Updated IntrinsicCallOp helper shape
Changed mlir::Value range to template Operands &&...ops and moved flags before
the operands to improve the overall design.
---
clang/lib/CIR/CodeGen/CIRGenBuilder.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index c58eee276f0cfa..b581212b0db567 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -834,12 +834,14 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
.getResult();
}
+ template <typename... Operands>
mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str,
const mlir::Type &resTy,
- mlir::ValueRange operands,
- cir::FastMathFlagsAttr fastmath) {
+ cir::FastMathFlagsAttr fastmath,
+ Operands &&...op) {
return cir::LLVMIntrinsicCallOp::create(
- *this, loc, this->getStringAttr(str), resTy, operands, fastmath)
+ *this, loc, this->getStringAttr(str), resTy,
+ std::forward<Operands>(op)..., fastmath)
.getResult();
}
};
>From 9d795b9ddca037dd6a91c264fdc15966ce07efab Mon Sep 17 00:00:00 2001
From: Kunal Dubey <xakep8 at protonmail.com>
Date: Thu, 24 Sep 2026 15:08:58 +0530
Subject: [PATCH 4/4] [CIR] Lowering for __builtin_reduce_assoc_fadd
Added lowering for __builtin_reduce_assoc_fadd with the use of the new
implementation of CIR FastMathFlags, following same lowering path as
Classic Codegen.
Added tests for the same.
---
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 39 ++++++++++++++-----
.../builtin-reduce-arithmetic-sve.c | 23 ++++++++++-
.../builtin-reduce-arithmetic.c | 35 ++++++++++++++++-
3 files changed, 85 insertions(+), 12 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 245708691b7d99..3a379668543804 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -2240,22 +2240,41 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
cast<cir::VectorType>(convertType(e->getArg(0)->getType()))
.getElementType());
case Builtin::BI__builtin_reduce_assoc_fadd:
- return errorBuiltinNYI(*this, e, builtinID);
case Builtin::BI__builtin_reduce_in_order_fadd: {
- assert(e->getNumArgs() == 2 &&
- "__builtin_reduce_in_order_fadd requires a start value");
+ bool isAssociative =
+ builtinIDIfNoAsmLabel == Builtin::BI__builtin_reduce_assoc_fadd;
+
+ assert((isAssociative ? e->getNumArgs() == 1 || e->getNumArgs() == 2
+ : e->getNumArgs() == 2) &&
+ "invalid argument count for floating-point reduction");
mlir::Value vector = emitScalarExpr(e->getArg(0));
auto vectorTy = cast<cir::VectorType>(vector.getType());
mlir::Type scalarTy = vectorTy.getElementType();
mlir::Location loc = getLoc(e->getExprLoc());
- mlir::Value startValue = emitScalarExpr(e->getArg(1));
- if (startValue.getType() != scalarTy)
- startValue =
- builder.createCast(getLoc(e->getArg(1)->getExprLoc()),
- cir::CastKind::floating, startValue, scalarTy);
+ mlir::Value startValue;
+ if (e->getNumArgs() == 2) {
+ startValue = emitScalarExpr(e->getArg(1));
+ if (startValue.getType() != scalarTy)
+ startValue =
+ builder.createCast(getLoc(e->getArg(1)->getExprLoc()),
+ cir::CastKind::floating, startValue, scalarTy);
+ } else {
+ auto fpTy = cast<cir::FPTypeInterface>(scalarTy);
+ startValue = cir::ConstantOp::create(
+ builder, loc,
+ cir::FPAttr::get(scalarTy,
+ llvm::APFloat::getZero(fpTy.getFloatSemantics(),
+ /*Negative=*/true)));
+ }
+
SmallVector<mlir::Value, 2> args = {startValue, vector};
- mlir::Value result =
- builder.emitIntrinsicCallOp(loc, "vector.reduce.fadd", scalarTy, args);
+ cir::FastMathFlagsAttr fastMath;
+ if (isAssociative)
+ fastMath = cir::FastMathFlagsAttr::get(&getMLIRContext(),
+ cir::FastMathFlags::reassoc);
+
+ mlir::Value result = builder.emitIntrinsicCallOp(loc, "vector.reduce.fadd",
+ scalarTy, fastMath, args);
return RValue::get(result);
}
case Builtin::BI__builtin_reduce_maximum:
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic-sve.c b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic-sve.c
index fbd9752b255c32..00aac53da865f3 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic-sve.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic-sve.c
@@ -92,9 +92,30 @@ float test_sve_reduce_min_float(svfloat32_t x) {
return __builtin_reduce_min(x);
}
+float test_sve_reduce_assoc_fadd(svfloat32_t x, float start) {
+ // CIR-LABEL: @test_sve_reduce_assoc_fadd
+ // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.float, !cir.vector<[4] x !cir.float>) -> !cir.float {fastmath_flags = #cir.fastmath<reassoc>}
+ // CIR: cir.return
+ // LLVM-LABEL: @test_sve_reduce_assoc_fadd
+ // LLVM: call reassoc float @llvm.vector.reduce.fadd.nxv4f32(float %{{.*}}, <vscale x 4 x float>
+ // LLVM: ret float
+ return __builtin_reduce_assoc_fadd(x, start);
+}
+
+float test_sve_reduce_assoc_fadd_default_start(svfloat32_t x) {
+ // CIR-LABEL: @test_sve_reduce_assoc_fadd_default_start
+ // CIR: %[[START:.*]] = cir.const #cir.fp<-0.000000e+00> : !cir.float
+ // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" %[[START]], {{.*}} : (!cir.float, !cir.vector<[4] x !cir.float>) -> !cir.float {fastmath_flags = #cir.fastmath<reassoc>}
+ // CIR: cir.return
+ // LLVM-LABEL: @test_sve_reduce_assoc_fadd_default_start
+ // LLVM: call reassoc float @llvm.vector.reduce.fadd.nxv4f32(float -0.000000e+00, <vscale x 4 x float>
+ // LLVM: ret float
+ return __builtin_reduce_assoc_fadd(x);
+}
+
float test_sve_reduce_in_order_fadd(svfloat32_t x, float start) {
// CIR-LABEL: @test_sve_reduce_in_order_fadd
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.float, !cir.vector<[4] x !cir.float>) -> !cir.float
+ // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.float, !cir.vector<[4] x !cir.float>) -> !cir.float{{( loc.*)?$}}
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_in_order_fadd
// LLVM: call float @llvm.vector.reduce.fadd.nxv4f32(float %{{.*}}, <vscale x 4 x float>
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic.c b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic.c
index a2a4624de18549..6759b1a592d7f4 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic.c
@@ -110,9 +110,42 @@ float test_reduce_min_float(v4sf x) {
return __builtin_reduce_min(x);
}
+float test_reduce_assoc_fadd(v4sf x, float start) {
+ // CIR-LABEL: @test_reduce_assoc_fadd
+ // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.float, !cir.vector<4 x !cir.float>) -> !cir.float {fastmath_flags = #cir.fastmath<reassoc>}
+ // CIR: cir.return
+ // LLVM-LABEL: @test_reduce_assoc_fadd
+ // LLVM: call reassoc float @llvm.vector.reduce.fadd.v4f32(float %{{.*}}, <4 x float>
+ // LLVM: ret float
+ return __builtin_reduce_assoc_fadd(x, start);
+}
+
+float test_reduce_assoc_fadd_default_start(v4sf x) {
+ // CIR-LABEL: @test_reduce_assoc_fadd_default_start
+ // CIR: %[[START:.*]] = cir.const #cir.fp<-0.000000e+00> : !cir.float
+ // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" %[[START]], {{.*}} : (!cir.float, !cir.vector<4 x !cir.float>) -> !cir.float {fastmath_flags = #cir.fastmath<reassoc>}
+ // CIR: cir.return
+ // LLVM-LABEL: @test_reduce_assoc_fadd_default_start
+ // LLVM: call reassoc float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float>
+ // LLVM: ret float
+ return __builtin_reduce_assoc_fadd(x);
+}
+
+float test_reduce_assoc_fadd_cast_start(v4sf x, double start) {
+ // CIR-LABEL: @test_reduce_assoc_fadd_cast_start
+ // CIR: %[[START:.*]] = cir.cast floating {{.*}} : !cir.double -> !cir.float
+ // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" %[[START]], {{.*}} : (!cir.float, !cir.vector<4 x !cir.float>) -> !cir.float {fastmath_flags = #cir.fastmath<reassoc>}
+ // CIR: cir.return
+ // LLVM-LABEL: @test_reduce_assoc_fadd_cast_start
+ // LLVM: %[[START:.*]] = fptrunc double %{{.*}} to float
+ // LLVM: call reassoc float @llvm.vector.reduce.fadd.v4f32(float %[[START]], <4 x float>
+ // LLVM: ret float
+ return __builtin_reduce_assoc_fadd(x, start);
+}
+
float test_reduce_in_order_fadd(v4sf x, float start) {
// CIR-LABEL: @test_reduce_in_order_fadd
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.float, !cir.vector<4 x !cir.float>) -> !cir.float
+ // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.float, !cir.vector<4 x !cir.float>) -> !cir.float{{( loc.*)?$}}
// CIR: cir.return
// LLVM-LABEL: @test_reduce_in_order_fadd
// LLVM: call float @llvm.vector.reduce.fadd.v4f32(float %{{.*}}, <4 x float>
More information about the cfe-commits
mailing list