Re-commit r257064, after it was reverted in r257340.
This contains a fix for the issue that caused the revert:
we no longer assume that we can insert instructions after the
instruction that produces the base pointer. We previously
assumed that this would be ok, because the instruction produces
a value and therefore is not a terminator. This is false for invoke
instructions. We will now insert these new instruction directly
at the location of the users.
Original commit message:
[InstCombine] Look through PHIs, GEPs, IntToPtrs and PtrToInts to expose more constants when comparing GEPs
Summary:
When comparing two GEP instructions which have the same base pointer
and one of them has a constant index, it is possible to only compare
indices, transforming it to a compare with a constant. This removes
one use for the GEP instruction with the constant index, can reduce
register pressure and can sometimes lead to removing the comparisson
entirely.
InstCombine was already doing this when comparing two GEPs if the base
pointers were the same. However, in the case where we have complex
pointer arithmetic (GEPs applied to GEPs, PHIs of GEPs, conversions to
or from integers, etc) the value of the original base pointer will be
hidden to the optimizer and this transformation will be disabled.
This change detects when the two sides of the comparison can be
expressed as GEPs with the same base pointer, even if they don't
appear as such in the IR. The transformation will convert all the
pointer arithmetic to arithmetic done on indices and all the relevant
uses of GEPs to GEPs with a common base pointer. The GEP comparison
will be converted to a comparison done on indices.
Reviewers: majnemer, jmolloy
Subscribers: hfinkel, jevinskie, jmolloy, aadg, llvm-commits
Differential Revision: http://reviews.llvm.org/D15146
llvm-svn: 257897
2016-01-15 23:52:05 +08:00
|
|
|
; RUN: opt -instcombine -S < %s | FileCheck %s
|
|
|
|
|
|
|
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:64"
|
|
|
|
|
|
|
|
define i32 *@test1(i32* %A, i32 %Offset) {
|
|
|
|
entry:
|
|
|
|
%tmp = getelementptr inbounds i32, i32* %A, i32 %Offset
|
|
|
|
br label %bb
|
|
|
|
|
|
|
|
bb:
|
|
|
|
%RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %entry ]
|
|
|
|
%LHS = getelementptr inbounds i32, i32* %A, i32 100
|
|
|
|
%RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
|
|
|
|
%cond = icmp ult i32 * %LHS, %RHS
|
|
|
|
br i1 %cond, label %bb2, label %bb
|
|
|
|
|
|
|
|
bb2:
|
|
|
|
ret i32* %RHS
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test1(
|
|
|
|
; CHECK: %[[INDEX:[0-9A-Za-z.]+]] = phi i32 [ %[[ADD:[0-9A-Za-z.]+]], %bb ], [ %Offset, %entry ]
|
|
|
|
; CHECK: %[[ADD]] = add nsw i32 %[[INDEX]], 1
|
|
|
|
; CHECK: %cond = icmp sgt i32 %[[INDEX]], 100
|
|
|
|
; CHECK: br i1 %cond, label %bb2, label %bb
|
|
|
|
; CHECK: %[[PTR:[0-9A-Za-z.]+]] = getelementptr inbounds i32, i32* %A, i32 %[[INDEX]]
|
|
|
|
; CHECK: ret i32* %[[PTR]]
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 *@test2(i32 %A, i32 %Offset) {
|
|
|
|
entry:
|
|
|
|
%A.ptr = inttoptr i32 %A to i32*
|
|
|
|
%tmp = getelementptr inbounds i32, i32* %A.ptr, i32 %Offset
|
|
|
|
br label %bb
|
|
|
|
|
|
|
|
bb:
|
|
|
|
%RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %entry ]
|
|
|
|
%LHS = getelementptr inbounds i32, i32* %A.ptr, i32 100
|
|
|
|
%RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
|
|
|
|
%cmp0 = ptrtoint i32 *%LHS to i32
|
|
|
|
%cmp1 = ptrtoint i32 *%RHS to i32
|
|
|
|
%cond = icmp ult i32 %cmp0, %cmp1
|
|
|
|
br i1 %cond, label %bb2, label %bb
|
|
|
|
|
|
|
|
bb2:
|
|
|
|
ret i32* %RHS
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test2(
|
|
|
|
; CHECK: %[[INDEX:[0-9A-Za-z.]+]] = phi i32 [ %[[ADD:[0-9A-Za-z.]+]], %bb ], [ %Offset, %entry ]
|
|
|
|
; CHECK: %[[ADD]] = add nsw i32 %[[INDEX]], 1
|
|
|
|
; CHECK: %cond = icmp sgt i32 %[[INDEX]], 100
|
|
|
|
; CHECK: br i1 %cond, label %bb2, label %bb
|
|
|
|
; CHECK: %[[TOPTR:[0-9A-Za-z.]+]] = inttoptr i32 %[[ADD:[0-9A-Za-z.]+]] to i32*
|
|
|
|
; CHECK: %[[PTR:[0-9A-Za-z.]+]] = getelementptr inbounds i32, i32* %[[TOPTR]], i32 %[[INDEX]]
|
|
|
|
; CHECK: ret i32* %[[PTR]]
|
|
|
|
}
|
|
|
|
|
|
|
|
; Perform the transformation only if we know that the GEPs used are inbounds.
|
|
|
|
define i32 *@test3(i32* %A, i32 %Offset) {
|
|
|
|
entry:
|
|
|
|
%tmp = getelementptr i32, i32* %A, i32 %Offset
|
|
|
|
br label %bb
|
|
|
|
|
|
|
|
bb:
|
|
|
|
%RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %entry ]
|
|
|
|
%LHS = getelementptr i32, i32* %A, i32 100
|
|
|
|
%RHS.next = getelementptr i32, i32* %RHS, i64 1
|
|
|
|
%cond = icmp ult i32 * %LHS, %RHS
|
|
|
|
br i1 %cond, label %bb2, label %bb
|
|
|
|
|
|
|
|
bb2:
|
|
|
|
ret i32* %RHS
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test3(
|
|
|
|
; CHECK-NOT: %cond = icmp sgt i32 %{{[0-9A-Za-z.]+}}, 100
|
|
|
|
}
|
|
|
|
|
|
|
|
; An inttoptr that requires an extension or truncation will be opaque when determining
|
|
|
|
; the base pointer. In this case we can still perform the transformation by considering
|
|
|
|
; A.ptr as being the base pointer.
|
|
|
|
define i32 *@test4(i16 %A, i32 %Offset) {
|
|
|
|
entry:
|
|
|
|
%A.ptr = inttoptr i16 %A to i32*
|
|
|
|
%tmp = getelementptr inbounds i32, i32* %A.ptr, i32 %Offset
|
|
|
|
br label %bb
|
|
|
|
|
|
|
|
bb:
|
|
|
|
%RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %entry ]
|
|
|
|
%LHS = getelementptr inbounds i32, i32* %A.ptr, i32 100
|
|
|
|
%RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
|
|
|
|
%cmp0 = ptrtoint i32 *%LHS to i32
|
|
|
|
%cmp1 = ptrtoint i32 *%RHS to i32
|
|
|
|
%cond = icmp ult i32 %cmp0, %cmp1
|
|
|
|
br i1 %cond, label %bb2, label %bb
|
|
|
|
|
|
|
|
bb2:
|
|
|
|
ret i32* %RHS
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test4(
|
|
|
|
; CHECK: %cond = icmp sgt i32 %{{[0-9A-Za-z.]+}}, 100
|
|
|
|
}
|
|
|
|
|
|
|
|
declare i32* @fun_ptr()
|
|
|
|
|
|
|
|
define i32 *@test5(i32 %Offset) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
%A = invoke i32 *@fun_ptr() to label %cont unwind label %lpad
|
|
|
|
|
|
|
|
cont:
|
|
|
|
%tmp = getelementptr inbounds i32, i32* %A, i32 %Offset
|
|
|
|
br label %bb
|
|
|
|
|
|
|
|
bb:
|
|
|
|
%RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %cont ]
|
|
|
|
%LHS = getelementptr inbounds i32, i32* %A, i32 100
|
|
|
|
%RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
|
|
|
|
%cond = icmp ult i32 * %LHS, %RHS
|
|
|
|
br i1 %cond, label %bb2, label %bb
|
|
|
|
|
|
|
|
bb2:
|
|
|
|
ret i32* %RHS
|
|
|
|
|
|
|
|
lpad:
|
|
|
|
%l = landingpad { i8*, i32 } cleanup
|
|
|
|
ret i32* null
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test5(
|
|
|
|
; CHECK: %[[INDEX:[0-9A-Za-z.]+]] = phi i32 [ %[[ADD:[0-9A-Za-z.]+]], %bb ], [ %Offset, %cont ]
|
|
|
|
; CHECK: %[[ADD]] = add nsw i32 %[[INDEX]], 1
|
|
|
|
; CHECK: %cond = icmp sgt i32 %[[INDEX]], 100
|
|
|
|
; CHECK: br i1 %cond, label %bb2, label %bb
|
|
|
|
; CHECK: %[[PTR:[0-9A-Za-z.]+]] = getelementptr inbounds i32, i32* %A, i32 %[[INDEX]]
|
|
|
|
; CHECK: ret i32* %[[PTR]]
|
|
|
|
}
|
|
|
|
|
|
|
|
declare i32 @fun_i32()
|
|
|
|
|
|
|
|
define i32 *@test6(i32 %Offset) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
%A = invoke i32 @fun_i32() to label %cont unwind label %lpad
|
|
|
|
|
|
|
|
cont:
|
|
|
|
%A.ptr = inttoptr i32 %A to i32*
|
|
|
|
%tmp = getelementptr inbounds i32, i32* %A.ptr, i32 %Offset
|
|
|
|
br label %bb
|
|
|
|
|
|
|
|
bb:
|
|
|
|
%RHS = phi i32* [ %RHS.next, %bb ], [ %tmp, %cont ]
|
|
|
|
%LHS = getelementptr inbounds i32, i32* %A.ptr, i32 100
|
|
|
|
%RHS.next = getelementptr inbounds i32, i32* %RHS, i64 1
|
|
|
|
%cond = icmp ult i32 * %LHS, %RHS
|
|
|
|
br i1 %cond, label %bb2, label %bb
|
|
|
|
|
|
|
|
bb2:
|
|
|
|
ret i32* %RHS
|
|
|
|
|
|
|
|
lpad:
|
|
|
|
%l = landingpad { i8*, i32 } cleanup
|
|
|
|
ret i32* null
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test6(
|
|
|
|
; CHECK: %[[INDEX:[0-9A-Za-z.]+]] = phi i32 [ %[[ADD:[0-9A-Za-z.]+]], %bb ], [ %Offset, %cont ]
|
|
|
|
; CHECK: %[[ADD]] = add nsw i32 %[[INDEX]], 1
|
|
|
|
; CHECK: %cond = icmp sgt i32 %[[INDEX]], 100
|
|
|
|
; CHECK: br i1 %cond, label %bb2, label %bb
|
|
|
|
; CHECK: %[[TOPTR:[0-9A-Za-z.]+]] = inttoptr i32 %[[ADD:[0-9A-Za-z.]+]] to i32*
|
|
|
|
; CHECK: %[[PTR:[0-9A-Za-z.]+]] = getelementptr inbounds i32, i32* %[[TOPTR]], i32 %[[INDEX]]
|
|
|
|
; CHECK: ret i32* %[[PTR]]
|
|
|
|
}
|
|
|
|
|
2016-09-16 04:10:09 +08:00
|
|
|
|
|
|
|
@pr30402 = constant i64 3
|
|
|
|
define i1 @test7() {
|
|
|
|
entry:
|
|
|
|
br label %bb7
|
|
|
|
|
|
|
|
bb7: ; preds = %bb10, %entry-block
|
|
|
|
%phi = phi i64* [ @pr30402, %entry ], [ getelementptr inbounds (i64, i64* @pr30402, i32 1), %bb7 ]
|
|
|
|
%cmp = icmp eq i64* %phi, getelementptr inbounds (i64, i64* @pr30402, i32 1)
|
|
|
|
br i1 %cmp, label %bb10, label %bb7
|
|
|
|
|
|
|
|
bb10:
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
; CHECK-LABEL: @test7(
|
|
|
|
; CHECK: %[[phi:.*]] = phi i64* [ @pr30402, %entry ], [ getelementptr inbounds (i64, i64* @pr30402, i32 1), %bb7 ]
|
|
|
|
; CHECK: %[[cmp:.*]] = icmp eq i64* %[[phi]], getelementptr inbounds (i64, i64* @pr30402, i32 1)
|
|
|
|
; CHECK: ret i1 %[[cmp]]
|
|
|
|
|
|
|
|
|
Re-commit r257064, after it was reverted in r257340.
This contains a fix for the issue that caused the revert:
we no longer assume that we can insert instructions after the
instruction that produces the base pointer. We previously
assumed that this would be ok, because the instruction produces
a value and therefore is not a terminator. This is false for invoke
instructions. We will now insert these new instruction directly
at the location of the users.
Original commit message:
[InstCombine] Look through PHIs, GEPs, IntToPtrs and PtrToInts to expose more constants when comparing GEPs
Summary:
When comparing two GEP instructions which have the same base pointer
and one of them has a constant index, it is possible to only compare
indices, transforming it to a compare with a constant. This removes
one use for the GEP instruction with the constant index, can reduce
register pressure and can sometimes lead to removing the comparisson
entirely.
InstCombine was already doing this when comparing two GEPs if the base
pointers were the same. However, in the case where we have complex
pointer arithmetic (GEPs applied to GEPs, PHIs of GEPs, conversions to
or from integers, etc) the value of the original base pointer will be
hidden to the optimizer and this transformation will be disabled.
This change detects when the two sides of the comparison can be
expressed as GEPs with the same base pointer, even if they don't
appear as such in the IR. The transformation will convert all the
pointer arithmetic to arithmetic done on indices and all the relevant
uses of GEPs to GEPs with a common base pointer. The GEP comparison
will be converted to a comparison done on indices.
Reviewers: majnemer, jmolloy
Subscribers: hfinkel, jevinskie, jmolloy, aadg, llvm-commits
Differential Revision: http://reviews.llvm.org/D15146
llvm-svn: 257897
2016-01-15 23:52:05 +08:00
|
|
|
declare i32 @__gxx_personality_v0(...)
|
2017-01-31 22:04:15 +08:00
|
|
|
|
|
|
|
define i1 @test8(i64* %in, i64 %offset) {
|
|
|
|
entry:
|
|
|
|
|
|
|
|
%ld = load i64, i64* %in, align 8
|
|
|
|
%casti8 = inttoptr i64 %ld to i8*
|
|
|
|
%gepi8 = getelementptr inbounds i8, i8* %casti8, i64 %offset
|
|
|
|
%cast = bitcast i8* %gepi8 to i32**
|
|
|
|
%ptrcast = inttoptr i64 %ld to i32**
|
|
|
|
%gepi32 = getelementptr inbounds i32*, i32** %ptrcast, i64 1
|
|
|
|
%cmp = icmp eq i32** %gepi32, %cast
|
|
|
|
ret i1 %cmp
|
|
|
|
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test8(
|
|
|
|
; CHECK-NOT: icmp eq i32 %{{[0-9A-Za-z.]+}}, 1
|
|
|
|
}
|