[llvm] [LoopVectorize] Support vectorization of frexp intrinsic (PR #172957)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 23 07:29:27 PST 2025
https://github.com/Michael-Chen-NJU updated https://github.com/llvm/llvm-project/pull/172957
>From e162679d2faab197cb7d0c5e65de811be9732401 Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Fri, 19 Dec 2025 14:17:46 +0800
Subject: [PATCH 1/5] Initial support for frexp vectorization.
---
llvm/lib/Analysis/VectorUtils.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index a3e9b039f9225..2fb502bb26f40 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -81,6 +81,7 @@ bool llvm::isTriviallyVectorizable(Intrinsic::ID ID) {
case Intrinsic::exp:
case Intrinsic::exp10:
case Intrinsic::exp2:
+ case Intrinsic::frexp:
case Intrinsic::ldexp:
case Intrinsic::log:
case Intrinsic::log10:
@@ -129,10 +130,7 @@ bool llvm::isTriviallyScalarizable(Intrinsic::ID ID,
if (TTI && Intrinsic::isTargetIntrinsic(ID))
return TTI->isTargetIntrinsicTriviallyScalarizable(ID);
- // TODO: Move frexp to isTriviallyVectorizable.
- // https://github.com/llvm/llvm-project/issues/112408
switch (ID) {
- case Intrinsic::frexp:
case Intrinsic::uadd_with_overflow:
case Intrinsic::sadd_with_overflow:
case Intrinsic::ssub_with_overflow:
>From 1ff8215a479de946d98c209527891141da4bafcf Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Mon, 22 Dec 2025 23:48:15 +0800
Subject: [PATCH 2/5] Add test
---
.../multiple-result-intrinsics.ll | 69 ++++++++++++++++++-
1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/llvm/test/Transforms/LoopVectorize/multiple-result-intrinsics.ll b/llvm/test/Transforms/LoopVectorize/multiple-result-intrinsics.ll
index b19f9c5a3b60d..beeda43f4fe99 100644
--- a/llvm/test/Transforms/LoopVectorize/multiple-result-intrinsics.ll
+++ b/llvm/test/Transforms/LoopVectorize/multiple-result-intrinsics.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --filter "(:|sincos|modf|extract|store)" --version 5
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --filter "(:|sincos|frexp|modf|extract|store)" --version 5
; RUN: opt -passes=loop-vectorize -force-vector-interleave=1 -force-vector-width=2 < %s -S -o - | FileCheck %s
define void @sincos_f32(ptr noalias %in, ptr noalias writeonly %out_a, ptr noalias writeonly %out_b) {
@@ -277,3 +277,70 @@ exit:
ret void
}
+define void @frexp_f32(ptr noalias %in, ptr noalias writeonly %out_mantissa, ptr noalias writeonly %out_exponent) {
+; CHECK-LABEL: define void @frexp_f32(
+; CHECK-SAME: ptr noalias [[IN:%.*]], ptr noalias writeonly [[OUT_MANTISSA:%.*]], ptr noalias writeonly [[OUT_EXPONENT:%.*]]) {
+; CHECK: [[ENTRY:.*:]]
+; CHECK: [[FOR_BODY:.*:]]
+; CHECK: [[CALL:%.*]] = tail call { float, i32 } @llvm.frexp.f32.i32(float [[IN_VAL:%.*]])
+; CHECK: [[MANTISSA:%.*]] = extractvalue { float, i32 } [[CALL]], 0
+; CHECK: [[EXPONENT:%.*]] = extractvalue { float, i32 } [[CALL]], 1
+; CHECK: store float [[MANTISSA]], ptr [[ARRAYIDX2:%.*]], align 4
+; CHECK: store i32 [[EXPONENT]], ptr [[ARRAYIDX4:%.*]], align 4
+; CHECK: [[EXIT:.*:]]
+;
+entry:
+ br label %for.body
+
+for.body:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
+ %arrayidx = getelementptr inbounds float, ptr %in, i64 %iv
+ %in_val = load float, ptr %arrayidx, align 4
+ %call = tail call { float, i32 } @llvm.frexp.f32.i32(float %in_val)
+ %mantissa = extractvalue { float, i32 } %call, 0
+ %exponent = extractvalue { float, i32 } %call, 1
+ %arrayidx2 = getelementptr inbounds float, ptr %out_mantissa, i64 %iv
+ store float %mantissa, ptr %arrayidx2, align 4
+ %arrayidx4 = getelementptr inbounds i32, ptr %out_exponent, i64 %iv
+ store i32 %exponent, ptr %arrayidx4, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 1024
+ br i1 %exitcond.not, label %exit, label %for.body
+
+exit:
+ ret void
+}
+
+define void @frexp_f64(ptr noalias %in, ptr noalias writeonly %out_mantissa, ptr noalias writeonly %out_exponent) {
+; CHECK-LABEL: define void @frexp_f64(
+; CHECK-SAME: ptr noalias [[IN:%.*]], ptr noalias writeonly [[OUT_MANTISSA:%.*]], ptr noalias writeonly [[OUT_EXPONENT:%.*]]) {
+; CHECK: [[ENTRY:.*:]]
+; CHECK: [[FOR_BODY:.*:]]
+; CHECK: [[CALL:%.*]] = tail call { double, i32 } @llvm.frexp.f64.i32(double [[IN_VAL:%.*]])
+; CHECK: [[MANTISSA:%.*]] = extractvalue { double, i32 } [[CALL]], 0
+; CHECK: [[EXPONENT:%.*]] = extractvalue { double, i32 } [[CALL]], 1
+; CHECK: store double [[MANTISSA]], ptr [[ARRAYIDX2:%.*]], align 8
+; CHECK: store i32 [[EXPONENT]], ptr [[ARRAYIDX4:%.*]], align 4
+; CHECK: [[EXIT:.*:]]
+;
+entry:
+ br label %for.body
+
+for.body:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
+ %arrayidx = getelementptr inbounds double, ptr %in, i64 %iv
+ %in_val = load double, ptr %arrayidx, align 8
+ %call = tail call { double, i32 } @llvm.frexp.f64.i32(double %in_val)
+ %mantissa = extractvalue { double, i32 } %call, 0
+ %exponent = extractvalue { double, i32 } %call, 1
+ %arrayidx2 = getelementptr inbounds double, ptr %out_mantissa, i64 %iv
+ store double %mantissa, ptr %arrayidx2, align 8
+ %arrayidx4 = getelementptr inbounds i32, ptr %out_exponent, i64 %iv
+ store i32 %exponent, ptr %arrayidx4, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 1024
+ br i1 %exitcond.not, label %exit, label %for.body
+
+exit:
+ ret void
+}
>From db36d2bc8f6229746a2f99dbd94debf18daf8fe2 Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Tue, 23 Dec 2025 20:33:07 +0800
Subject: [PATCH 3/5] [LoopVectorize] Support widening of intrinsics with
mixed-type struct returns
---
.../Vectorize/LoopVectorizationLegality.cpp | 10 +-----
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 14 ++++++--
.../multiple-result-intrinsics.ll | 24 +++++++------
.../Transforms/LoopVectorize/struct-return.ll | 36 ++++++++++---------
4 files changed, 47 insertions(+), 37 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 5238a5d7d7c24..8a0f39d7d530b 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -802,15 +802,7 @@ static bool isTLIScalarize(const TargetLibraryInfo &TLI, const CallInst &CI) {
/// Returns true if the call return type `Ty` can be widened by the loop
/// vectorizer.
-static bool canWidenCallReturnType(Type *Ty) {
- auto *StructTy = dyn_cast<StructType>(Ty);
- // TODO: Remove the homogeneous types restriction. This is just an initial
- // simplification. When we want to support things like the overflow intrinsics
- // we will have to lift this restriction.
- if (StructTy && !StructTy->containsHomogeneousTypes())
- return false;
- return canVectorizeTy(StructTy);
-}
+static bool canWidenCallReturnType(Type *Ty) { return canVectorizeTy(Ty); }
bool LoopVectorizationLegality::canVectorizeInstrs() {
bool DoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 849448a015fe5..4e043dfd5564f 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -1695,8 +1695,18 @@ void VPWidenIntrinsicRecipe::execute(VPTransformState &State) {
SmallVector<Type *, 2> TysForDecl;
// Add return type if intrinsic is overloaded on it.
- if (isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, -1, State.TTI))
- TysForDecl.push_back(VectorType::get(getResultType(), State.VF));
+ if (isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, -1,
+ State.TTI)) {
+ // If the return type is a struct, we need to unpack its elements and
+ // vectorize them individually for the overloaded declaration.
+ Type *RetTy = getResultType();
+ if (auto *ST = dyn_cast<StructType>(RetTy)) {
+ for (Type *ElemTy : ST->elements())
+ TysForDecl.push_back(VectorType::get(ElemTy, State.VF));
+ } else {
+ TysForDecl.push_back(VectorType::get(RetTy, State.VF));
+ }
+ }
SmallVector<Value *, 4> Args;
for (const auto &I : enumerate(operands())) {
// Some intrinsics have a scalar argument - don't replace it with a
diff --git a/llvm/test/Transforms/LoopVectorize/multiple-result-intrinsics.ll b/llvm/test/Transforms/LoopVectorize/multiple-result-intrinsics.ll
index beeda43f4fe99..c6fcbed983d3c 100644
--- a/llvm/test/Transforms/LoopVectorize/multiple-result-intrinsics.ll
+++ b/llvm/test/Transforms/LoopVectorize/multiple-result-intrinsics.ll
@@ -282,12 +282,14 @@ define void @frexp_f32(ptr noalias %in, ptr noalias writeonly %out_mantissa, ptr
; CHECK-SAME: ptr noalias [[IN:%.*]], ptr noalias writeonly [[OUT_MANTISSA:%.*]], ptr noalias writeonly [[OUT_EXPONENT:%.*]]) {
; CHECK: [[ENTRY:.*:]]
; CHECK: [[FOR_BODY:.*:]]
-; CHECK: [[CALL:%.*]] = tail call { float, i32 } @llvm.frexp.f32.i32(float [[IN_VAL:%.*]])
-; CHECK: [[MANTISSA:%.*]] = extractvalue { float, i32 } [[CALL]], 0
-; CHECK: [[EXPONENT:%.*]] = extractvalue { float, i32 } [[CALL]], 1
-; CHECK: store float [[MANTISSA]], ptr [[ARRAYIDX2:%.*]], align 4
-; CHECK: store i32 [[EXPONENT]], ptr [[ARRAYIDX4:%.*]], align 4
; CHECK: [[EXIT:.*:]]
+; CHECK: [[TMP1:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> [[WIDE_LOAD:%.*]])
+; CHECK: [[TMP2:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[TMP1]], 0
+; CHECK: [[TMP3:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[TMP1]], 1
+; CHECK: store <2 x float> [[TMP2]], ptr [[TMP4:%.*]], align 4
+; CHECK: store <2 x i32> [[TMP3]], ptr [[TMP5:%.*]], align 4
+; CHECK: [[MIDDLE_BLOCK:.*:]]
+; CHECK: [[EXIT1:.*:]]
;
entry:
br label %for.body
@@ -316,12 +318,14 @@ define void @frexp_f64(ptr noalias %in, ptr noalias writeonly %out_mantissa, ptr
; CHECK-SAME: ptr noalias [[IN:%.*]], ptr noalias writeonly [[OUT_MANTISSA:%.*]], ptr noalias writeonly [[OUT_EXPONENT:%.*]]) {
; CHECK: [[ENTRY:.*:]]
; CHECK: [[FOR_BODY:.*:]]
-; CHECK: [[CALL:%.*]] = tail call { double, i32 } @llvm.frexp.f64.i32(double [[IN_VAL:%.*]])
-; CHECK: [[MANTISSA:%.*]] = extractvalue { double, i32 } [[CALL]], 0
-; CHECK: [[EXPONENT:%.*]] = extractvalue { double, i32 } [[CALL]], 1
-; CHECK: store double [[MANTISSA]], ptr [[ARRAYIDX2:%.*]], align 8
-; CHECK: store i32 [[EXPONENT]], ptr [[ARRAYIDX4:%.*]], align 4
; CHECK: [[EXIT:.*:]]
+; CHECK: [[TMP1:%.*]] = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> [[WIDE_LOAD:%.*]])
+; CHECK: [[TMP2:%.*]] = extractvalue { <2 x double>, <2 x i32> } [[TMP1]], 0
+; CHECK: [[TMP3:%.*]] = extractvalue { <2 x double>, <2 x i32> } [[TMP1]], 1
+; CHECK: store <2 x double> [[TMP2]], ptr [[TMP4:%.*]], align 8
+; CHECK: store <2 x i32> [[TMP3]], ptr [[TMP5:%.*]], align 4
+; CHECK: [[MIDDLE_BLOCK:.*:]]
+; CHECK: [[EXIT1:.*:]]
;
entry:
br label %for.body
diff --git a/llvm/test/Transforms/LoopVectorize/struct-return.ll b/llvm/test/Transforms/LoopVectorize/struct-return.ll
index 70c6c7e900c51..16f3c07ebe680 100644
--- a/llvm/test/Transforms/LoopVectorize/struct-return.ll
+++ b/llvm/test/Transforms/LoopVectorize/struct-return.ll
@@ -378,27 +378,31 @@ exit:
ret void
}
-; Negative test. Widening structs with mixed element types is not supported.
-; CHECK-REMARKS-COUNT: remark: {{.*}} loop not vectorized: instruction return type cannot be vectorized
-define void @negative_mixed_element_type_struct_return(ptr noalias %in, ptr noalias writeonly %out_a, ptr noalias writeonly %out_b) {
-; CHECK-LABEL: define void @negative_mixed_element_type_struct_return(
+; Widening structs with mixed element types is now supported.
+; CHECK-REMARKS: remark: {{.*}} vectorized loop (vectorization width: 2, interleaved count: 1)
+define void @mixed_element_type_struct_return(ptr noalias %in, ptr noalias writeonly %out_a, ptr noalias writeonly %out_b) {
+; CHECK-LABEL: define void @mixed_element_type_struct_return(
; CHECK-SAME: ptr noalias [[IN:%.*]], ptr noalias writeonly [[OUT_A:%.*]], ptr noalias writeonly [[OUT_B:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: br label %[[FOR_BODY:.*]]
-; CHECK: [[FOR_BODY]]:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[FOR_BODY]] ]
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[VECTOR_PH:.*]]
+; CHECK: [[VECTOR_PH]]:
+; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
+; CHECK: [[VECTOR_BODY]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[IV_NEXT:%.*]], %[[VECTOR_BODY]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[IN]], i64 [[IV]]
-; CHECK-NEXT: [[IN_VAL:%.*]] = load float, ptr [[ARRAYIDX]], align 4
-; CHECK-NEXT: [[CALL:%.*]] = tail call { float, i32 } @baz(float [[IN_VAL]]) #[[ATTR3:[0-9]+]]
-; CHECK-NEXT: [[EXTRACT_A:%.*]] = extractvalue { float, i32 } [[CALL]], 0
-; CHECK-NEXT: [[EXTRACT_B:%.*]] = extractvalue { float, i32 } [[CALL]], 1
+; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x float>, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT: [[TMP1:%.*]] = call { <2 x float>, <2 x i32> } @fixed_vec_baz(<2 x float> [[WIDE_LOAD]])
+; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[TMP1]], 0
+; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[TMP1]], 1
; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds float, ptr [[OUT_A]], i64 [[IV]]
-; CHECK-NEXT: store float [[EXTRACT_A]], ptr [[ARRAYIDX2]], align 4
+; CHECK-NEXT: store <2 x float> [[TMP2]], ptr [[ARRAYIDX2]], align 4
; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, ptr [[OUT_B]], i64 [[IV]]
-; CHECK-NEXT: store i32 [[EXTRACT_B]], ptr [[ARRAYIDX4]], align 4
-; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT: store <2 x i32> [[TMP3]], ptr [[ARRAYIDX4]], align 4
+; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 2
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024
-; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[FOR_BODY]]
+; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]
+; CHECK: [[MIDDLE_BLOCK]]:
+; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
>From 56b4c8179cc163965527ab42d4dafb0e88135c27 Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Tue, 23 Dec 2025 21:36:08 +0800
Subject: [PATCH 4/5] [LoopVectorize] Support widening intrinsics with struct
return types
---
llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 4e043dfd5564f..f10ac003a25a1 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -1697,15 +1697,8 @@ void VPWidenIntrinsicRecipe::execute(VPTransformState &State) {
// Add return type if intrinsic is overloaded on it.
if (isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, -1,
State.TTI)) {
- // If the return type is a struct, we need to unpack its elements and
- // vectorize them individually for the overloaded declaration.
- Type *RetTy = getResultType();
- if (auto *ST = dyn_cast<StructType>(RetTy)) {
- for (Type *ElemTy : ST->elements())
- TysForDecl.push_back(VectorType::get(ElemTy, State.VF));
- } else {
- TysForDecl.push_back(VectorType::get(RetTy, State.VF));
- }
+ Type *RetTy = toVectorizedTy(getResultType(), State.VF);
+ append_range(TysForDecl, getContainedTypes(RetTy));
}
SmallVector<Value *, 4> Args;
for (const auto &I : enumerate(operands())) {
>From a19df640758e55602408766a6b3aad195fdcdee0 Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Tue, 23 Dec 2025 23:29:01 +0800
Subject: [PATCH 5/5] fix
---
llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp | 6 +-----
llvm/test/Transforms/LoopVectorize/struct-return.ll | 1 -
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 8a0f39d7d530b..93229ea625a5d 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -800,10 +800,6 @@ static bool isTLIScalarize(const TargetLibraryInfo &TLI, const CallInst &CI) {
return Scalarize;
}
-/// Returns true if the call return type `Ty` can be widened by the loop
-/// vectorizer.
-static bool canWidenCallReturnType(Type *Ty) { return canVectorizeTy(Ty); }
-
bool LoopVectorizationLegality::canVectorizeInstrs() {
bool DoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE);
bool Result = true;
@@ -1018,7 +1014,7 @@ bool LoopVectorizationLegality::canVectorizeInstr(Instruction &I) {
// For now, we only recognize struct values returned from calls where
// all users are extractvalue as vectorizable. All element types of the
// struct must be types that can be widened.
- return isa<CallInst>(Inst) && canWidenCallReturnType(InstTy) &&
+ return isa<CallInst>(Inst) && canVectorizeTy(InstTy) &&
all_of(Inst.users(), IsaPred<ExtractValueInst>);
};
diff --git a/llvm/test/Transforms/LoopVectorize/struct-return.ll b/llvm/test/Transforms/LoopVectorize/struct-return.ll
index 16f3c07ebe680..83c87f1e15e8f 100644
--- a/llvm/test/Transforms/LoopVectorize/struct-return.ll
+++ b/llvm/test/Transforms/LoopVectorize/struct-return.ll
@@ -378,7 +378,6 @@ exit:
ret void
}
-; Widening structs with mixed element types is now supported.
; CHECK-REMARKS: remark: {{.*}} vectorized loop (vectorization width: 2, interleaved count: 1)
define void @mixed_element_type_struct_return(ptr noalias %in, ptr noalias writeonly %out_a, ptr noalias writeonly %out_b) {
; CHECK-LABEL: define void @mixed_element_type_struct_return(
More information about the llvm-commits
mailing list