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 <[email protected]>
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
+  }
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to