@@ -1515,6 +1515,17 @@ void CodeGen_LLVM::visit(const Reinterpret *op) {
15151515 llvm::Type *llvm_dst_fixed = get_vector_type (llvm_type_of (dst.element_of ()), dst.lanes (), VectorTypeConstraint::Fixed);
15161516 value = builder->CreateBitOrPointerCast (value, llvm_dst_fixed);
15171517 value = fixed_to_scalable_vector_type (value);
1518+ } else if (isa<FixedVectorType>(value->getType ()) && isa<ScalableVectorType>(llvm_dst)) {
1519+ // Cannot bitcast/ptrtoint directly between fixed and scalable vectors.
1520+ // First cast to a fixed vector of the destination element type, then convert to scalable.
1521+ llvm::Type *llvm_dst_fixed = get_vector_type (llvm_dst->getScalarType (), dst.lanes (), VectorTypeConstraint::Fixed);
1522+ value = builder->CreateBitOrPointerCast (value, llvm_dst_fixed);
1523+ value = fixed_to_scalable_vector_type (value);
1524+ } else if (isa<ScalableVectorType>(value->getType ()) && isa<FixedVectorType>(llvm_dst)) {
1525+ // Cannot bitcast/ptrtoint directly between scalable and fixed vectors.
1526+ // First convert to a fixed vector of the source element type, then cast.
1527+ value = scalable_to_fixed_vector_type (value);
1528+ value = builder->CreateBitOrPointerCast (value, llvm_dst);
15181529 } else {
15191530 // Our `Reinterpret` expr directly maps to LLVM IR bitcast/ptrtoint/inttoptr
15201531 // instructions with no additional handling required:
@@ -4314,10 +4325,12 @@ void CodeGen_LLVM::codegen_vector_reduce(const VectorReduce *op, const Expr &ini
43144325 const int input_lanes = val.type ().lanes ();
43154326 const int input_bytes = input_lanes * val.type ().bytes ();
43164327 const int vscale = std::max (effective_vscale, 1 );
4328+ // LLVM added VECREDUCE_MUL/FMUL lowering for SVE in LLVM 22.
4329+ const bool mul_ok = LLVM_VERSION >= 220 || effective_vscale == 0 ;
43174330 const bool llvm_has_intrinsic =
43184331 // Must be one of these ops
43194332 ((op->op == VectorReduce::Add ||
4320- op->op == VectorReduce::Mul ||
4333+ ( op->op == VectorReduce::Mul && mul_ok) ||
43214334 op->op == VectorReduce::Min ||
43224335 op->op == VectorReduce::Max) &&
43234336 (use_llvm_vp_intrinsics ||
@@ -4920,6 +4933,13 @@ Value *CodeGen_LLVM::slice_vector(Value *vec, int start, int size) {
49204933 // otherwise.
49214934 llvm::Type *scalar_type = vec->getType ()->getScalarType ();
49224935
4936+ if (scalar_type->isIntegerTy (1 )) {
4937+ auto *result_type = cast<VectorType>(get_vector_type (scalar_type, size / effective_vscale, VectorTypeConstraint::VScale));
4938+ return handle_bool_as_i8 (vec, result_type, [&](Value *v) {
4939+ return slice_vector (v, start, size);
4940+ });
4941+ }
4942+
49234943 int intermediate_lanes = std::min (size, vec_lanes - start);
49244944 llvm::Type *intermediate_type = get_vector_type (scalar_type, intermediate_lanes, VectorTypeConstraint::Fixed);
49254945
@@ -5190,6 +5210,18 @@ llvm::Value *CodeGen_LLVM::match_vector_type_scalable(llvm::Value *value, llvm::
51905210 return match_vector_type_scalable (value, guide->getType ());
51915211}
51925212
5213+ llvm::Value *CodeGen_LLVM::handle_bool_as_i8 (llvm::Value *arg, llvm::VectorType *result_i1_type,
5214+ const std::function<llvm::Value *(llvm::Value *)> &fn) {
5215+ auto *arg_vty = cast<llvm::VectorType>(arg->getType ());
5216+ bool scalable = isa<llvm::ScalableVectorType>(arg_vty);
5217+ int min_elts = scalable ? cast<llvm::ScalableVectorType>(arg_vty)->getMinNumElements () : cast<llvm::FixedVectorType>(arg_vty)->getNumElements ();
5218+ auto constraint = scalable ? VectorTypeConstraint::VScale : VectorTypeConstraint::Fixed;
5219+ llvm::Type *arg_i8 = get_vector_type (i8_t , min_elts, constraint);
5220+ llvm::Value *widened = builder->CreateZExt (arg, arg_i8);
5221+ llvm::Value *result = fn (widened);
5222+ return builder->CreateTrunc (result, result_i1_type);
5223+ }
5224+
51935225llvm::Value *CodeGen_LLVM::convert_fixed_or_scalable_vector_type (llvm::Value *arg,
51945226 llvm::Type *desired_type) {
51955227 llvm::Type *arg_type = arg->getType ();
@@ -5199,6 +5231,18 @@ llvm::Value *CodeGen_LLVM::convert_fixed_or_scalable_vector_type(llvm::Value *ar
51995231 }
52005232
52015233 internal_assert (arg_type->getScalarType () == desired_type->getScalarType ());
5234+
5235+ if (arg_type->isVectorTy () && desired_type->isVectorTy () &&
5236+ arg_type->getScalarType ()->isIntegerTy (1 )) {
5237+ bool dst_scalable = isa<llvm::ScalableVectorType>(desired_type);
5238+ int dst_elts = get_vector_num_elements (desired_type);
5239+ llvm::Type *dst_i8 = get_vector_type (i8_t , dst_scalable ? dst_elts / effective_vscale : dst_elts,
5240+ dst_scalable ? VectorTypeConstraint::VScale : VectorTypeConstraint::Fixed);
5241+ return handle_bool_as_i8 (arg, cast<VectorType>(desired_type), [&](Value *v) {
5242+ return convert_fixed_or_scalable_vector_type (v, dst_i8);
5243+ });
5244+ }
5245+
52025246 if (!arg_type->isVectorTy ()) {
52035247 arg = create_broadcast (arg, 1 );
52045248 arg_type = arg->getType ();
@@ -5280,6 +5324,12 @@ llvm::Value *CodeGen_LLVM::fixed_to_scalable_vector_type(llvm::Value *fixed_arg)
52805324 internal_assert (fixed_type->getElementType () == scalable_type->getElementType ());
52815325 internal_assert (lanes == (scalable_type->getMinNumElements () * effective_vscale));
52825326
5327+ if (fixed_type->getElementType ()->isIntegerTy (1 )) {
5328+ return handle_bool_as_i8 (fixed_arg, scalable_type, [&](Value *v) {
5329+ return fixed_to_scalable_vector_type (v);
5330+ });
5331+ }
5332+
52835333 // E.g. <vscale x 2 x i64> llvm.vector.insert.nxv2i64.v4i64(<vscale x 2 x i64>, <4 x i64>, i64)
52845334 const char *type_designator;
52855335 if (fixed_type->getElementType ()->isIntegerTy ()) {
@@ -5297,7 +5347,7 @@ llvm::Value *CodeGen_LLVM::fixed_to_scalable_vector_type(llvm::Value *fixed_arg)
52975347
52985348 std::vector<llvm::Value *> args;
52995349 args.push_back (result_vec);
5300- args.push_back (value );
5350+ args.push_back (fixed_arg );
53015351 args.push_back (ConstantInt::get (i64_t , 0 ));
53025352
53035353 return simple_call_intrin (intrin, args, scalable_type);
@@ -5316,6 +5366,12 @@ llvm::Value *CodeGen_LLVM::scalable_to_fixed_vector_type(llvm::Value *scalable_a
53165366 internal_assert (fixed_type->getElementType () == scalable_type->getElementType ());
53175367 internal_assert (fixed_type->getNumElements () == (scalable_type->getMinNumElements () * effective_vscale));
53185368
5369+ if (scalable_type->getElementType ()->isIntegerTy (1 )) {
5370+ return handle_bool_as_i8 (scalable_arg, fixed_type, [&](Value *v) {
5371+ return scalable_to_fixed_vector_type (v);
5372+ });
5373+ }
5374+
53195375 // E.g. <64 x i8> @llvm.vector.extract.v64i8.nxv8i8(<vscale x 8 x i8> %vresult, i64 0)
53205376 const char *type_designator;
53215377 if (scalable_type->getElementType ()->isIntegerTy ()) {
0 commit comments