[clang] [CIR] Added Vector Reduce Op (PR #226546)
Kunal Dubey via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 3 09:31:13 PDT 2026
https://github.com/xakep8 updated https://github.com/llvm/llvm-project/pull/226546
>From 26b71d1bc55b76962f36bb85f8473e5ac8e17342 Mon Sep 17 00:00:00 2001
From: Kunal Dubey <xakep8 at protonmail.com>
Date: Fri, 25 Sep 2026 22:45:22 +0530
Subject: [PATCH] [CIR] Added Vector Reduce Op
Added cir.vec.reduce for vector reduction builtins supporting integer,
floating-point, bitwise and min/max reductions.
Used the operation for generic and x86 reduction builtins and preserved
expression FP options and merged builtin-required reassoc and nnan
flags.
Added CIR, verifier, lowering, fixed and scalable vector, boolean, FP16
and fast-math regression tests.
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 63 ++++++++++++
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 90 +++++++++--------
clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 44 +++++----
clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 23 +++++
clang/lib/CIR/CodeGen/CIRGenFunction.h | 5 +
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 71 +++++++++++++
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 68 +++++++++++++
.../CodeGenBuiltins/X86/avx512-reduceIntrin.c | 27 +++--
.../X86/avx512-reduceMinMaxIntrin.c | 27 +++--
.../CodeGenBuiltins/X86/avx512fp16-builtins.c | 16 +--
.../X86/avx512vlfp16-builtins.c | 33 +++----
.../builtin-reduce-arithmetic-sve.c | 27 +++--
.../builtin-reduce-arithmetic.c | 58 +++++++----
.../CodeGenBuiltins/builtin-reduce-bitwise.c | 20 +++-
.../builtin-reduce-fast-math.c | 99 +++++++++++++++++++
clang/test/CIR/IR/invalid-vector-reduce.cir | 78 +++++++++++++++
clang/test/CIR/IR/vector.cir | 43 ++++++++
clang/test/CIR/Lowering/vector-reduce.cir | 50 ++++++++++
18 files changed, 707 insertions(+), 135 deletions(-)
create mode 100644 clang/test/CIR/CodeGenBuiltins/builtin-reduce-fast-math.c
create mode 100644 clang/test/CIR/IR/invalid-vector-reduce.cir
create mode 100644 clang/test/CIR/Lowering/vector-reduce.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index e450423c12ce247..a193c4d12a95fe9 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -6169,6 +6169,69 @@ def CIR_VecExtractOp : CIR_Op<"vec.extract", [
let hasFolder = 1;
}
+//===----------------------------------------------------------------------===//
+// VecReduceOp
+//===----------------------------------------------------------------------===//
+
+def CIR_VecReduceKind : CIR_I32Enum<
+ "VecReduceKind", "vector reduction operation kind", [
+ I32EnumCase<"Add", 0, "add">,
+ I32EnumCase<"Mul", 1, "mul">,
+ I32EnumCase<"And", 2, "and">,
+ I32EnumCase<"Or", 3, "or">,
+ I32EnumCase<"Xor", 4, "xor">,
+ I32EnumCase<"SMax", 5, "smax">,
+ I32EnumCase<"SMin", 6, "smin">,
+ I32EnumCase<"UMax", 7, "umax">,
+ I32EnumCase<"UMin", 8, "umin">,
+ I32EnumCase<"FAdd", 9, "fadd">,
+ I32EnumCase<"FMul", 10, "fmul">,
+ I32EnumCase<"FMax", 11, "fmax">,
+ I32EnumCase<"FMin", 12, "fmin">
+]>;
+
+def CIR_VecReduceKindAttr
+ : CIR_EnumAttr<CIR_VecReduceKind, "vec_reduce">;
+
+def CIR_VecReduceOp : CIR_Op<"vec.reduce", [
+ Pure,
+ TypesMatchWith<"type of 'result' matches element type of 'input'",
+ "input", "result",
+ "mlir::cast<cir::VectorType>($_self).getElementType()">
+]> {
+ let summary = "Reduce a vector to a scalar";
+ let description = [{
+ The `cir.vec.reduce` operation combines the elements of a vector using the
+ specified reduction kind and returns a scalar of the vector element type.
+ Floating-point addition and multiplication require an accumulator value.
+
+ Examples:
+
+ ```
+ %sum = cir.vec.reduce(add, %vec) : (!cir.vector<4 x !s32i>) -> !s32i
+ %fsum = cir.vec.reduce(fadd, %fvec, %start) :
+ (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float
+ <fastmath_flags = [reassoc]>
+ ```
+ }];
+
+ let arguments = (ins
+ CIR_VectorType:$input,
+ Optional<CIR_VectorElementType>:$accumulator,
+ CIR_VecReduceKindAttr:$kind,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath_flags
+ );
+
+ let results = (outs CIR_VectorElementType:$result);
+
+ let assemblyFormat = [{
+ `(` enum($kind) `,` $input (`,` $accumulator^)? `)` `:`
+ functional-type(operands, results) prop-dict attr-dict
+ }];
+
+ let hasVerifier = 1;
+}
+
//===----------------------------------------------------------------------===//
// VecCmpOp
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 9203cc0b9f7220f..4ef1bdb757a292b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -2193,7 +2193,8 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
return errorBuiltinNYI(*this, e, builtinID);
case Builtin::BI__builtin_reduce_max:
case Builtin::BI__builtin_reduce_min: {
- auto getIntrinsicName = [this, builtinIDIfNoAsmLabel](QualType type) {
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
+ auto getReductionKind = [this, builtinIDIfNoAsmLabel](QualType type) {
if (const auto *vecTy = type->getAs<VectorType>())
type = vecTy->getElementType();
else if (type->isSizelessVectorType())
@@ -2201,52 +2202,64 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
if (builtinIDIfNoAsmLabel == Builtin::BI__builtin_reduce_max) {
if (type->isSignedIntegerType())
- return "vector.reduce.smax";
+ return cir::VecReduceKind::SMax;
if (type->isUnsignedIntegerType())
- return "vector.reduce.umax";
+ return cir::VecReduceKind::UMax;
assert(type->isFloatingType() && "must have a float here");
- return "vector.reduce.fmax";
+ return cir::VecReduceKind::FMax;
}
if (type->isSignedIntegerType())
- return "vector.reduce.smin";
+ return cir::VecReduceKind::SMin;
if (type->isUnsignedIntegerType())
- return "vector.reduce.umin";
+ return cir::VecReduceKind::UMin;
assert(type->isFloatingType() && "must have a float here");
- return "vector.reduce.fmin";
+ return cir::VecReduceKind::FMin;
};
- return emitBuiltinWithOneOverloadedType<1>(
- e, getIntrinsicName(e->getArg(0)->getType()),
- cast<cir::VectorType>(convertType(e->getArg(0)->getType()))
- .getElementType());
+ mlir::Value input = emitScalarExpr(e->getArg(0));
+ cir::VecReduceKind kind = getReductionKind(e->getArg(0)->getType());
+ cir::FastMathFlagsAttr fastMath;
+ if (kind == cir::VecReduceKind::FMax || kind == cir::VecReduceKind::FMin)
+ fastMath = getFastMathFlagsAttr();
+ auto reduction = cir::VecReduceOp::create(
+ builder, getLoc(e->getExprLoc()), input, mlir::Value{}, kind, fastMath);
+ return RValue::get(reduction.getResult());
}
case Builtin::BI__builtin_reduce_add:
- return emitBuiltinWithOneOverloadedType<1>(
- e, "vector.reduce.add",
- cast<cir::VectorType>(convertType(e->getArg(0)->getType()))
- .getElementType());
case Builtin::BI__builtin_reduce_mul:
- return emitBuiltinWithOneOverloadedType<1>(
- e, "vector.reduce.mul",
- cast<cir::VectorType>(convertType(e->getArg(0)->getType()))
- .getElementType());
case Builtin::BI__builtin_reduce_xor:
- return emitBuiltinWithOneOverloadedType<1>(
- e, "vector.reduce.xor",
- cast<cir::VectorType>(convertType(e->getArg(0)->getType()))
- .getElementType());
case Builtin::BI__builtin_reduce_or:
- return emitBuiltinWithOneOverloadedType<1>(
- e, "vector.reduce.or",
- cast<cir::VectorType>(convertType(e->getArg(0)->getType()))
- .getElementType());
- case Builtin::BI__builtin_reduce_and:
- return emitBuiltinWithOneOverloadedType<1>(
- e, "vector.reduce.and",
- cast<cir::VectorType>(convertType(e->getArg(0)->getType()))
- .getElementType());
+ case Builtin::BI__builtin_reduce_and: {
+ cir::VecReduceKind kind;
+ switch (builtinIDIfNoAsmLabel) {
+ case Builtin::BI__builtin_reduce_add:
+ kind = cir::VecReduceKind::Add;
+ break;
+ case Builtin::BI__builtin_reduce_mul:
+ kind = cir::VecReduceKind::Mul;
+ break;
+ case Builtin::BI__builtin_reduce_xor:
+ kind = cir::VecReduceKind::Xor;
+ break;
+ case Builtin::BI__builtin_reduce_or:
+ kind = cir::VecReduceKind::Or;
+ break;
+ case Builtin::BI__builtin_reduce_and:
+ kind = cir::VecReduceKind::And;
+ break;
+ default:
+ llvm_unreachable("unexpected vector reduction builtin");
+ }
+
+ mlir::Value input = emitScalarExpr(e->getArg(0));
+ auto reduction =
+ cir::VecReduceOp::create(builder, getLoc(e->getExprLoc()), input,
+ mlir::Value{}, kind, cir::FastMathFlagsAttr{});
+ return RValue::get(reduction.getResult());
+ }
case Builtin::BI__builtin_reduce_assoc_fadd:
case Builtin::BI__builtin_reduce_in_order_fadd: {
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
bool isAssociative =
builtinIDIfNoAsmLabel == Builtin::BI__builtin_reduce_assoc_fadd;
@@ -2273,15 +2286,12 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
/*Negative=*/true)));
}
- SmallVector<mlir::Value, 2> args = {startValue, vector};
- cir::FastMathFlagsAttr fastMath;
- if (isAssociative)
- fastMath = cir::FastMathFlagsAttr::get(&getMLIRContext(),
- cir::FastMathFlags::reassoc);
+ cir::FastMathFlagsAttr fastMath = getFastMathFlagsAttr(
+ isAssociative ? cir::FastMathFlags::reassoc : cir::FastMathFlags::none);
- mlir::Value result = builder.emitIntrinsicCallOp(loc, "vector.reduce.fadd",
- scalarTy, fastMath, args);
- return RValue::get(result);
+ auto reduction = cir::VecReduceOp::create(
+ builder, loc, vector, startValue, cir::VecReduceKind::FAdd, fastMath);
+ return RValue::get(reduction.getResult());
}
case Builtin::BI__builtin_reduce_maximum:
case Builtin::BI__builtin_reduce_minimum:
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index bc376e4aaab616d..0b5545fdf13e869 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -2425,42 +2425,50 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI__builtin_ia32_reduce_fadd_ph512:
case X86::BI__builtin_ia32_reduce_fadd_ph256:
case X86::BI__builtin_ia32_reduce_fadd_ph128: {
- assert(!cir::MissingFeatures::fastMathFlags());
- return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
- "vector.reduce.fadd", ops[0].getType(),
- mlir::ValueRange{ops[0], ops[1]});
+ CIRGenFPOptionsRAII FPOptsRAII(*this, expr);
+ cir::FastMathFlagsAttr fastMath =
+ getFastMathFlagsAttr(cir::FastMathFlags::reassoc);
+ return cir::VecReduceOp::create(builder, getLoc(expr->getExprLoc()), ops[1],
+ ops[0], cir::VecReduceKind::FAdd, fastMath)
+ .getResult();
}
case X86::BI__builtin_ia32_reduce_fmul_pd512:
case X86::BI__builtin_ia32_reduce_fmul_ps512:
case X86::BI__builtin_ia32_reduce_fmul_ph512:
case X86::BI__builtin_ia32_reduce_fmul_ph256:
case X86::BI__builtin_ia32_reduce_fmul_ph128: {
- assert(!cir::MissingFeatures::fastMathFlags());
- return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
- "vector.reduce.fmul", ops[0].getType(),
- mlir::ValueRange{ops[0], ops[1]});
+ CIRGenFPOptionsRAII FPOptsRAII(*this, expr);
+ cir::FastMathFlagsAttr fastMath =
+ getFastMathFlagsAttr(cir::FastMathFlags::reassoc);
+ return cir::VecReduceOp::create(builder, getLoc(expr->getExprLoc()), ops[1],
+ ops[0], cir::VecReduceKind::FMul, fastMath)
+ .getResult();
}
case X86::BI__builtin_ia32_reduce_fmax_pd512:
case X86::BI__builtin_ia32_reduce_fmax_ps512:
case X86::BI__builtin_ia32_reduce_fmax_ph512:
case X86::BI__builtin_ia32_reduce_fmax_ph256:
case X86::BI__builtin_ia32_reduce_fmax_ph128: {
- assert(!cir::MissingFeatures::fastMathFlags());
- cir::VectorType vecTy = cast<cir::VectorType>(ops[0].getType());
- return builder.emitIntrinsicCallOp(
- getLoc(expr->getExprLoc()), "vector.reduce.fmax",
- vecTy.getElementType(), mlir::ValueRange{ops[0]});
+ CIRGenFPOptionsRAII FPOptsRAII(*this, expr);
+ cir::FastMathFlagsAttr fastMath =
+ getFastMathFlagsAttr(cir::FastMathFlags::nnan);
+ return cir::VecReduceOp::create(builder, getLoc(expr->getExprLoc()), ops[0],
+ mlir::Value{}, cir::VecReduceKind::FMax,
+ fastMath)
+ .getResult();
}
case X86::BI__builtin_ia32_reduce_fmin_pd512:
case X86::BI__builtin_ia32_reduce_fmin_ps512:
case X86::BI__builtin_ia32_reduce_fmin_ph512:
case X86::BI__builtin_ia32_reduce_fmin_ph256:
case X86::BI__builtin_ia32_reduce_fmin_ph128: {
- assert(!cir::MissingFeatures::fastMathFlags());
- cir::VectorType vecTy = cast<cir::VectorType>(ops[0].getType());
- return builder.emitIntrinsicCallOp(
- getLoc(expr->getExprLoc()), "vector.reduce.fmin",
- vecTy.getElementType(), mlir::ValueRange{ops[0]});
+ CIRGenFPOptionsRAII FPOptsRAII(*this, expr);
+ cir::FastMathFlagsAttr fastMath =
+ getFastMathFlagsAttr(cir::FastMathFlags::nnan);
+ return cir::VecReduceOp::create(builder, getLoc(expr->getExprLoc()), ops[0],
+ mlir::Value{}, cir::VecReduceKind::FMin,
+ fastMath)
+ .getResult();
}
case X86::BI__builtin_ia32_rdrand16_step:
case X86::BI__builtin_ia32_rdrand32_step:
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 382a0008113e225..4809e7680d303eb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -1471,6 +1471,29 @@ CIRGenFunction::CIRGenFPOptionsRAII::~CIRGenFPOptionsRAII() {
cgf.builder.setDefaultConstrainedRounding(oldRounding);
}
+cir::FastMathFlagsAttr
+CIRGenFunction::getFastMathFlagsAttr(cir::FastMathFlags additionalFlags) {
+ cir::FastMathFlags flags = additionalFlags;
+ if (curFPFeatures.getAllowFPReassociate())
+ flags |= cir::FastMathFlags::reassoc;
+ if (curFPFeatures.getNoHonorNaNs())
+ flags |= cir::FastMathFlags::nnan;
+ if (curFPFeatures.getNoHonorInfs())
+ flags |= cir::FastMathFlags::ninf;
+ if (curFPFeatures.getNoSignedZero())
+ flags |= cir::FastMathFlags::nsz;
+ if (curFPFeatures.getAllowReciprocal())
+ flags |= cir::FastMathFlags::arcp;
+ if (curFPFeatures.getAllowApproxFunc())
+ flags |= cir::FastMathFlags::afn;
+ if (curFPFeatures.allowFPContractAcrossStatement())
+ flags |= cir::FastMathFlags::contract;
+
+ if (flags == cir::FastMathFlags::none)
+ return {};
+ return cir::FastMathFlagsAttr::get(&getMLIRContext(), flags);
+}
+
// TODO(cir): should be shared with LLVM codegen.
bool CIRGenFunction::shouldNullCheckClassCastValue(const CastExpr *ce) {
const Expr *e = ce->getSubExpr();
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index c6427d60a379268..3b6e7b0ccae93b6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -342,6 +342,11 @@ class CIRGenFunction : public CIRGenTypeCache {
};
clang::FPOptions curFPFeatures;
+ /// Convert the active Clang floating-point options to CIR fast-math flags,
+ /// including any flags required by the operation itself.
+ cir::FastMathFlagsAttr getFastMathFlagsAttr(
+ cir::FastMathFlags additionalFlags = cir::FastMathFlags::none);
+
/// The symbol table maps a variable name to a value in the current scope.
/// Entering a function creates a new scope, and the function arguments are
/// added to the mapping. When the processing of a function is terminated,
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 15cebd358040e3f..07c2b2ef09ba1ca 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -4098,6 +4098,77 @@ OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
return elements[index];
}
+//===----------------------------------------------------------------------===//
+// VecReduceOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::VecReduceOp::verify() {
+ mlir::Type elementTy = getInput().getType().getElementType();
+ const bool hasAccumulator = static_cast<bool>(getAccumulator());
+ const bool isFloatingPoint = cir::isAnyFloatingPointType(elementTy);
+ const bool isInteger = mlir::isa<cir::IntType>(elementTy);
+ const bool isIntegerOrBool = isInteger || mlir::isa<cir::BoolType>(elementTy);
+
+ if (getAccumulator() && getAccumulator().getType() != elementTy)
+ return emitOpError() << "accumulator type " << getAccumulator().getType()
+ << " doesn't match vector element type " << elementTy;
+
+ const bool requiresAccumulator = getKind() == cir::VecReduceKind::FAdd ||
+ getKind() == cir::VecReduceKind::FMul;
+ if (hasAccumulator != requiresAccumulator)
+ return emitOpError() << (requiresAccumulator ? "requires"
+ : "does not accept")
+ << " an accumulator for "
+ << stringifyVecReduceKind(getKind()) << " reduction";
+
+ if (getFastmathFlagsAttr() && !isFloatingPoint)
+ return emitOpError()
+ << "fast-math flags are only valid for floating-point reductions";
+
+ switch (getKind()) {
+ case cir::VecReduceKind::Add:
+ case cir::VecReduceKind::Mul:
+ if (!isIntegerOrBool)
+ return emitOpError() << "requires an integer or boolean vector for "
+ << stringifyVecReduceKind(getKind()) << " reduction";
+ break;
+ case cir::VecReduceKind::And:
+ case cir::VecReduceKind::Or:
+ case cir::VecReduceKind::Xor:
+ if (!isIntegerOrBool)
+ return emitOpError() << "requires an integer or boolean vector for "
+ << stringifyVecReduceKind(getKind()) << " reduction";
+ break;
+ case cir::VecReduceKind::SMax:
+ case cir::VecReduceKind::SMin: {
+ auto intTy = mlir::dyn_cast<cir::IntType>(elementTy);
+ if (!intTy || !intTy.isSigned())
+ return emitOpError() << "requires a signed integer vector for "
+ << stringifyVecReduceKind(getKind()) << " reduction";
+ break;
+ }
+ case cir::VecReduceKind::UMax:
+ case cir::VecReduceKind::UMin: {
+ auto intTy = mlir::dyn_cast<cir::IntType>(elementTy);
+ if ((!intTy || !intTy.isUnsigned()) && !mlir::isa<cir::BoolType>(elementTy))
+ return emitOpError()
+ << "requires an unsigned integer or boolean vector for "
+ << stringifyVecReduceKind(getKind()) << " reduction";
+ break;
+ }
+ case cir::VecReduceKind::FAdd:
+ case cir::VecReduceKind::FMul:
+ case cir::VecReduceKind::FMax:
+ case cir::VecReduceKind::FMin:
+ if (!isFloatingPoint)
+ return emitOpError() << "requires a floating-point vector for "
+ << stringifyVecReduceKind(getKind()) << " reduction";
+ break;
+ }
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// CmpOp
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 8c6679c1c5c512c..7fd1ce78e549690 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5076,6 +5076,74 @@ mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
return mlir::success();
}
+mlir::LogicalResult CIRToLLVMVecReduceOpLowering::matchAndRewrite(
+ cir::VecReduceOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
+ mlir::LLVM::FastmathFlags fastmathFlags{};
+ if (std::optional<cir::FastMathFlags> fastmath = op.getFastmathFlags())
+ fastmathFlags = convertFastMathFlags(*fastmath);
+
+ switch (op.getKind()) {
+ case cir::VecReduceKind::Add:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_add>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::Mul:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_mul>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::And:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_and>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::Or:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_or>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::Xor:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_xor>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::SMax:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_smax>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::SMin:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_smin>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::UMax:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_umax>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::UMin:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_umin>(
+ op, resultTy, adaptor.getInput());
+ break;
+ case cir::VecReduceKind::FAdd:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_fadd>(
+ op, resultTy, adaptor.getAccumulator(), adaptor.getInput(),
+ fastmathFlags);
+ break;
+ case cir::VecReduceKind::FMul:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_fmul>(
+ op, resultTy, adaptor.getAccumulator(), adaptor.getInput(),
+ fastmathFlags);
+ break;
+ case cir::VecReduceKind::FMax:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_fmax>(
+ op, resultTy, adaptor.getInput(), fastmathFlags);
+ break;
+ case cir::VecReduceKind::FMin:
+ rewriter.replaceOpWithNewOp<mlir::LLVM::vector_reduce_fmin>(
+ op, resultTy, adaptor.getInput(), fastmathFlags);
+ break;
+ }
+
+ return mlir::success();
+}
+
mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
cir::VecCmpOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx512-reduceIntrin.c b/clang/test/CIR/CodeGenBuiltins/X86/avx512-reduceIntrin.c
index acb6dca7a24f509..b9d2f20ee457315 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx512-reduceIntrin.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx512-reduceIntrin.c
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -x c -ffreestanding %s -O2 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -fclangir -emit-cir -o - -Wall -Werror | FileCheck %s --check-prefixes=CIR
// RUN: %clang_cc1 -x c -ffreestanding %s -O2 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -fclangir -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=LLVM
// RUN: %clang_cc1 -x c -ffreestanding %s -O2 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=OGCG
+// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -menable-no-infs -fclangir -emit-cir -o - -Wall -Werror | FileCheck %s --check-prefix=CIR-NINF
+// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -menable-no-infs -fclangir -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=LLVM-NINF
+// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -menable-no-infs -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=LLVM-NINF
#include <immintrin.h>
@@ -10,10 +13,14 @@ double test_mm512_reduce_add_pd(__m512d __W, double ExtraAddOp){
// CIR: cir.call @_mm512_reduce_add_pd(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<8 x !cir.double>{{.*}}) -> !cir.double
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_add_pd(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" %[[R:.*]], %[[V:.*]] : (!cir.double{{.*}}, !cir.vector<8 x !cir.double>{{.*}}) -> !cir.double
+ // CIR: cir.vec.reduce(fadd, %[[V:.*]], %[[R:.*]]) : (!cir.vector<8 x !cir.double>, !cir.double) -> !cir.double <fastmath_flags = [reassoc]>
+ // CIR-NINF-LABEL: cir.func{{.*}} @_mm512_reduce_add_pd(
+ // CIR-NINF: cir.vec.reduce(fadd, {{.*}}) {{.*}} <fastmath_flags = [ninf, reassoc]>
// LLVM-LABEL: test_mm512_reduce_add_pd
- // LLVM: call double @llvm.vector.reduce.fadd.v8f64(double -0.000000e+00, <8 x double> %{{.*}})
+ // LLVM: call reassoc double @llvm.vector.reduce.fadd.v8f64(double -0.000000e+00, <8 x double> %{{.*}})
+ // LLVM-NINF-LABEL: define {{.*}} @test_mm512_reduce_add_pd(
+ // LLVM-NINF: call reassoc ninf {{.*}}double @llvm.vector.reduce.fadd.v8f64(
// OGCG-LABEL: test_mm512_reduce_add_pd
// OGCG-NOT: reassoc
@@ -27,10 +34,14 @@ double test_mm512_reduce_mul_pd(__m512d __W, double ExtraMulOp){
// CIR: cir.call @_mm512_reduce_mul_pd(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<8 x !cir.double>{{.*}}) -> !cir.double
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_mul_pd(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmul" %[[R:.*]], %[[V:.*]] : (!cir.double{{.*}}, !cir.vector<8 x !cir.double>{{.*}}) -> !cir.double
+ // CIR: cir.vec.reduce(fmul, %[[V:.*]], %[[R:.*]]) : (!cir.vector<8 x !cir.double>, !cir.double) -> !cir.double <fastmath_flags = [reassoc]>
+ // CIR-NINF-LABEL: cir.func{{.*}} @_mm512_reduce_mul_pd(
+ // CIR-NINF: cir.vec.reduce(fmul, {{.*}}) {{.*}} <fastmath_flags = [ninf, reassoc]>
// LLVM-LABEL: test_mm512_reduce_mul_pd
- // LLVM: call double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}})
+ // LLVM: call reassoc double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}})
+ // LLVM-NINF-LABEL: define {{.*}} @test_mm512_reduce_mul_pd(
+ // LLVM-NINF: call reassoc ninf {{.*}}double @llvm.vector.reduce.fmul.v8f64(
// OGCG-LABEL: test_mm512_reduce_mul_pd
// OGCG-NOT: reassoc
@@ -45,10 +56,10 @@ float test_mm512_reduce_add_ps(__m512 __W){
// CIR: cir.call @_mm512_reduce_add_ps(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<16 x !cir.float>{{.*}}) -> !cir.float
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_add_ps(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" %[[R:.*]], %[[V:.*]] : (!cir.float{{.*}}, !cir.vector<16 x !cir.float>{{.*}}) -> !cir.float
+ // CIR: cir.vec.reduce(fadd, %[[V:.*]], %[[R:.*]]) : (!cir.vector<16 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [reassoc]>
// LLVM-LABEL: test_mm512_reduce_add_ps
- // LLVM: call float @llvm.vector.reduce.fadd.v16f32(float -0.000000e+00, <16 x float> %{{.*}})
+ // LLVM: call reassoc float @llvm.vector.reduce.fadd.v16f32(float -0.000000e+00, <16 x float> %{{.*}})
// OGCG-LABEL: test_mm512_reduce_add_ps
// OGCG: call reassoc {{.*}}float @llvm.vector.reduce.fadd.v16f32(float -0.000000e+00, <16 x float> %{{.*}})
@@ -60,10 +71,10 @@ float test_mm512_reduce_mul_ps(__m512 __W){
// CIR: cir.call @_mm512_reduce_mul_ps(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<16 x !cir.float>{{.*}}) -> !cir.float
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_mul_ps(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmul" %[[R:.*]], %[[V:.*]] : (!cir.float{{.*}}, !cir.vector<16 x !cir.float>{{.*}}) -> !cir.float
+ // CIR: cir.vec.reduce(fmul, %[[V:.*]], %[[R:.*]]) : (!cir.vector<16 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [reassoc]>
// LLVM-LABEL: test_mm512_reduce_mul_ps
- // LLVM: call float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}})
+ // LLVM: call reassoc float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}})
// OGCG-LABEL: test_mm512_reduce_mul_ps
// OGCG: call reassoc {{.*}}float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}})
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx512-reduceMinMaxIntrin.c b/clang/test/CIR/CodeGenBuiltins/X86/avx512-reduceMinMaxIntrin.c
index eb60be24e9345ff..913162a33679435 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx512-reduceMinMaxIntrin.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx512-reduceMinMaxIntrin.c
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -fclangir -emit-cir -o - -Wall -Werror | FileCheck %s --check-prefixes=CIR
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -fclangir -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=LLVM
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=OGCG
+// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -menable-no-infs -fclangir -emit-cir -o - -Wall -Werror | FileCheck %s --check-prefix=CIR-NINF
+// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -menable-no-infs -fclangir -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=LLVM-NINF
+// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -menable-no-infs -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=LLVM-NINF
#include <immintrin.h>
@@ -9,10 +12,14 @@ double test_mm512_reduce_max_pd(__m512d __W, double ExtraAddOp){
// CIR: cir.call @_mm512_reduce_max_pd(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<8 x !cir.double>{{.*}}) -> !cir.double
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_max_pd(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmax" %[[V:.*]] : (!cir.vector<8 x !cir.double>{{.*}}) -> !cir.double
+ // CIR: cir.vec.reduce(fmax, %[[V:.*]]) : (!cir.vector<8 x !cir.double>) -> !cir.double <fastmath_flags = [nnan]>
+ // CIR-NINF-LABEL: cir.func{{.*}} @_mm512_reduce_max_pd(
+ // CIR-NINF: cir.vec.reduce(fmax, {{.*}}) {{.*}} <fastmath_flags = [nnan, ninf]>
// LLVM-LABEL: test_mm512_reduce_max_pd
- // LLVM: call double @llvm.vector.reduce.fmax.v8f64(<8 x double> %{{.*}})
+ // LLVM: call nnan double @llvm.vector.reduce.fmax.v8f64(<8 x double> %{{.*}})
+ // LLVM-NINF-LABEL: define {{.*}} @test_mm512_reduce_max_pd(
+ // LLVM-NINF: call nnan ninf {{.*}}double @llvm.vector.reduce.fmax.v8f64(
// OGCG-LABEL: test_mm512_reduce_max_pd
// OGCG-NOT: nnan
@@ -26,10 +33,14 @@ double test_mm512_reduce_min_pd(__m512d __W, double ExtraMulOp){
// CIR: cir.call @_mm512_reduce_min_pd(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<8 x !cir.double>{{.*}}) -> !cir.double
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_min_pd(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmin" %[[V:.*]] : (!cir.vector<8 x !cir.double>{{.*}}) -> !cir.double
+ // CIR: cir.vec.reduce(fmin, %[[V:.*]]) : (!cir.vector<8 x !cir.double>) -> !cir.double <fastmath_flags = [nnan]>
+ // CIR-NINF-LABEL: cir.func{{.*}} @_mm512_reduce_min_pd(
+ // CIR-NINF: cir.vec.reduce(fmin, {{.*}}) {{.*}} <fastmath_flags = [nnan, ninf]>
// LLVM-LABEL: test_mm512_reduce_min_pd
- // LLVM: call double @llvm.vector.reduce.fmin.v8f64(<8 x double> %{{.*}})
+ // LLVM: call nnan double @llvm.vector.reduce.fmin.v8f64(<8 x double> %{{.*}})
+ // LLVM-NINF-LABEL: define {{.*}} @test_mm512_reduce_min_pd(
+ // LLVM-NINF: call nnan ninf {{.*}}double @llvm.vector.reduce.fmin.v8f64(
// OGCG-LABEL: test_mm512_reduce_min_pd
// OGCG-NOT: nnan
@@ -43,10 +54,10 @@ float test_mm512_reduce_max_ps(__m512 __W){
// CIR: cir.call @_mm512_reduce_max_ps(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<16 x !cir.float>{{.*}}) -> !cir.float
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_max_ps(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmax" %[[V:.*]] : (!cir.vector<16 x !cir.float>{{.*}}) -> !cir.float
+ // CIR: cir.vec.reduce(fmax, %[[V:.*]]) : (!cir.vector<16 x !cir.float>) -> !cir.float <fastmath_flags = [nnan]>
// LLVM-LABEL: test_mm512_reduce_max_ps
- // LLVM: call float @llvm.vector.reduce.fmax.v16f32(<16 x float> %{{.*}})
+ // LLVM: call nnan float @llvm.vector.reduce.fmax.v16f32(<16 x float> %{{.*}})
// OGCG-LABEL: test_mm512_reduce_max_ps
// OGCG: call nnan {{.*}}float @llvm.vector.reduce.fmax.v16f32(<16 x float> %{{.*}})
@@ -58,10 +69,10 @@ float test_mm512_reduce_min_ps(__m512 __W){
// CIR: cir.call @_mm512_reduce_min_ps(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<16 x !cir.float>{{.*}}) -> !cir.float
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_min_ps(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmin" %[[V:.*]] : (!cir.vector<16 x !cir.float>{{.*}}) -> !cir.float
+ // CIR: cir.vec.reduce(fmin, %[[V:.*]]) : (!cir.vector<16 x !cir.float>) -> !cir.float <fastmath_flags = [nnan]>
// LLVM-LABEL: test_mm512_reduce_min_ps
- // LLVM: call float @llvm.vector.reduce.fmin.v16f32(<16 x float> %{{.*}})
+ // LLVM: call nnan float @llvm.vector.reduce.fmin.v16f32(<16 x float> %{{.*}})
// OGCG-LABEL: test_mm512_reduce_min_ps
// OGCG: call nnan {{.*}}float @llvm.vector.reduce.fmin.v16f32(<16 x float> %{{.*}})
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx512fp16-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx512fp16-builtins.c
index 470b72075e2200f..13080f7f4272667 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx512fp16-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx512fp16-builtins.c
@@ -70,10 +70,10 @@ _Float16 test_mm512_reduce_add_ph(__m512h __W) {
// CIR: cir.call @_mm512_reduce_add_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<32 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_add_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" %[[R:.*]], %[[V:.*]] : (!cir.f16{{.*}}, !cir.vector<32 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fadd, %[[V:.*]], %[[R:.*]]) : (!cir.vector<32 x !cir.f16>, !cir.f16) -> !cir.f16 <fastmath_flags = [reassoc]>
// LLVM-LABEL: test_mm512_reduce_add_ph
- // LLVM: call half @llvm.vector.reduce.fadd.v32f16(half -0.000000e+00, <32 x half> %{{.*}})
+ // LLVM: call reassoc half @llvm.vector.reduce.fadd.v32f16(half -0.000000e+00, <32 x half> %{{.*}})
// OGCG-LABEL: test_mm512_reduce_add_ph
// OGCG: call reassoc {{.*}}half @llvm.vector.reduce.fadd.v32f16(half -0.000000e+00, <32 x half> %{{.*}})
@@ -85,10 +85,10 @@ _Float16 test_mm512_reduce_mul_ph(__m512h __W) {
// CIR: cir.call @_mm512_reduce_mul_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<32 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_mul_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmul" %[[R:.*]], %[[V:.*]] : (!cir.f16{{.*}}, !cir.vector<32 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmul, %[[V:.*]], %[[R:.*]]) : (!cir.vector<32 x !cir.f16>, !cir.f16) -> !cir.f16 <fastmath_flags = [reassoc]>
// LLVM-LABEL: test_mm512_reduce_mul_ph
- // LLVM: call half @llvm.vector.reduce.fmul.v32f16(half 1.000000e+00, <32 x half> %{{.*}})
+ // LLVM: call reassoc half @llvm.vector.reduce.fmul.v32f16(half 1.000000e+00, <32 x half> %{{.*}})
// OGCG-LABEL: test_mm512_reduce_mul_ph
// OGCG: call reassoc {{.*}}half @llvm.vector.reduce.fmul.v32f16(half 1.000000e+00, <32 x half> %{{.*}})
@@ -100,10 +100,10 @@ _Float16 test_mm512_reduce_max_ph(__m512h __W) {
// CIR: cir.call @_mm512_reduce_max_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<32 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_max_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmax" %[[V:.*]] (!cir.vector<32 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmax, %[[V:.*]]) : (!cir.vector<32 x !cir.f16>) -> !cir.f16 <fastmath_flags = [nnan]>
// LLVM-LABEL: test_mm512_reduce_max_ph
- // LLVM: call half @llvm.vector.reduce.fmax.v32f16(<32 x half> %{{.*}})
+ // LLVM: call nnan half @llvm.vector.reduce.fmax.v32f16(<32 x half> %{{.*}})
// OGCG-LABEL: test_mm512_reduce_max_ph
// OGCG: call nnan {{.*}}half @llvm.vector.reduce.fmax.v32f16(<32 x half> %{{.*}})
@@ -115,10 +115,10 @@ _Float16 test_mm512_reduce_min_ph(__m512h __W) {
// CIR: cir.call @_mm512_reduce_min_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<32 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm512_reduce_min_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmin" %[[V:.*]] (!cir.vector<32 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmin, %[[V:.*]]) : (!cir.vector<32 x !cir.f16>) -> !cir.f16 <fastmath_flags = [nnan]>
// LLVM-LABEL: test_mm512_reduce_min_ph
- // LLVM: call half @llvm.vector.reduce.fmin.v32f16(<32 x half> %{{.*}})
+ // LLVM: call nnan half @llvm.vector.reduce.fmin.v32f16(<32 x half> %{{.*}})
// OGCG-LABEL: test_mm512_reduce_min_ph
// OGCG: call nnan {{.*}}half @llvm.vector.reduce.fmin.v32f16(<32 x half> %{{.*}})
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx512vlfp16-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx512vlfp16-builtins.c
index f6be98ca40dbf64..279e1c0c1f9eb16 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx512vlfp16-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx512vlfp16-builtins.c
@@ -12,10 +12,10 @@ _Float16 test_mm256_reduce_add_ph(__m256h __W) {
// CIR: cir.call @_mm256_reduce_add_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<16 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm256_reduce_add_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" %[[R:.*]], %[[V:.*]] : (!cir.f16{{.*}}, !cir.vector<16 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fadd, %[[V:.*]], %[[R:.*]]) : (!cir.vector<16 x !cir.f16>, !cir.f16) -> !cir.f16 <fastmath_flags = [reassoc]>
// LLVM-LABEL: test_mm256_reduce_add_ph
- // LLVM: call half @llvm.vector.reduce.fadd.v16f16(half -0.000000e+00, <16 x half> %{{.*}})
+ // LLVM: call reassoc half @llvm.vector.reduce.fadd.v16f16(half -0.000000e+00, <16 x half> %{{.*}})
// OGCG-LABEL: test_mm256_reduce_add_ph
// OGCG: call reassoc {{.*}}@llvm.vector.reduce.fadd.v16f16(half -0.000000e+00, <16 x half> %{{.*}})
@@ -27,10 +27,10 @@ _Float16 test_mm256_reduce_mul_ph(__m256h __W) {
// CIR: cir.call @_mm256_reduce_mul_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<16 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm256_reduce_mul_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmul" %[[R:.*]], %[[V:.*]] : (!cir.f16{{.*}}, !cir.vector<16 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmul, %[[V:.*]], %[[R:.*]]) : (!cir.vector<16 x !cir.f16>, !cir.f16) -> !cir.f16 <fastmath_flags = [reassoc]>
// LLVM-LABEL: test_mm256_reduce_mul_ph
- // LLVM: call half @llvm.vector.reduce.fmul.v16f16(half 1.000000e+00, <16 x half> %{{.*}})
+ // LLVM: call reassoc half @llvm.vector.reduce.fmul.v16f16(half 1.000000e+00, <16 x half> %{{.*}})
// OGCG-LABEL: test_mm256_reduce_mul_ph
// OGCG: call reassoc {{.*}}@llvm.vector.reduce.fmul.v16f16(half 1.000000e+00, <16 x half> %{{.*}})
@@ -42,10 +42,10 @@ _Float16 test_mm256_reduce_max_ph(__m256h __W) {
// CIR: cir.call @_mm256_reduce_max_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<16 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm256_reduce_max_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmax" %[[V:.*]] (!cir.vector<16 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmax, %[[V:.*]]) : (!cir.vector<16 x !cir.f16>) -> !cir.f16 <fastmath_flags = [nnan]>
// LLVM-LABEL: test_mm256_reduce_max_ph
- // LLVM: call half @llvm.vector.reduce.fmax.v16f16(<16 x half> %{{.*}})
+ // LLVM: call nnan half @llvm.vector.reduce.fmax.v16f16(<16 x half> %{{.*}})
// OGCG-LABEL: test_mm256_reduce_max_ph
// OGCG: call nnan {{.*}}@llvm.vector.reduce.fmax.v16f16(<16 x half> %{{.*}})
@@ -57,10 +57,10 @@ _Float16 test_mm256_reduce_min_ph(__m256h __W) {
// CIR: cir.call @_mm256_reduce_min_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<16 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm256_reduce_min_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmin" %[[V:.*]] : (!cir.vector<16 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmin, %[[V:.*]]) : (!cir.vector<16 x !cir.f16>) -> !cir.f16 <fastmath_flags = [nnan]>
// LLVM-LABEL: test_mm256_reduce_min_ph
- // LLVM: call half @llvm.vector.reduce.fmin.v16f16(<16 x half> %{{.*}})
+ // LLVM: call nnan half @llvm.vector.reduce.fmin.v16f16(<16 x half> %{{.*}})
// OGCG-LABEL: test_mm256_reduce_min_ph
// OGCG: call nnan {{.*}}@llvm.vector.reduce.fmin.v16f16(<16 x half> %{{.*}})
@@ -72,10 +72,10 @@ _Float16 test_mm_reduce_add_ph(__m128h __W) {
// CIR: cir.call @_mm_reduce_add_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<8 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm_reduce_add_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" %[[R:.*]], %[[V:.*]] : (!cir.f16{{.*}}, !cir.vector<8 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fadd, %[[V:.*]], %[[R:.*]]) : (!cir.vector<8 x !cir.f16>, !cir.f16) -> !cir.f16 <fastmath_flags = [reassoc]>
// LLVM-LABEL: test_mm_reduce_add_ph
- // LLVM: call half @llvm.vector.reduce.fadd.v8f16(half -0.000000e+00, <8 x half> %{{.*}})
+ // LLVM: call reassoc half @llvm.vector.reduce.fadd.v8f16(half -0.000000e+00, <8 x half> %{{.*}})
// OGCG-LABEL: test_mm_reduce_add_ph
// OGCG: call reassoc {{.*}}@llvm.vector.reduce.fadd.v8f16(half -0.000000e+00, <8 x half> %{{.*}})
@@ -87,10 +87,10 @@ _Float16 test_mm_reduce_mul_ph(__m128h __W) {
// CIR: cir.call @_mm_reduce_mul_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<8 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm_reduce_mul_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmul" %[[R:.*]], %[[V:.*]] : (!cir.f16{{.*}}, !cir.vector<8 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmul, %[[V:.*]], %[[R:.*]]) : (!cir.vector<8 x !cir.f16>, !cir.f16) -> !cir.f16 <fastmath_flags = [reassoc]>
// LLVM-LABEL: test_mm_reduce_mul_ph
- // LLVM: call half @llvm.vector.reduce.fmul.v8f16(half 1.000000e+00, <8 x half> %{{.*}})
+ // LLVM: call reassoc half @llvm.vector.reduce.fmul.v8f16(half 1.000000e+00, <8 x half> %{{.*}})
// OGCG-LABEL: test_mm_reduce_mul_ph
// OGCG: call reassoc {{.*}}@llvm.vector.reduce.fmul.v8f16(half 1.000000e+00, <8 x half> %{{.*}})
@@ -102,10 +102,10 @@ _Float16 test_mm_reduce_max_ph(__m128h __W) {
// CIR: cir.call @_mm_reduce_max_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<8 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm_reduce_max_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmax" %[[V:.*]] (!cir.vector<8 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmax, %[[V:.*]]) : (!cir.vector<8 x !cir.f16>) -> !cir.f16 <fastmath_flags = [nnan]>
// LLVM-LABEL: test_mm_reduce_max_ph
- // LLVM: call half @llvm.vector.reduce.fmax.v8f16(<8 x half> %{{.*}})
+ // LLVM: call nnan half @llvm.vector.reduce.fmax.v8f16(<8 x half> %{{.*}})
// OGCG-LABEL: test_mm_reduce_max_ph
// OGCG: call nnan {{.*}}@llvm.vector.reduce.fmax.v8f16(<8 x half> %{{.*}})
@@ -117,13 +117,12 @@ _Float16 test_mm_reduce_min_ph(__m128h __W) {
// CIR: cir.call @_mm_reduce_min_ph(%[[VEC:.*]]) {nobuiltin, nobuiltins = [{{.*}}]} : (!cir.vector<8 x !cir.f16>{{.*}}) -> !cir.f16
// CIR-LABEL: cir.func{{.*}} @_mm_reduce_min_ph(
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmin" %[[V:.*]] : (!cir.vector<8 x !cir.f16>{{.*}}) -> !cir.f16
+ // CIR: cir.vec.reduce(fmin, %[[V:.*]]) : (!cir.vector<8 x !cir.f16>) -> !cir.f16 <fastmath_flags = [nnan]>
// LLVM-LABEL: test_mm_reduce_min_ph
- // LLVM: call half @llvm.vector.reduce.fmin.v8f16(<8 x half> %{{.*}})
+ // LLVM: call nnan half @llvm.vector.reduce.fmin.v8f16(<8 x half> %{{.*}})
// OGCG-LABEL: test_mm_reduce_min_ph
// OGCG: call nnan {{.*}}@llvm.vector.reduce.fmin.v8f16(<8 x half> %{{.*}})
return _mm_reduce_min_ph(__W);
}
-
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic-sve.c b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic-sve.c
index 2ce6bdad767279b..e9f092645ce161d 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic-sve.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic-sve.c
@@ -14,7 +14,7 @@
int test_sve_reduce_add(svint32_t x) {
// CIR-LABEL: @test_sve_reduce_add
- // CIR: cir.call_llvm_intrinsic "vector.reduce.add"
+ // CIR: cir.vec.reduce(add,
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_add
// LLVM: call i32 @llvm.vector.reduce.add.nxv4i32(<vscale x 4 x i32>
@@ -24,7 +24,7 @@ int test_sve_reduce_add(svint32_t x) {
int test_sve_reduce_mul(svint32_t x) {
// CIR-LABEL: @test_sve_reduce_mul
- // CIR: cir.call_llvm_intrinsic "vector.reduce.mul"
+ // CIR: cir.vec.reduce(mul,
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_mul
// LLVM: call i32 @llvm.vector.reduce.mul.nxv4i32(<vscale x 4 x i32>
@@ -34,7 +34,7 @@ int test_sve_reduce_mul(svint32_t x) {
int test_sve_reduce_max(svint32_t x) {
// CIR-LABEL: @test_sve_reduce_max
- // CIR: cir.call_llvm_intrinsic "vector.reduce.smax"
+ // CIR: cir.vec.reduce(smax,
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_max
// LLVM: call i32 @llvm.vector.reduce.smax.nxv4i32(<vscale x 4 x i32>
@@ -44,7 +44,7 @@ int test_sve_reduce_max(svint32_t x) {
unsigned test_sve_reduce_max_unsigned(svuint32_t x) {
// CIR-LABEL: @test_sve_reduce_max_unsigned
- // CIR: cir.call_llvm_intrinsic "vector.reduce.umax"
+ // CIR: cir.vec.reduce(umax,
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_max_unsigned
// LLVM: call i32 @llvm.vector.reduce.umax.nxv4i32(<vscale x 4 x i32>
@@ -54,7 +54,7 @@ unsigned test_sve_reduce_max_unsigned(svuint32_t x) {
float test_sve_reduce_max_float(svfloat32_t x) {
// CIR-LABEL: @test_sve_reduce_max_float
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmax"
+ // CIR: cir.vec.reduce(fmax,
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_max_float
// LLVM: call float @llvm.vector.reduce.fmax.nxv4f32(<vscale x 4 x float>
@@ -64,7 +64,7 @@ float test_sve_reduce_max_float(svfloat32_t x) {
int test_sve_reduce_min(svint32_t x) {
// CIR-LABEL: @test_sve_reduce_min
- // CIR: cir.call_llvm_intrinsic "vector.reduce.smin"
+ // CIR: cir.vec.reduce(smin,
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_min
// LLVM: call i32 @llvm.vector.reduce.smin.nxv4i32(<vscale x 4 x i32>
@@ -74,7 +74,7 @@ int test_sve_reduce_min(svint32_t x) {
unsigned test_sve_reduce_min_unsigned(svuint32_t x) {
// CIR-LABEL: @test_sve_reduce_min_unsigned
- // CIR: cir.call_llvm_intrinsic "vector.reduce.umin"
+ // CIR: cir.vec.reduce(umin,
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_min_unsigned
// LLVM: call i32 @llvm.vector.reduce.umin.nxv4i32(<vscale x 4 x i32>
@@ -84,7 +84,7 @@ unsigned test_sve_reduce_min_unsigned(svuint32_t x) {
float test_sve_reduce_min_float(svfloat32_t x) {
// CIR-LABEL: @test_sve_reduce_min_float
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmin"
+ // CIR: cir.vec.reduce(fmin,
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_min_float
// LLVM: call float @llvm.vector.reduce.fmin.nxv4f32(<vscale x 4 x float>
@@ -94,7 +94,7 @@ float test_sve_reduce_min_float(svfloat32_t 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<reassoc>
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<[4] x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [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>
@@ -105,7 +105,7 @@ float test_sve_reduce_assoc_fadd(svfloat32_t x, float 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<reassoc>
+ // CIR: cir.vec.reduce(fadd, {{.*}}, %[[START]]) : (!cir.vector<[4] x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [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>
@@ -115,8 +115,7 @@ float test_sve_reduce_assoc_fadd_default_start(svfloat32_t 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-NOT: fastmath_flags
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<[4] x !cir.float>, !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>
@@ -127,7 +126,7 @@ float test_sve_reduce_in_order_fadd(svfloat32_t x, float start) {
float test_sve_reduce_in_order_fadd_cast_start(svfloat32_t x, double start) {
// CIR-LABEL: @test_sve_reduce_in_order_fadd_cast_start
// CIR: cir.cast floating {{.*}} : !cir.double -> !cir.float
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.float, !cir.vector<[4] x !cir.float>) -> !cir.float
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<[4] x !cir.float>, !cir.float) -> !cir.float
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_in_order_fadd_cast_start
// LLVM: fptrunc double %{{.*}} to float
@@ -138,7 +137,7 @@ float test_sve_reduce_in_order_fadd_cast_start(svfloat32_t x, double start) {
double test_sve_reduce_in_order_fadd_double(svfloat64_t x, double start) {
// CIR-LABEL: @test_sve_reduce_in_order_fadd_double
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.double, !cir.vector<[2] x !cir.double>) -> !cir.double
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<[2] x !cir.double>, !cir.double) -> !cir.double
// CIR: cir.return
// LLVM-LABEL: @test_sve_reduce_in_order_fadd_double
// LLVM: call double @llvm.vector.reduce.fadd.nxv2f64(double %{{.*}}, <vscale x 2 x double>
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic.c b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic.c
index 57408af5d80d461..85bda3f284026d4 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-arithmetic.c
@@ -9,10 +9,11 @@ typedef int v4si __attribute__((vector_size(16)));
typedef unsigned int v4su __attribute__((vector_size(16)));
typedef float v4sf __attribute__((vector_size(16)));
typedef double v2df __attribute__((vector_size(16)));
+typedef _Bool v4b __attribute__((ext_vector_type(4)));
int test_reduce_add(v4si x) {
// CIR-LABEL: @test_reduce_add
- // CIR: cir.call_llvm_intrinsic "vector.reduce.add"
+ // CIR: cir.vec.reduce(add,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_add
// LLVM: call i32 @llvm.vector.reduce.add.v4i32(<4 x i32>
@@ -22,7 +23,7 @@ int test_reduce_add(v4si x) {
unsigned test_reduce_add_unsigned(v4su x) {
// CIR-LABEL: @test_reduce_add_unsigned
- // CIR: cir.call_llvm_intrinsic "vector.reduce.add"
+ // CIR: cir.vec.reduce(add,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_add_unsigned
// LLVM: call i32 @llvm.vector.reduce.add.v4i32(<4 x i32>
@@ -30,9 +31,20 @@ unsigned test_reduce_add_unsigned(v4su x) {
return __builtin_reduce_add(x);
}
+_Bool test_reduce_add_bool(void) {
+ // CIR-LABEL: @test_reduce_add_bool
+ // CIR: cir.vec.reduce(add, {{.*}}) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ // CIR: cir.return
+ // LLVM-LABEL: @test_reduce_add_bool
+ // LLVM: call i1 @llvm.vector.reduce.add.v4i1(<4 x i1>
+ // LLVM: ret i1
+ v4b x = {1, 0, 1, 0};
+ return __builtin_reduce_add(x);
+}
+
int test_reduce_mul(v4si x) {
// CIR-LABEL: @test_reduce_mul
- // CIR: cir.call_llvm_intrinsic "vector.reduce.mul"
+ // CIR: cir.vec.reduce(mul,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_mul
// LLVM: call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32>
@@ -42,7 +54,7 @@ int test_reduce_mul(v4si x) {
unsigned test_reduce_mul_unsigned(v4su x) {
// CIR-LABEL: @test_reduce_mul_unsigned
- // CIR: cir.call_llvm_intrinsic "vector.reduce.mul"
+ // CIR: cir.vec.reduce(mul,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_mul_unsigned
// LLVM: call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32>
@@ -52,7 +64,7 @@ unsigned test_reduce_mul_unsigned(v4su x) {
int test_reduce_max(v4si x) {
// CIR-LABEL: @test_reduce_max
- // CIR: cir.call_llvm_intrinsic "vector.reduce.smax"
+ // CIR: cir.vec.reduce(smax,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_max
// LLVM: call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32>
@@ -62,7 +74,7 @@ int test_reduce_max(v4si x) {
unsigned test_reduce_max_unsigned(v4su x) {
// CIR-LABEL: @test_reduce_max_unsigned
- // CIR: cir.call_llvm_intrinsic "vector.reduce.umax"
+ // CIR: cir.vec.reduce(umax,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_max_unsigned
// LLVM: call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32>
@@ -70,9 +82,20 @@ unsigned test_reduce_max_unsigned(v4su x) {
return __builtin_reduce_max(x);
}
+_Bool test_reduce_max_bool(void) {
+ // CIR-LABEL: @test_reduce_max_bool
+ // CIR: cir.vec.reduce(umax, {{.*}}) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ // CIR: cir.return
+ // LLVM-LABEL: @test_reduce_max_bool
+ // LLVM: call i1 @llvm.vector.reduce.umax.v4i1(<4 x i1>
+ // LLVM: ret i1
+ v4b x = {1, 0, 1, 0};
+ return __builtin_reduce_max(x);
+}
+
float test_reduce_max_float(v4sf x) {
// CIR-LABEL: @test_reduce_max_float
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmax"
+ // CIR: cir.vec.reduce(fmax,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_max_float
// LLVM: call float @llvm.vector.reduce.fmax.v4f32(<4 x float>
@@ -82,7 +105,7 @@ float test_reduce_max_float(v4sf x) {
int test_reduce_min(v4si x) {
// CIR-LABEL: @test_reduce_min
- // CIR: cir.call_llvm_intrinsic "vector.reduce.smin"
+ // CIR: cir.vec.reduce(smin,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_min
// LLVM: call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32>
@@ -92,7 +115,7 @@ int test_reduce_min(v4si x) {
unsigned test_reduce_min_unsigned(v4su x) {
// CIR-LABEL: @test_reduce_min_unsigned
- // CIR: cir.call_llvm_intrinsic "vector.reduce.umin"
+ // CIR: cir.vec.reduce(umin,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_min_unsigned
// LLVM: call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32>
@@ -102,7 +125,7 @@ unsigned test_reduce_min_unsigned(v4su x) {
float test_reduce_min_float(v4sf x) {
// CIR-LABEL: @test_reduce_min_float
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fmin"
+ // CIR: cir.vec.reduce(fmin,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_min_float
// LLVM: call float @llvm.vector.reduce.fmin.v4f32(<4 x float>
@@ -112,7 +135,7 @@ float test_reduce_min_float(v4sf 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<reassoc>
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [reassoc]>
// CIR: cir.return
// LLVM-LABEL: @test_reduce_assoc_fadd
// LLVM: call reassoc float @llvm.vector.reduce.fadd.v4f32(float %{{.*}}, <4 x float>
@@ -123,7 +146,7 @@ float test_reduce_assoc_fadd(v4sf x, float 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<reassoc>
+ // CIR: cir.vec.reduce(fadd, {{.*}}, %[[START]]) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [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>
@@ -134,7 +157,7 @@ float test_reduce_assoc_fadd_default_start(v4sf 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<reassoc>
+ // CIR: cir.vec.reduce(fadd, {{.*}}, %[[START]]) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [reassoc]>
// CIR: cir.return
// LLVM-LABEL: @test_reduce_assoc_fadd_cast_start
// LLVM: %[[START:.*]] = fptrunc double %{{.*}} to float
@@ -145,8 +168,7 @@ float test_reduce_assoc_fadd_cast_start(v4sf x, double 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-NOT: fastmath_flags
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<4 x !cir.float>, !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>
@@ -157,7 +179,7 @@ float test_reduce_in_order_fadd(v4sf x, float start) {
float test_reduce_in_order_fadd_cast_start(v4sf x, double start) {
// CIR-LABEL: @test_reduce_in_order_fadd_cast_start
// CIR: cir.cast floating {{.*}} : !cir.double -> !cir.float
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.float, !cir.vector<4 x !cir.float>) -> !cir.float
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float
// CIR: cir.return
// LLVM-LABEL: @test_reduce_in_order_fadd_cast_start
// LLVM: fptrunc double %{{.*}} to float
@@ -168,7 +190,7 @@ float test_reduce_in_order_fadd_cast_start(v4sf x, double start) {
double test_reduce_in_order_fadd_double(v2df x, double start) {
// CIR-LABEL: @test_reduce_in_order_fadd_double
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.double, !cir.vector<2 x !cir.double>) -> !cir.double
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<2 x !cir.double>, !cir.double) -> !cir.double
// CIR: cir.return
// LLVM-LABEL: @test_reduce_in_order_fadd_double
// LLVM: call double @llvm.vector.reduce.fadd.v2f64(double %{{.*}}, <2 x double>
@@ -179,7 +201,7 @@ double test_reduce_in_order_fadd_double(v2df x, double start) {
double test_reduce_in_order_fadd_ext_start(v2df x, float start) {
// CIR-LABEL: @test_reduce_in_order_fadd_ext_start
// CIR: cir.cast floating {{.*}} : !cir.float -> !cir.double
- // CIR: cir.call_llvm_intrinsic "vector.reduce.fadd" {{.*}} : (!cir.double, !cir.vector<2 x !cir.double>) -> !cir.double
+ // CIR: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<2 x !cir.double>, !cir.double) -> !cir.double
// CIR: cir.return
// LLVM-LABEL: @test_reduce_in_order_fadd_ext_start
// LLVM: fpext float %{{.*}} to double
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-bitwise.c b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-bitwise.c
index 0036c62201ee0b1..a5b4bbb7bce406a 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-bitwise.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-bitwise.c
@@ -7,10 +7,11 @@
typedef int v4si __attribute__((vector_size(16)));
typedef unsigned int v4su __attribute__((vector_size(16)));
+typedef _Bool v4b __attribute__((ext_vector_type(4)));
int test_reduce_or(v4si x) {
// CIR-LABEL: @test_reduce_or
- // CIR: cir.call_llvm_intrinsic "vector.reduce.or"
+ // CIR: cir.vec.reduce(or,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_or
// LLVM: call i32 @llvm.vector.reduce.or.v4i32(<4 x i32>
@@ -20,7 +21,7 @@ int test_reduce_or(v4si x) {
int test_reduce_and(v4si x) {
// CIR-LABEL: @test_reduce_and
- // CIR: cir.call_llvm_intrinsic "vector.reduce.and"
+ // CIR: cir.vec.reduce(and,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_and
// LLVM: call i32 @llvm.vector.reduce.and.v4i32(<4 x i32>
@@ -28,9 +29,20 @@ int test_reduce_and(v4si x) {
return __builtin_reduce_and(x);
}
+_Bool test_reduce_and_bool(void) {
+ // CIR-LABEL: @test_reduce_and_bool
+ // CIR: cir.vec.reduce(and, {{.*}}) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ // CIR: cir.return
+ // LLVM-LABEL: @test_reduce_and_bool
+ // LLVM: call i1 @llvm.vector.reduce.and.v4i1(<4 x i1>
+ // LLVM: ret i1
+ v4b x = {1, 0, 1, 0};
+ return __builtin_reduce_and(x);
+}
+
int test_reduce_xor(v4si x) {
// CIR-LABEL: @test_reduce_xor
- // CIR: cir.call_llvm_intrinsic "vector.reduce.xor"
+ // CIR: cir.vec.reduce(xor,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_xor
// LLVM: call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32>
@@ -40,7 +52,7 @@ int test_reduce_xor(v4si x) {
unsigned test_reduce_or_unsigned(v4su x) {
// CIR-LABEL: @test_reduce_or_unsigned
- // CIR: cir.call_llvm_intrinsic "vector.reduce.or"
+ // CIR: cir.vec.reduce(or,
// CIR: cir.return
// LLVM-LABEL: @test_reduce_or_unsigned
// LLVM: call i32 @llvm.vector.reduce.or.v4i32(<4 x i32>
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-reduce-fast-math.c b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-fast-math.c
new file mode 100644
index 000000000000000..23bed21eb8390ae
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-reduce-fast-math.c
@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir \
+// RUN: -menable-no-nans %s -o - | FileCheck %s --check-prefix=CIR-NNAN
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm \
+// RUN: -menable-no-nans %s -o - | FileCheck %s --check-prefix=LLVM-NNAN
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm \
+// RUN: -menable-no-nans %s -o - | FileCheck %s --check-prefix=LLVM-NNAN
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir \
+// RUN: -ffast-math -ffp-contract=fast %s -o - | FileCheck %s --check-prefix=CIR-FAST
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm \
+// RUN: -ffast-math -ffp-contract=fast %s -o - | FileCheck %s --check-prefix=LLVM-FAST
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm \
+// RUN: -ffast-math -ffp-contract=fast %s -o - | FileCheck %s --check-prefix=LLVM-FAST
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir \
+// RUN: -mreassociate %s -o - | FileCheck %s --check-prefix=CIR-PRAGMA
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm \
+// RUN: -mreassociate %s -o - | FileCheck %s --check-prefix=LLVM-PRAGMA
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm \
+// RUN: -mreassociate %s -o - | FileCheck %s --check-prefix=LLVM-PRAGMA
+
+typedef float v4sf __attribute__((vector_size(16)));
+typedef int v4si __attribute__((vector_size(16)));
+
+float test_assoc(v4sf x, float start) {
+ // CIR-NNAN-LABEL: @test_assoc
+ // CIR-NNAN: cir.vec.reduce(fadd, {{.*}}) {{.*}} <fastmath_flags = [nnan, reassoc]>
+ // CIR-FAST-LABEL: @test_assoc
+ // CIR-FAST: cir.vec.reduce(fadd, {{.*}}) {{.*}} <fastmath_flags = [fast]>
+ // LLVM-NNAN-LABEL: @test_assoc
+ // LLVM-NNAN: call reassoc nnan float @llvm.vector.reduce.fadd.v4f32(
+ // LLVM-FAST-LABEL: @test_assoc
+ // LLVM-FAST: call fast float @llvm.vector.reduce.fadd.v4f32(
+ return __builtin_reduce_assoc_fadd(x, start);
+}
+
+float test_in_order(v4sf x, float start) {
+ // CIR-NNAN-LABEL: @test_in_order
+ // CIR-NNAN: cir.vec.reduce(fadd, {{.*}}) {{.*}} <fastmath_flags = [nnan]>
+ // CIR-FAST-LABEL: @test_in_order
+ // CIR-FAST: cir.vec.reduce(fadd, {{.*}}) {{.*}} <fastmath_flags = [fast]>
+ // LLVM-NNAN-LABEL: @test_in_order
+ // LLVM-NNAN: call nnan float @llvm.vector.reduce.fadd.v4f32(
+ // LLVM-FAST-LABEL: @test_in_order
+ // LLVM-FAST: call fast float @llvm.vector.reduce.fadd.v4f32(
+ return __builtin_reduce_in_order_fadd(x, start);
+}
+
+float test_max(v4sf x) {
+ // CIR-NNAN-LABEL: @test_max
+ // CIR-NNAN: cir.vec.reduce(fmax, {{.*}}) {{.*}} <fastmath_flags = [nnan]>
+ // CIR-FAST-LABEL: @test_max
+ // CIR-FAST: cir.vec.reduce(fmax, {{.*}}) {{.*}} <fastmath_flags = [fast]>
+ // LLVM-NNAN-LABEL: @test_max
+ // LLVM-NNAN: call nnan float @llvm.vector.reduce.fmax.v4f32(
+ // LLVM-FAST-LABEL: @test_max
+ // LLVM-FAST: call fast float @llvm.vector.reduce.fmax.v4f32(
+ return __builtin_reduce_max(x);
+}
+
+float test_min(v4sf x) {
+ // CIR-NNAN-LABEL: @test_min
+ // CIR-NNAN: cir.vec.reduce(fmin, {{.*}}) {{.*}} <fastmath_flags = [nnan]>
+ // CIR-FAST-LABEL: @test_min
+ // CIR-FAST: cir.vec.reduce(fmin, {{.*}}) {{.*}} <fastmath_flags = [fast]>
+ // LLVM-NNAN-LABEL: @test_min
+ // LLVM-NNAN: call nnan float @llvm.vector.reduce.fmin.v4f32(
+ // LLVM-FAST-LABEL: @test_min
+ // LLVM-FAST: call fast float @llvm.vector.reduce.fmin.v4f32(
+ return __builtin_reduce_min(x);
+}
+
+int test_int_max(v4si x) {
+ // CIR-NNAN-LABEL: @test_int_max
+ // CIR-NNAN: cir.vec.reduce(smax, {{.*}}) : (!cir.vector<4 x !s32i>) -> !s32i{{( loc.*)?$}}
+ // CIR-FAST-LABEL: @test_int_max
+ // CIR-FAST: cir.vec.reduce(smax, {{.*}}) : (!cir.vector<4 x !s32i>) -> !s32i{{( loc.*)?$}}
+ // LLVM-NNAN-LABEL: @test_int_max
+ // LLVM-NNAN: call i32 @llvm.vector.reduce.smax.v4i32(
+ // LLVM-FAST-LABEL: @test_int_max
+ // LLVM-FAST: call i32 @llvm.vector.reduce.smax.v4i32(
+ return __builtin_reduce_max(x);
+}
+
+float test_pragma_reassociate(v4sf x, float start) {
+#pragma clang fp reassociate(on)
+ // CIR-PRAGMA-LABEL: @test_pragma_reassociate
+ // CIR-PRAGMA: cir.vec.reduce(fadd, {{.*}}) {{.*}} <fastmath_flags = [reassoc]>
+ // LLVM-PRAGMA-LABEL: @test_pragma_reassociate
+ // LLVM-PRAGMA: call reassoc float @llvm.vector.reduce.fadd.v4f32(
+ return __builtin_reduce_in_order_fadd(x, start);
+}
+
+float test_pragma_no_reassociate(v4sf x, float start) {
+#pragma clang fp reassociate(off)
+ // CIR-PRAGMA-LABEL: @test_pragma_no_reassociate
+ // CIR-PRAGMA: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float{{( loc.*)?$}}
+ // LLVM-PRAGMA-LABEL: @test_pragma_no_reassociate
+ // LLVM-PRAGMA: call float @llvm.vector.reduce.fadd.v4f32(
+ return __builtin_reduce_in_order_fadd(x, start);
+}
diff --git a/clang/test/CIR/IR/invalid-vector-reduce.cir b/clang/test/CIR/IR/invalid-vector-reduce.cir
new file mode 100644
index 000000000000000..ea13f67092e8dec
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-vector-reduce.cir
@@ -0,0 +1,78 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!f32 = !cir.float
+!v4f32 = !cir.vector<4 x !f32>
+
+module {
+ cir.func @missing_accumulator(%vec: !v4f32) {
+ // expected-error @below {{'cir.vec.reduce' op requires an accumulator for fadd reduction}}
+ %0 = cir.vec.reduce(fadd, %vec) : (!v4f32) -> !f32
+ cir.return
+ }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!v4s32 = !cir.vector<4 x !s32i>
+
+module {
+ cir.func @unexpected_accumulator(%vec: !v4s32, %start: !s32i) {
+ // expected-error @below {{'cir.vec.reduce' op does not accept an accumulator for add reduction}}
+ %0 = cir.vec.reduce(add, %vec, %start) : (!v4s32, !s32i) -> !s32i
+ cir.return
+ }
+}
+
+// -----
+
+!f32 = !cir.float
+!v4f32 = !cir.vector<4 x !f32>
+
+module {
+ cir.func @wrong_vector_type(%vec: !v4f32) {
+ // expected-error @below {{'cir.vec.reduce' op requires an integer or boolean vector for add reduction}}
+ %0 = cir.vec.reduce(add, %vec) : (!v4f32) -> !f32
+ cir.return
+ }
+}
+
+// -----
+
+!u32i = !cir.int<u, 32>
+!v4u32 = !cir.vector<4 x !u32i>
+
+module {
+ cir.func @wrong_signedness(%vec: !v4u32) {
+ // expected-error @below {{'cir.vec.reduce' op requires a signed integer vector for smax reduction}}
+ %0 = cir.vec.reduce(smax, %vec) : (!v4u32) -> !u32i
+ cir.return
+ }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!v4s32 = !cir.vector<4 x !s32i>
+
+module {
+ cir.func @integer_fastmath(%vec: !v4s32) {
+ // expected-error @below {{'cir.vec.reduce' op fast-math flags are only valid for floating-point reductions}}
+ %0 = cir.vec.reduce(add, %vec) : (!v4s32) -> !s32i <fastmath_flags = [reassoc]>
+ cir.return
+ }
+}
+
+// -----
+
+!f32 = !cir.float
+!f64 = !cir.double
+!v4f32 = !cir.vector<4 x !f32>
+
+module {
+ cir.func @wrong_accumulator_type(%vec: !v4f32, %start: !f64) {
+ // expected-error @below {{'cir.vec.reduce' op accumulator type '!cir.double' doesn't match vector element type '!cir.float'}}
+ %0 = cir.vec.reduce(fadd, %vec, %start) : (!v4f32, !f64) -> !f32
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/IR/vector.cir b/clang/test/CIR/IR/vector.cir
index d744d6f07676347..7b96f562485e205 100644
--- a/clang/test/CIR/IR/vector.cir
+++ b/clang/test/CIR/IR/vector.cir
@@ -1,6 +1,7 @@
// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
!s32i = !cir.int<s, 32>
+!u32i = !cir.int<u, 32>
module {
@@ -222,4 +223,46 @@ cir.func @vector_splat_test() {
// CHECK-NEXT: cir.store %[[SHL]], %[[SHL_RES:.*]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
// CHECK-NEXT: cir.return
+cir.func @vector_reduce_test(%svec: !cir.vector<4 x !s32i>,
+ %uvec: !cir.vector<4 x !u32i>,
+ %fvec: !cir.vector<4 x !cir.float>,
+ %bvec: !cir.vector<4 x !cir.bool>,
+ %start: !cir.float) {
+ %0 = cir.vec.reduce(add, %svec) : (!cir.vector<4 x !s32i>) -> !s32i
+ %1 = cir.vec.reduce(mul, %svec) : (!cir.vector<4 x !s32i>) -> !s32i
+ %2 = cir.vec.reduce(and, %svec) : (!cir.vector<4 x !s32i>) -> !s32i
+ %3 = cir.vec.reduce(or, %svec) : (!cir.vector<4 x !s32i>) -> !s32i
+ %4 = cir.vec.reduce(xor, %svec) : (!cir.vector<4 x !s32i>) -> !s32i
+ %5 = cir.vec.reduce(smax, %svec) : (!cir.vector<4 x !s32i>) -> !s32i
+ %6 = cir.vec.reduce(smin, %svec) : (!cir.vector<4 x !s32i>) -> !s32i
+ %7 = cir.vec.reduce(umax, %uvec) : (!cir.vector<4 x !u32i>) -> !u32i
+ %8 = cir.vec.reduce(umin, %uvec) : (!cir.vector<4 x !u32i>) -> !u32i
+ %9 = cir.vec.reduce(fadd, %fvec, %start) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [reassoc]>
+ %10 = cir.vec.reduce(fmul, %fvec, %start) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [reassoc]>
+ %11 = cir.vec.reduce(fmax, %fvec) : (!cir.vector<4 x !cir.float>) -> !cir.float <fastmath_flags = [nnan]>
+ %12 = cir.vec.reduce(fmin, %fvec) : (!cir.vector<4 x !cir.float>) -> !cir.float <fastmath_flags = [nnan]>
+ %13 = cir.vec.reduce(add, %bvec) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ %14 = cir.vec.reduce(umax, %bvec) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ %15 = cir.vec.reduce(and, %bvec) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ cir.return
+}
+
+// CHECK-LABEL: cir.func @vector_reduce_test
+// CHECK: cir.vec.reduce(add,
+// CHECK: cir.vec.reduce(mul,
+// CHECK: cir.vec.reduce(and,
+// CHECK: cir.vec.reduce(or,
+// CHECK: cir.vec.reduce(xor,
+// CHECK: cir.vec.reduce(smax,
+// CHECK: cir.vec.reduce(smin,
+// CHECK: cir.vec.reduce(umax,
+// CHECK: cir.vec.reduce(umin,
+// CHECK: cir.vec.reduce(fadd, {{.*}}) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [reassoc]>
+// CHECK: cir.vec.reduce(fmul, {{.*}}) : (!cir.vector<4 x !cir.float>, !cir.float) -> !cir.float <fastmath_flags = [reassoc]>
+// CHECK: cir.vec.reduce(fmax, {{.*}}) : (!cir.vector<4 x !cir.float>) -> !cir.float <fastmath_flags = [nnan]>
+// CHECK: cir.vec.reduce(fmin, {{.*}}) : (!cir.vector<4 x !cir.float>) -> !cir.float <fastmath_flags = [nnan]>
+// CHECK: cir.vec.reduce(add, {{.*}}) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+// CHECK: cir.vec.reduce(umax, {{.*}}) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+// CHECK: cir.vec.reduce(and, {{.*}}) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+
}
diff --git a/clang/test/CIR/Lowering/vector-reduce.cir b/clang/test/CIR/Lowering/vector-reduce.cir
new file mode 100644
index 000000000000000..e8a67176b1206f6
--- /dev/null
+++ b/clang/test/CIR/Lowering/vector-reduce.cir
@@ -0,0 +1,50 @@
+// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+!u32i = !cir.int<u, 32>
+!f32 = !cir.float
+!v4s32 = !cir.vector<4 x !s32i>
+!v4u32 = !cir.vector<4 x !u32i>
+!v4f32 = !cir.vector<4 x !f32>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ // CHECK-LABEL: llvm.func @vector_reduce
+ // CHECK: "llvm.intr.vector.reduce.add"
+ // CHECK: "llvm.intr.vector.reduce.mul"
+ // CHECK: "llvm.intr.vector.reduce.and"
+ // CHECK: "llvm.intr.vector.reduce.or"
+ // CHECK: "llvm.intr.vector.reduce.xor"
+ // CHECK: "llvm.intr.vector.reduce.smax"
+ // CHECK: "llvm.intr.vector.reduce.smin"
+ // CHECK: "llvm.intr.vector.reduce.umax"
+ // CHECK: "llvm.intr.vector.reduce.umin"
+ // CHECK: llvm.intr.vector.reduce.fadd(%{{.*}}, %{{.*}}) fastmath<reassoc> : (f32, vector<4xf32>) -> f32
+ // CHECK: llvm.intr.vector.reduce.fmul(%{{.*}}, %{{.*}}) fastmath<reassoc> : (f32, vector<4xf32>) -> f32
+ // CHECK: llvm.intr.vector.reduce.fmax(%{{.*}}) fastmath<nnan> : (vector<4xf32>) -> f32
+ // CHECK: llvm.intr.vector.reduce.fmin(%{{.*}}) fastmath<nnan> : (vector<4xf32>) -> f32
+ // CHECK: "llvm.intr.vector.reduce.add"(%{{.*}}) : (vector<4xi1>) -> i1
+ // CHECK: "llvm.intr.vector.reduce.umax"(%{{.*}}) : (vector<4xi1>) -> i1
+ // CHECK: "llvm.intr.vector.reduce.and"(%{{.*}}) : (vector<4xi1>) -> i1
+ // CHECK: llvm.return
+ cir.func @vector_reduce(%svec: !v4s32, %uvec: !v4u32,
+ %fvec: !v4f32,
+ %bvec: !cir.vector<4 x !cir.bool>, %start: !f32) {
+ %0 = cir.vec.reduce(add, %svec) : (!v4s32) -> !s32i
+ %1 = cir.vec.reduce(mul, %svec) : (!v4s32) -> !s32i
+ %2 = cir.vec.reduce(and, %svec) : (!v4s32) -> !s32i
+ %3 = cir.vec.reduce(or, %svec) : (!v4s32) -> !s32i
+ %4 = cir.vec.reduce(xor, %svec) : (!v4s32) -> !s32i
+ %5 = cir.vec.reduce(smax, %svec) : (!v4s32) -> !s32i
+ %6 = cir.vec.reduce(smin, %svec) : (!v4s32) -> !s32i
+ %7 = cir.vec.reduce(umax, %uvec) : (!v4u32) -> !u32i
+ %8 = cir.vec.reduce(umin, %uvec) : (!v4u32) -> !u32i
+ %9 = cir.vec.reduce(fadd, %fvec, %start) : (!v4f32, !f32) -> !f32 <fastmath_flags = [reassoc]>
+ %10 = cir.vec.reduce(fmul, %fvec, %start) : (!v4f32, !f32) -> !f32 <fastmath_flags = [reassoc]>
+ %11 = cir.vec.reduce(fmax, %fvec) : (!v4f32) -> !f32 <fastmath_flags = [nnan]>
+ %12 = cir.vec.reduce(fmin, %fvec) : (!v4f32) -> !f32 <fastmath_flags = [nnan]>
+ %13 = cir.vec.reduce(add, %bvec) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ %14 = cir.vec.reduce(umax, %bvec) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ %15 = cir.vec.reduce(and, %bvec) : (!cir.vector<4 x !cir.bool>) -> !cir.bool
+ cir.return
+ }
+}
More information about the cfe-commits
mailing list