[llvm] [LV] Check for vector-to-scalar casts in legalizer (PR #106244)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 6 01:09:00 PDT 2024


https://github.com/ErikHogeman updated https://github.com/llvm/llvm-project/pull/106244

>From 11451c6fc56e8c09c81540660f8afbefafe2146c Mon Sep 17 00:00:00 2001
From: Erik Hogeman <erik.hogeman at arm.com>
Date: Tue, 27 Aug 2024 18:20:23 +0200
Subject: [PATCH 1/4] [LoopVectorize] Check for vector-to-scalar casts in
 legalizer

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.
---
 .../Vectorize/LoopVectorizationLegality.cpp   |  3 ++
 .../LoopVectorize/vector-to-scalar-cast.ll    | 32 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 66a779da8c25bc..b1366b484587d6 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -943,9 +943,12 @@ bool LoopVectorizationLegality::canVectorizeInstrs() {
         VecCallVariantsFound = true;
 
       // Check that the instruction return type is vectorizable.
+      // We can't vectorize casts from vector type to scalar type.
       // Also, we can't vectorize extractelement instructions.
       if ((!VectorType::isValidElementType(I.getType()) &&
            !I.getType()->isVoidTy()) ||
+          (isa<CastInst>(&I) &&
+           !VectorType::isValidElementType(I.getOperand(0)->getType())) ||
           isa<ExtractElementInst>(I)) {
         reportVectorizationFailure("Found unvectorizable type",
             "instruction return type cannot be vectorized",
diff --git a/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll b/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
new file mode 100644
index 00000000000000..1a34c815f5a18d
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
@@ -0,0 +1,32 @@
+; RUN: opt --force-widen-divrem-via-safe-divisor=false -passes=loop-vectorize -S --debug-only=loop-vectorize < %s 2>&1 | FileCheck %s
+
+; CHECK: LV: Not vectorizing: Found unvectorizable type   %s2 = bitcast <2 x i16> %vec1 to i32
+; CHECK-NOT: Assertion
+
+; Function Attrs: willreturn
+define void @__start() #0 {
+entry:
+  %vec0 = insertelement <2 x i16> undef, i16 0, i64 0
+  %vec1 = insertelement <2 x i16> %vec0, i16 0, i64 1
+  br label %bb0
+
+bb0:
+  %s0 = phi i32 [ %s1, %bb1 ], [ 1, %entry ]
+  br i1 0, label %bb2, label %bb1
+
+bb1:
+  %s1 = add nuw nsw i32 %s0, 1
+  %exitcond = icmp ne i32 %s1, 11
+  br i1 %exitcond, label %bb0, label %bb3
+
+bb2:
+  %s2 = bitcast <2 x i16> %vec1 to i32
+  %s3 = srem i32 0, %s2
+  br label %bb1
+
+bb3:
+  ret void
+}
+
+attributes #0 = { willreturn }
+

>From 121121fd31abfa8978aaa3b2cb6781f85478584b Mon Sep 17 00:00:00 2001
From: Erik Hogeman <erik.hogeman at arm.com>
Date: Wed, 28 Aug 2024 14:27:09 +0200
Subject: [PATCH 2/4] Fix review comments

---
 .../Vectorize/LoopVectorizationLegality.cpp   |  2 +-
 .../LoopVectorize/vector-to-scalar-cast.ll    | 57 +++++++++++--------
 2 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index b1366b484587d6..3cf65389e952a1 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -947,7 +947,7 @@ bool LoopVectorizationLegality::canVectorizeInstrs() {
       // Also, we can't vectorize extractelement instructions.
       if ((!VectorType::isValidElementType(I.getType()) &&
            !I.getType()->isVoidTy()) ||
-          (isa<CastInst>(&I) &&
+          (isa<CastInst>(I) &&
            !VectorType::isValidElementType(I.getOperand(0)->getType())) ||
           isa<ExtractElementInst>(I)) {
         reportVectorizationFailure("Found unvectorizable type",
diff --git a/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll b/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
index 1a34c815f5a18d..d201b598fc39ba 100644
--- a/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
+++ b/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
@@ -1,32 +1,41 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt --force-widen-divrem-via-safe-divisor=false -passes=loop-vectorize -S --debug-only=loop-vectorize < %s 2>&1 | FileCheck %s
 
-; CHECK: LV: Not vectorizing: Found unvectorizable type   %s2 = bitcast <2 x i16> %vec1 to i32
-; CHECK-NOT: Assertion
-
-; Function Attrs: willreturn
-define void @__start() #0 {
+define void @vector_to_scalar_cast(ptr %out) {
+; CHECK-LABEL: define void @vector_to_scalar_cast(
+; CHECK-SAME: ptr [[OUT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[VEC0:%.*]] = insertelement <2 x i16> undef, i16 0, i64 0
+; CHECK-NEXT:    [[VEC1:%.*]] = insertelement <2 x i16> [[VEC0]], i16 0, i64 1
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[ADD:%.*]], %[[LOOP]] ], [ 1, %[[ENTRY]] ]
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], 11
+; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[IV]], 1
+; CHECK-NEXT:    [[VEC_SCALAR_CAST:%.*]] = bitcast <2 x i16> [[VEC1]] to i32
+; CHECK-NEXT:    [[SREM:%.*]] = srem i32 0, [[VEC_SCALAR_CAST]]
+; CHECK-NEXT:    store i32 [[SREM]], ptr [[OUT]], align 4
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]], !llvm.loop [[LOOP0:![0-9]+]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %vec0 = insertelement <2 x i16> undef, i16 0, i64 0
   %vec1 = insertelement <2 x i16> %vec0, i16 0, i64 1
-  br label %bb0
-
-bb0:
-  %s0 = phi i32 [ %s1, %bb1 ], [ 1, %entry ]
-  br i1 0, label %bb2, label %bb1
-
-bb1:
-  %s1 = add nuw nsw i32 %s0, 1
-  %exitcond = icmp ne i32 %s1, 11
-  br i1 %exitcond, label %bb0, label %bb3
-
-bb2:
-  %s2 = bitcast <2 x i16> %vec1 to i32
-  %s3 = srem i32 0, %s2
-  br label %bb1
-
-bb3:
+  br label %loop
+
+loop:
+  %iv = phi i32 [ %add, %loop ], [ 1, %entry ]
+  %exitcond = icmp ne i32 %iv, 11
+  %add = add nuw nsw i32 %iv, 1
+  %vec.scalar.cast = bitcast <2 x i16> %vec1 to i32
+  %srem = srem i32 0, %vec.scalar.cast
+  store i32 %srem, ptr %out
+  br i1 %exitcond, label %loop, label %exit, !llvm.loop !0
+
+exit:
   ret void
 }
 
-attributes #0 = { willreturn }
-
+!0 = !{!0, !1}
+!1 = !{!"llvm.loop.vectorize.width", i32 4}

>From f2cf45fb89fd7d95514b84215e31b5daabb00ccb Mon Sep 17 00:00:00 2001
From: Erik Hogeman <erik.hogeman at arm.com>
Date: Thu, 29 Aug 2024 12:51:05 +0200
Subject: [PATCH 3/4] Fix review comments - second iteration

---
 .../LoopVectorize/vector-to-scalar-cast.ll    | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll b/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
index d201b598fc39ba..f9fb615015f70c 100644
--- a/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
+++ b/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
@@ -1,5 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt --force-widen-divrem-via-safe-divisor=false -passes=loop-vectorize -S --debug-only=loop-vectorize < %s 2>&1 | FileCheck %s
+; The test was crashing earlier due to a vectorization attempt; vector-to-scalar cast
+; is now forbidden in the legalizer, and the test isn't a vectorization candidate now.
+; RUN: opt -S --force-widen-divrem-via-safe-divisor=false --force-vector-width=4 --passes=loop-vectorize < %s | FileCheck %s
 
 define void @vector_to_scalar_cast(ptr %out) {
 ; CHECK-LABEL: define void @vector_to_scalar_cast(
@@ -9,13 +11,13 @@ define void @vector_to_scalar_cast(ptr %out) {
 ; CHECK-NEXT:    [[VEC1:%.*]] = insertelement <2 x i16> [[VEC0]], i16 0, i64 1
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[ADD:%.*]], %[[LOOP]] ], [ 1, %[[ENTRY]] ]
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 1, %[[ENTRY]] ]
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], 11
-; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[IV]], 1
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
 ; CHECK-NEXT:    [[VEC_SCALAR_CAST:%.*]] = bitcast <2 x i16> [[VEC1]] to i32
 ; CHECK-NEXT:    [[SREM:%.*]] = srem i32 0, [[VEC_SCALAR_CAST]]
 ; CHECK-NEXT:    store i32 [[SREM]], ptr [[OUT]], align 4
-; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]], !llvm.loop [[LOOP0:![0-9]+]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    ret void
 ;
@@ -25,17 +27,14 @@ entry:
   br label %loop
 
 loop:
-  %iv = phi i32 [ %add, %loop ], [ 1, %entry ]
+  %iv = phi i32 [ %iv.next, %loop ], [ 1, %entry ]
   %exitcond = icmp ne i32 %iv, 11
-  %add = add nuw nsw i32 %iv, 1
+  %iv.next = add nuw nsw i32 %iv, 1
   %vec.scalar.cast = bitcast <2 x i16> %vec1 to i32
   %srem = srem i32 0, %vec.scalar.cast
   store i32 %srem, ptr %out
-  br i1 %exitcond, label %loop, label %exit, !llvm.loop !0
+  br i1 %exitcond, label %loop, label %exit
 
 exit:
   ret void
 }
-
-!0 = !{!0, !1}
-!1 = !{!"llvm.loop.vectorize.width", i32 4}

>From 920c122166515cd243ec722e7d0c7a6d7b292825 Mon Sep 17 00:00:00 2001
From: ErikHogeman <erik_h at live.se>
Date: Fri, 6 Sep 2024 10:08:52 +0200
Subject: [PATCH 4/4] Update
 llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll

Co-authored-by: Florian Hahn <flo at fhahn.com>
---
 llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll b/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
index f9fb615015f70c..a6dcd4d1cfc114 100644
--- a/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
+++ b/llvm/test/Transforms/LoopVectorize/vector-to-scalar-cast.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; The test was crashing earlier due to a vectorization attempt; vector-to-scalar cast
 ; is now forbidden in the legalizer, and the test isn't a vectorization candidate now.
-; RUN: opt -S --force-widen-divrem-via-safe-divisor=false --force-vector-width=4 --passes=loop-vectorize < %s | FileCheck %s
+; RUN: opt -S -force-widen-divrem-via-safe-divisor=false -force-vector-width=4 --passes=loop-vectorize < %s | FileCheck %s
 
 define void @vector_to_scalar_cast(ptr %out) {
 ; CHECK-LABEL: define void @vector_to_scalar_cast(



More information about the llvm-commits mailing list