summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2018-12-12 23:19:03 +0000
committerNikita Popov <nikita.ppv@gmail.com>2018-12-12 23:19:03 +0000
commit36e03ac6ee91366225f446db6437f184de258be6 (patch)
treea11100974c6cfbedcc61bef71cfccc3bffa9ab1c /llvm
parent102008589836db7d5f95fe5efb5dae31754cbb8c (diff)
downloadbcm5719-llvm-36e03ac6ee91366225f446db6437f184de258be6.tar.gz
bcm5719-llvm-36e03ac6ee91366225f446db6437f184de258be6.zip
[InstCombine] Fix negative GEP offset evaluation for 32-bit pointers
This fixes https://bugs.llvm.org/show_bug.cgi?id=39908. The evaluateGEPOffsetExpression() function simplifies GEP offsets for use in comparisons against zero, basically by converting X*Scale+Offset==0 to X+Offset/Scale==0 if Scale divides Offset. However, before this is done, Offset is masked down to the pointer size. This results in incorrect results for negative Offsets, because we basically end up dividing the 32-bit offset *zero* extended to 64-bit bits (rather than sign extended). Fix this by explicitly sign extending the truncated value. Differential Revision: https://reviews.llvm.org/D55449 llvm-svn: 348987
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp8
-rw-r--r--llvm/test/Transforms/InstCombine/pr39908.ll49
2 files changed, 52 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 41a1a28a007..38539936a24 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -522,11 +522,9 @@ static Value *evaluateGEPOffsetExpression(User *GEP, InstCombiner &IC,
}
// Otherwise, there is an index. The computation we will do will be modulo
- // the pointer size, so get it.
- uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth);
-
- Offset &= PtrSizeMask;
- VariableScale &= PtrSizeMask;
+ // the pointer size.
+ Offset = SignExtend64(Offset, IntPtrWidth);
+ VariableScale = SignExtend64(VariableScale, IntPtrWidth);
// To do this transformation, any constant index must be a multiple of the
// variable scale factor. For example, we can evaluate "12 + 4*i" as "3 + i",
diff --git a/llvm/test/Transforms/InstCombine/pr39908.ll b/llvm/test/Transforms/InstCombine/pr39908.ll
new file mode 100644
index 00000000000..bd7a82990ad
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/pr39908.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+target datalayout = "p:32:32"
+
+%S = type { [2 x i32] }
+
+define i1 @test([0 x %S]* %p, i32 %n) {
+; CHECK-LABEL: @test(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %start.cast = bitcast [0 x %S]* %p to %S*
+ %end = getelementptr inbounds [0 x %S], [0 x %S]* %p, i32 0, i32 %n, i32 0, i32 0
+ %end.cast = bitcast i32* %end to %S*
+ %last = getelementptr inbounds %S, %S* %end.cast, i32 -1
+ %cmp = icmp eq %S* %last, %start.cast
+ ret i1 %cmp
+}
+
+; Same test using 64-bit indices.
+define i1 @test64([0 x %S]* %p, i64 %n) {
+; CHECK-LABEL: @test64(
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[N:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %start.cast = bitcast [0 x %S]* %p to %S*
+ %end = getelementptr inbounds [0 x %S], [0 x %S]* %p, i64 0, i64 %n, i32 0, i64 0
+ %end.cast = bitcast i32* %end to %S*
+ %last = getelementptr inbounds %S, %S* %end.cast, i64 -1
+ %cmp = icmp eq %S* %last, %start.cast
+ ret i1 %cmp
+}
+
+; Here the offset overflows and is treated modulo 2^32. This is UB.
+define i1 @test64_overflow([0 x %S]* %p, i64 %n) {
+; CHECK-LABEL: @test64_overflow(
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[N:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %start.cast = bitcast [0 x %S]* %p to %S*
+ %end = getelementptr inbounds [0 x %S], [0 x %S]* %p, i64 0, i64 %n, i32 0, i64 8589934592
+ %end.cast = bitcast i32* %end to %S*
+ %last = getelementptr inbounds %S, %S* %end.cast, i64 -1
+ %cmp = icmp eq %S* %last, %start.cast
+ ret i1 %cmp
+}
OpenPOWER on IntegriCloud