[llvm] 5969e57 - [IR] Handle large element size when calculating GEP indices

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 24 13:20:30 PDT 2021


Author: Nikita Popov
Date: 2021-09-24T22:20:20+02:00
New Revision: 5969e5743ae9cd17d08436a4b1139b8c4a24cc4d

URL: https://github.com/llvm/llvm-project/commit/5969e5743ae9cd17d08436a4b1139b8c4a24cc4d
DIFF: https://github.com/llvm/llvm-project/commit/5969e5743ae9cd17d08436a4b1139b8c4a24cc4d.diff

LOG: [IR] Handle large element size when calculating GEP indices

This is a fix for the issue reported at
https://reviews.llvm.org/D110043#3019942:
The ElementSize is a uint64_t and as such may be larger than the
index space, or be negative in the index space. This is UB, but
shouldn't cause assertion failures.

We address this by detecting whether the size is too large and
use a zero index in that case (which is always conservatively
correct).

Differential Revision: https://reviews.llvm.org/D110437

Added: 
    llvm/test/Transforms/GlobalOpt/large-element-size.ll

Modified: 
    llvm/lib/IR/DataLayout.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 5de47b8625b37..d2bdd2a0d4e00 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -903,9 +903,13 @@ int64_t DataLayout::getIndexedOffsetInType(Type *ElemTy,
 
 static void addElementIndex(SmallVectorImpl<APInt> &Indices, TypeSize ElemSize,
                             APInt &Offset) {
-  // Skip over scalable or zero size elements.
-  if (ElemSize.isScalable() || ElemSize == 0) {
-    Indices.push_back(APInt::getZero(Offset.getBitWidth()));
+  // Skip over scalable or zero size elements. Also skip element sizes larger
+  // than the positive index space, because the arithmetic below may not be
+  // correct in that case.
+  unsigned BitWidth = Offset.getBitWidth();
+  if (ElemSize.isScalable() || ElemSize == 0 ||
+      !isUIntN(BitWidth - 1, ElemSize)) {
+    Indices.push_back(APInt::getZero(BitWidth));
     return;
   }
 

diff  --git a/llvm/test/Transforms/GlobalOpt/large-element-size.ll b/llvm/test/Transforms/GlobalOpt/large-element-size.ll
new file mode 100644
index 0000000000000..1c09152138084
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/large-element-size.ll
@@ -0,0 +1,12 @@
+; RUN: opt -S -passes=globalopt < %s | FileCheck %s
+
+target datalayout = "p:32:32"
+
+%struct.s.2 = type { %struct.t.1, %struct.t.1, %struct.t.1, %struct.u.0, %struct.u.0 }
+%struct.t.1 = type { %struct.u.0, %struct.u.0, %struct.u.0, %struct.u.0, i32, i32, i32, i32 }
+%struct.u.0 = type { i32, i32, i32, i8 }
+
+ at s = external global [700 x [24000 x %struct.s.2]], align 1
+ at p = global %struct.s.2* bitcast (i8* getelementptr (i8, i8* bitcast ([700 x [24000 x %struct.s.2]]* @s to i8*), i64 2247483647) to %struct.s.2*), align 1
+
+; CHECK: @p = local_unnamed_addr global %struct.s.2* bitcast (i8* getelementptr (i8, i8* bitcast ([700 x [24000 x %struct.s.2]]* @s to i8*), i32 -2047483649) to %struct.s.2*), align 1


        


More information about the llvm-commits mailing list