This repository has been archived by the owner on Feb 5, 2019. It is now read-only.
forked from luqmana/llvm
-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@348987 91177308-0d34-0410-b5e6-96231b3b80d8
- Loading branch information
Showing
2 changed files
with
52 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |