[llvm] r274306 - LoadStoreVectorizer: Fix crashes on sub-byte types

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 30 17:36:54 PDT 2016


Author: arsenm
Date: Thu Jun 30 19:36:54 2016
New Revision: 274306

URL: http://llvm.org/viewvc/llvm-project?rev=274306&view=rev
Log:
LoadStoreVectorizer: Fix crashes on sub-byte types

Added:
    llvm/trunk/test/Transforms/LoadStoreVectorizer/AMDGPU/weird-type-accesses.ll
Modified:
    llvm/trunk/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp

Modified: llvm/trunk/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp?rev=274306&r1=274305&r2=274306&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp Thu Jun 30 19:36:54 2016
@@ -437,8 +437,14 @@ void Vectorizer::collectInstructions(Bas
       if (!VectorType::isValidElementType(Ty->getScalarType()))
         continue;
 
+      // Skip weird non-byte sizes. They probably aren't worth the effort of
+      // handling correctly.
+      unsigned TySize = DL.getTypeSizeInBits(Ty);
+      if (TySize < 8)
+        continue;
+
       // No point in looking at these if they're too big to vectorize.
-      if (DL.getTypeSizeInBits(Ty) > VecRegSize / 2)
+      if (TySize > VecRegSize / 2)
         continue;
 
       // Make sure all the users of a vector are constant-index extracts.
@@ -464,7 +470,13 @@ void Vectorizer::collectInstructions(Bas
       if (!VectorType::isValidElementType(Ty->getScalarType()))
         continue;
 
-      if (DL.getTypeSizeInBits(Ty) > VecRegSize / 2)
+      // Skip weird non-byte sizes. They probably aren't worth the effort of
+      // handling correctly.
+      unsigned TySize = DL.getTypeSizeInBits(Ty);
+      if (TySize < 8)
+        continue;
+
+      if (TySize > VecRegSize / 2)
         continue;
 
       if (isa<VectorType>(Ty) &&

Added: llvm/trunk/test/Transforms/LoadStoreVectorizer/AMDGPU/weird-type-accesses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoadStoreVectorizer/AMDGPU/weird-type-accesses.ll?rev=274306&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LoadStoreVectorizer/AMDGPU/weird-type-accesses.ll (added)
+++ llvm/trunk/test/Transforms/LoadStoreVectorizer/AMDGPU/weird-type-accesses.ll Thu Jun 30 19:36:54 2016
@@ -0,0 +1,199 @@
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -load-store-vectorizer -S -o - %s | FileCheck %s
+
+; Checks that we don't merge loads/stores of types smaller than one
+; byte, or vectors with elements smaller than one byte.
+
+%struct.foo = type { i32, i8 }
+
+declare void @use_i1(i1)
+declare void @use_i2(i2)
+declare void @use_i8(i8)
+declare void @use_foo(%struct.foo)
+declare void @use_v2i2(<2 x i2>)
+declare void @use_v4i2(<4 x i2>)
+declare void @use_v2i9(<2 x i9>)
+
+; CHECK-LABEL: @merge_store_2_constants_i1(
+; CHECK: store i1
+; CHECK: store i1
+define void @merge_store_2_constants_i1(i1 addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr i1, i1 addrspace(1)* %out, i32 1
+  store i1 true, i1 addrspace(1)* %out.gep.1
+  store i1 false, i1 addrspace(1)* %out
+  ret void
+}
+
+; CHECK-LABEL: @merge_store_2_constants_i2(
+; CHECK: store i2 1
+; CHECK: store i2 -1
+define void @merge_store_2_constants_i2(i2 addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr i2, i2 addrspace(1)* %out, i32 1
+  store i2 1, i2 addrspace(1)* %out.gep.1
+  store i2 -1, i2 addrspace(1)* %out
+  ret void
+}
+
+; CHECK-LABEL: @merge_different_store_sizes_i1_i8(
+; CHECK: store i1 true
+; CHECK: store i8 123
+define void @merge_different_store_sizes_i1_i8(i8 addrspace(1)* %out) #0 {
+  %out.i1 = bitcast i8 addrspace(1)* %out to i1 addrspace(1)*
+  %out.gep.1 = getelementptr i8, i8 addrspace(1)* %out, i32 1
+  store i1 true, i1 addrspace(1)* %out.i1
+  store i8 123, i8 addrspace(1)* %out.gep.1
+  ret void
+}
+
+; CHECK-LABEL: @merge_different_store_sizes_i8_i1(
+; CHECK: store i8 123
+; CHECK: store i1 true
+define void @merge_different_store_sizes_i8_i1(i1 addrspace(1)* %out) #0 {
+  %out.i8 = bitcast i1 addrspace(1)* %out to i8 addrspace(1)*
+  %out.gep.1 = getelementptr i8, i8 addrspace(1)* %out.i8, i32 1
+  store i8 123, i8 addrspace(1)* %out.gep.1
+  store i1 true, i1 addrspace(1)* %out
+  ret void
+}
+
+; CHECK-LABEL: @merge_store_2_constant_structs(
+; CHECK: store %struct.foo
+; CHECK: store %struct.foo
+define void @merge_store_2_constant_structs(%struct.foo addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr %struct.foo, %struct.foo addrspace(1)* %out, i32 1
+  store %struct.foo { i32 12, i8 3 }, %struct.foo addrspace(1)* %out.gep.1
+  store %struct.foo { i32 92, i8 9 }, %struct.foo addrspace(1)* %out
+  ret void
+}
+
+; sub-byte element size
+; CHECK-LABEL: @merge_store_2_constants_v2i2(
+; CHECK: store <2 x i2>
+; CHECK: store <2 x i2>
+define void @merge_store_2_constants_v2i2(<2 x i2> addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr <2 x i2>, <2 x i2> addrspace(1)* %out, i32 1
+  store <2 x i2> <i2 1, i2 -1>, <2 x i2> addrspace(1)* %out.gep.1
+  store <2 x i2> <i2 -1, i2 1>, <2 x i2> addrspace(1)* %out
+  ret void
+}
+
+; sub-byte element size but byte size
+
+; CHECK-LABEL: @merge_store_2_constants_v4i2(
+; CHECK: store <4 x i2>
+; CHECK: store <4 x i2>
+define void @merge_store_2_constants_v4i2(<4 x i2> addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr <4 x i2>, <4 x i2> addrspace(1)* %out, i32 1
+  store <4 x i2> <i2 1, i2 -1, i2 1, i2 -1>, <4 x i2> addrspace(1)* %out.gep.1
+  store <4 x i2> <i2 -1, i2 1, i2 -1, i2 1>, <4 x i2> addrspace(1)* %out
+  ret void
+}
+
+; CHECK-LABEL: @merge_load_2_constants_i1(
+; CHECK: load i1
+; CHECK: load i1
+define void @merge_load_2_constants_i1(i1 addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr i1, i1 addrspace(1)* %out, i32 1
+  %x = load i1, i1 addrspace(1)* %out.gep.1
+  %y = load i1, i1 addrspace(1)* %out
+  call void @use_i1(i1 %x)
+  call void @use_i1(i1 %y)
+  ret void
+}
+
+; CHECK-LABEL: @merge_load_2_constants_i2(
+; CHECK: load i2
+; CHECK: load i2
+define void @merge_load_2_constants_i2(i2 addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr i2, i2 addrspace(1)* %out, i32 1
+  %x = load i2, i2 addrspace(1)* %out.gep.1
+  %y = load i2, i2 addrspace(1)* %out
+  call void @use_i2(i2 %x)
+  call void @use_i2(i2 %y)
+  ret void
+}
+
+; CHECK-LABEL: @merge_different_load_sizes_i1_i8(
+; CHECK: load i1
+; CHECK: load i8
+define void @merge_different_load_sizes_i1_i8(i8 addrspace(1)* %out) #0 {
+  %out.i1 = bitcast i8 addrspace(1)* %out to i1 addrspace(1)*
+  %out.gep.1 = getelementptr i8, i8 addrspace(1)* %out, i32 1
+  %x = load i1, i1 addrspace(1)* %out.i1
+  %y = load i8, i8 addrspace(1)* %out.gep.1
+  call void @use_i1(i1 %x)
+  call void @use_i8(i8 %y)
+  ret void
+}
+
+; CHECK-LABEL: @merge_different_load_sizes_i8_i1(
+; CHECK: load i8
+; CHECK: load i1
+define void @merge_different_load_sizes_i8_i1(i1 addrspace(1)* %out) #0 {
+  %out.i8 = bitcast i1 addrspace(1)* %out to i8 addrspace(1)*
+  %out.gep.1 = getelementptr i8, i8 addrspace(1)* %out.i8, i32 1
+  %x = load i8, i8 addrspace(1)* %out.gep.1
+  %y = load i1, i1 addrspace(1)* %out
+  call void @use_i8(i8 %x)
+  call void @use_i1(i1 %y)
+  ret void
+}
+
+; CHECK-LABEL: @merge_load_2_constant_structs(
+; CHECK: load %struct.foo
+; CHECK: load %struct.foo
+define void @merge_load_2_constant_structs(%struct.foo addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr %struct.foo, %struct.foo addrspace(1)* %out, i32 1
+  %x = load %struct.foo, %struct.foo addrspace(1)* %out.gep.1
+  %y = load %struct.foo, %struct.foo addrspace(1)* %out
+  call void @use_foo(%struct.foo %x)
+  call void @use_foo(%struct.foo %y)
+  ret void
+}
+
+; CHECK-LABEL: @merge_load_2_constants_v2i2(
+; CHECK: load <2 x i2>
+; CHECK: load <2 x i2>
+define void @merge_load_2_constants_v2i2(<2 x i2> addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr <2 x i2>, <2 x i2> addrspace(1)* %out, i32 1
+  %x = load <2 x i2>, <2 x i2> addrspace(1)* %out.gep.1
+  %y = load <2 x i2>, <2 x i2> addrspace(1)* %out
+  call void @use_v2i2(<2 x i2> %x)
+  call void @use_v2i2(<2 x i2> %y)
+  ret void
+}
+
+; CHECK-LABEL: @merge_load_2_constants_v4i2(
+; CHECK: load <4 x i2>
+; CHECK: load <4 x i2>
+define void @merge_load_2_constants_v4i2(<4 x i2> addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr <4 x i2>, <4 x i2> addrspace(1)* %out, i32 1
+  %x = load <4 x i2>, <4 x i2> addrspace(1)* %out.gep.1
+  %y = load <4 x i2>, <4 x i2> addrspace(1)* %out
+  call void @use_v4i2(<4 x i2> %x)
+  call void @use_v4i2(<4 x i2> %y)
+  ret void
+}
+
+; CHECK-LABEL: @merge_store_2_constants_i9(
+; CHECK: store i9 3
+; CHECK: store i9 -5
+define void @merge_store_2_constants_i9(i9 addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr i9, i9 addrspace(1)* %out, i32 1
+  store i9 3, i9 addrspace(1)* %out.gep.1
+  store i9 -5, i9 addrspace(1)* %out
+  ret void
+}
+
+; CHECK-LABEL: @merge_load_2_constants_v2i9(
+; CHECK: load <2 x i9>
+; CHECK: load <2 x i9>
+define void @merge_load_2_constants_v2i9(<2 x i9> addrspace(1)* %out) #0 {
+  %out.gep.1 = getelementptr <2 x i9>, <2 x i9> addrspace(1)* %out, i32 1
+  %x = load <2 x i9>, <2 x i9> addrspace(1)* %out.gep.1
+  %y = load <2 x i9>, <2 x i9> addrspace(1)* %out
+  call void @use_v2i9(<2 x i9> %x)
+  call void @use_v2i9(<2 x i9> %y)
+  ret void
+}
+
+attributes #0 = { nounwind }




More information about the llvm-commits mailing list