[PATCH] D49816: [GlobalOpt] Test array indices inside structs for out-of-bounds accesses

Dave Green via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 25 12:09:51 PDT 2018


dmgreen created this revision.
dmgreen added reviewers: efriedma, rsmith, hfinkel.

First go at fixing PR38309.  We now, from clang, can turn arrays of

  static short g_data[] = {16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0};

into structs of the form

  @g_data = internal global <{ [8 x i16], [8 x i16] }> ...

GlobalOpt can incorrectly SROA it, not realising that the access to the first
element may overflow into the second.

I believe this makes the globalsra-partial.ll test case invalid as the %i value
could be out of bounds. I've re-purposed it as a negative test for this case.


https://reviews.llvm.org/D49816

Files:
  lib/Transforms/IPO/GlobalOpt.cpp
  test/Transforms/GlobalOpt/globalsra-partial.ll


Index: test/Transforms/GlobalOpt/globalsra-partial.ll
===================================================================
--- test/Transforms/GlobalOpt/globalsra-partial.ll
+++ test/Transforms/GlobalOpt/globalsra-partial.ll
@@ -1,11 +1,12 @@
-; In this case, the global can only be broken up by one level.
+; In this case, the global cannot be merged as i may be out of range
 
 ; RUN: opt < %s -globalopt -S | FileCheck %s
 target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
 
 @G = internal global { i32, [4 x float] } zeroinitializer               ; <{ i32, [4 x float] }*> [#uses=3]
 
-; CHECK-NOT: 12345
+; CHECK: @G = internal unnamed_addr global { i32, [4 x float] }
+; CHECK: 12345
 define void @onlystore() {
         store i32 12345, i32* getelementptr ({ i32, [4 x float] }, { i32, [4 x float] }* @G, i32 0, i32 0)
         ret void
Index: lib/Transforms/IPO/GlobalOpt.cpp
===================================================================
--- lib/Transforms/IPO/GlobalOpt.cpp
+++ lib/Transforms/IPO/GlobalOpt.cpp
@@ -409,8 +409,9 @@
   gep_type_iterator GEPI = gep_type_begin(U), E = gep_type_end(U);
   ++GEPI;  // Skip over the pointer index.
 
-  // If this is a use of an array allocation, do a bit more checking for sanity.
-  if (GEPI.isSequential()) {
+  // If this is a use of an array allocation (possibly inside a struct), do a
+  // bit more checking for sanity.
+  if (GEPI.isSequential() || GEPI.isStruct()) {
     ConstantInt *Idx = cast<ConstantInt>(U->getOperand(2));
 
     // Check to make sure that index falls within the array.  If not,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D49816.157333.patch
Type: text/x-patch
Size: 1648 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180725/7f6efbe1/attachment.bin>


More information about the llvm-commits mailing list