Skip to content

Commit 78e1e6a

Browse files
authored
[LV] Check for vector-to-scalar casts in legalizer (#106244)
The code makes assumptions later on the operations and their inputs being scalar in the loops that are processed, so we should make sure this is the case in the legalizer.
1 parent 66a0329 commit 78e1e6a

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,9 +943,12 @@ bool LoopVectorizationLegality::canVectorizeInstrs() {
943943
VecCallVariantsFound = true;
944944

945945
// Check that the instruction return type is vectorizable.
946+
// We can't vectorize casts from vector type to scalar type.
946947
// Also, we can't vectorize extractelement instructions.
947948
if ((!VectorType::isValidElementType(I.getType()) &&
948949
!I.getType()->isVoidTy()) ||
950+
(isa<CastInst>(I) &&
951+
!VectorType::isValidElementType(I.getOperand(0)->getType())) ||
949952
isa<ExtractElementInst>(I)) {
950953
reportVectorizationFailure("Found unvectorizable type",
951954
"instruction return type cannot be vectorized",
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; The test was crashing earlier due to a vectorization attempt; vector-to-scalar cast
3+
; is now forbidden in the legalizer, and the test isn't a vectorization candidate now.
4+
; RUN: opt -S -force-widen-divrem-via-safe-divisor=false -force-vector-width=4 --passes=loop-vectorize < %s | FileCheck %s
5+
6+
define void @vector_to_scalar_cast(ptr %out) {
7+
; CHECK-LABEL: define void @vector_to_scalar_cast(
8+
; CHECK-SAME: ptr [[OUT:%.*]]) {
9+
; CHECK-NEXT: [[ENTRY:.*]]:
10+
; CHECK-NEXT: [[VEC0:%.*]] = insertelement <2 x i16> undef, i16 0, i64 0
11+
; CHECK-NEXT: [[VEC1:%.*]] = insertelement <2 x i16> [[VEC0]], i16 0, i64 1
12+
; CHECK-NEXT: br label %[[LOOP:.*]]
13+
; CHECK: [[LOOP]]:
14+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 1, %[[ENTRY]] ]
15+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], 11
16+
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
17+
; CHECK-NEXT: [[VEC_SCALAR_CAST:%.*]] = bitcast <2 x i16> [[VEC1]] to i32
18+
; CHECK-NEXT: [[SREM:%.*]] = srem i32 0, [[VEC_SCALAR_CAST]]
19+
; CHECK-NEXT: store i32 [[SREM]], ptr [[OUT]], align 4
20+
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]]
21+
; CHECK: [[EXIT]]:
22+
; CHECK-NEXT: ret void
23+
;
24+
entry:
25+
%vec0 = insertelement <2 x i16> undef, i16 0, i64 0
26+
%vec1 = insertelement <2 x i16> %vec0, i16 0, i64 1
27+
br label %loop
28+
29+
loop:
30+
%iv = phi i32 [ %iv.next, %loop ], [ 1, %entry ]
31+
%exitcond = icmp ne i32 %iv, 11
32+
%iv.next = add nuw nsw i32 %iv, 1
33+
%vec.scalar.cast = bitcast <2 x i16> %vec1 to i32
34+
%srem = srem i32 0, %vec.scalar.cast
35+
store i32 %srem, ptr %out
36+
br i1 %exitcond, label %loop, label %exit
37+
38+
exit:
39+
ret void
40+
}

0 commit comments

Comments
 (0)