2009-09-12 02:01:28 +08:00
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
2002-04-18 23:39:50 +08:00
|
|
|
|
2013-08-21 05:20:04 +08:00
|
|
|
target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32"
|
|
|
|
|
2009-08-31 05:31:34 +08:00
|
|
|
%intstruct = type { i32 }
|
2009-08-31 04:48:15 +08:00
|
|
|
%pair = type { i32, i32 }
|
2009-08-31 05:02:36 +08:00
|
|
|
%struct.B = type { double }
|
|
|
|
%struct.A = type { %struct.B, i32, i32 }
|
|
|
|
|
|
|
|
|
2009-08-31 04:48:15 +08:00
|
|
|
@Global = constant [10 x i8] c"helloworld"
|
2013-08-21 05:20:04 +08:00
|
|
|
@Global_as1 = addrspace(1) constant [10 x i8] c"helloworld"
|
2002-08-17 05:18:21 +08:00
|
|
|
|
2008-03-25 12:26:08 +08:00
|
|
|
; Test noop elimination
|
2009-08-31 04:48:15 +08:00
|
|
|
define i32* @test1(i32* %I) {
|
2013-08-16 07:11:07 +08:00
|
|
|
%A = getelementptr i32* %I, i64 0
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i32* %A
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test1(
|
2009-08-31 04:48:15 +08:00
|
|
|
; CHECK: ret i32* %I
|
2002-08-03 02:47:11 +08:00
|
|
|
}
|
|
|
|
|
2013-08-21 05:20:04 +08:00
|
|
|
define i32 addrspace(1)* @test1_as1(i32 addrspace(1)* %I) {
|
|
|
|
%A = getelementptr i32 addrspace(1)* %I, i64 0
|
|
|
|
ret i32 addrspace(1)* %A
|
|
|
|
; CHECK-LABEL: @test1_as1(
|
|
|
|
; CHECK: ret i32 addrspace(1)* %I
|
|
|
|
}
|
|
|
|
|
2008-03-25 12:26:08 +08:00
|
|
|
; Test noop elimination
|
2009-08-31 04:48:15 +08:00
|
|
|
define i32* @test2(i32* %I) {
|
|
|
|
%A = getelementptr i32* %I
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i32* %A
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test2(
|
2009-08-31 04:48:15 +08:00
|
|
|
; CHECK: ret i32* %I
|
2002-08-03 02:47:11 +08:00
|
|
|
}
|
2008-03-25 12:26:08 +08:00
|
|
|
|
|
|
|
; Test that two array indexing geps fold
|
2009-08-31 04:48:15 +08:00
|
|
|
define i32* @test3(i32* %I) {
|
|
|
|
%A = getelementptr i32* %I, i64 17
|
|
|
|
%B = getelementptr i32* %A, i64 4
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i32* %B
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test3(
|
2009-08-31 04:48:15 +08:00
|
|
|
; CHECK: getelementptr i32* %I, i64 21
|
2002-08-03 02:47:11 +08:00
|
|
|
}
|
2002-05-02 23:24:40 +08:00
|
|
|
|
2008-03-25 12:26:08 +08:00
|
|
|
; Test that two getelementptr insts fold
|
2009-08-31 04:48:15 +08:00
|
|
|
define i32* @test4({ i32 }* %I) {
|
2013-08-16 07:11:07 +08:00
|
|
|
%A = getelementptr { i32 }* %I, i64 1
|
2009-08-31 04:48:15 +08:00
|
|
|
%B = getelementptr { i32 }* %A, i64 0, i32 0
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i32* %B
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test4(
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
; CHECK: getelementptr { i32 }* %I, i64 1, i32 0
|
2002-08-03 02:47:11 +08:00
|
|
|
}
|
2002-08-17 05:18:21 +08:00
|
|
|
|
2009-08-31 04:48:15 +08:00
|
|
|
define void @test5(i8 %B) {
|
2008-03-25 12:26:08 +08:00
|
|
|
; This should be turned into a constexpr instead of being an instruction
|
2013-08-16 07:11:07 +08:00
|
|
|
%A = getelementptr [10 x i8]* @Global, i64 0, i64 4
|
2008-03-25 12:26:08 +08:00
|
|
|
store i8 %B, i8* %A
|
|
|
|
ret void
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test5(
|
2009-08-31 04:48:15 +08:00
|
|
|
; CHECK: store i8 %B, i8* getelementptr inbounds ([10 x i8]* @Global, i64 0, i64 4)
|
2002-08-17 05:18:21 +08:00
|
|
|
}
|
2002-11-05 00:35:14 +08:00
|
|
|
|
2013-08-21 05:20:04 +08:00
|
|
|
define void @test5_as1(i8 %B) {
|
|
|
|
; This should be turned into a constexpr instead of being an instruction
|
|
|
|
%A = getelementptr [10 x i8] addrspace(1)* @Global_as1, i16 0, i16 4
|
|
|
|
store i8 %B, i8 addrspace(1)* %A
|
|
|
|
ret void
|
|
|
|
; CHECK-LABEL: @test5_as1(
|
|
|
|
; CHECK: store i8 %B, i8 addrspace(1)* getelementptr inbounds ([10 x i8] addrspace(1)* @Global_as1, i16 0, i16 4)
|
|
|
|
}
|
|
|
|
|
|
|
|
%as1_ptr_struct = type { i32 addrspace(1)* }
|
|
|
|
%as2_ptr_struct = type { i32 addrspace(2)* }
|
|
|
|
|
|
|
|
@global_as2 = addrspace(2) global i32 zeroinitializer
|
|
|
|
@global_as1_as2_ptr = addrspace(1) global %as2_ptr_struct { i32 addrspace(2)* @global_as2 }
|
|
|
|
|
|
|
|
; This should be turned into a constexpr instead of being an instruction
|
|
|
|
define void @test_evaluate_gep_nested_as_ptrs(i32 addrspace(2)* %B) {
|
|
|
|
; CHECK-LABEL: @test_evaluate_gep_nested_as_ptrs(
|
|
|
|
; CHECK-NEXT: store i32 addrspace(2)* %B, i32 addrspace(2)* addrspace(1)* getelementptr inbounds (%as2_ptr_struct addrspace(1)* @global_as1_as2_ptr, i16 0, i32 0), align 8
|
|
|
|
; CHECK-NEXT: ret void
|
|
|
|
%A = getelementptr %as2_ptr_struct addrspace(1)* @global_as1_as2_ptr, i16 0, i32 0
|
|
|
|
store i32 addrspace(2)* %B, i32 addrspace(2)* addrspace(1)* %A
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
@arst = addrspace(1) global [4 x i8 addrspace(2)*] zeroinitializer
|
|
|
|
|
|
|
|
define void @test_evaluate_gep_as_ptrs_array(i8 addrspace(2)* %B) {
|
|
|
|
; CHECK-LABEL: @test_evaluate_gep_as_ptrs_array(
|
|
|
|
; CHECK-NEXT: store i8 addrspace(2)* %B, i8 addrspace(2)* addrspace(1)* getelementptr inbounds ([4 x i8 addrspace(2)*] addrspace(1)* @arst, i16 0, i16 2), align 4
|
|
|
|
|
|
|
|
; CHECK-NEXT: ret void
|
|
|
|
%A = getelementptr [4 x i8 addrspace(2)*] addrspace(1)* @arst, i16 0, i16 2
|
|
|
|
store i8 addrspace(2)* %B, i8 addrspace(2)* addrspace(1)* %A
|
|
|
|
ret void
|
|
|
|
}
|
2003-03-06 06:32:48 +08:00
|
|
|
|
2009-08-31 04:48:15 +08:00
|
|
|
define i32* @test7(i32* %I, i64 %C, i64 %D) {
|
2013-08-16 07:11:07 +08:00
|
|
|
%A = getelementptr i32* %I, i64 %C
|
|
|
|
%B = getelementptr i32* %A, i64 %D
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i32* %B
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test7(
|
2009-08-31 04:48:15 +08:00
|
|
|
; CHECK: %A.sum = add i64 %C, %D
|
|
|
|
; CHECK: getelementptr i32* %I, i64 %A.sum
|
2003-03-06 06:32:48 +08:00
|
|
|
}
|
2003-06-22 06:59:39 +08:00
|
|
|
|
2009-08-31 04:48:15 +08:00
|
|
|
define i8* @test8([10 x i32]* %X) {
|
2008-03-25 12:26:08 +08:00
|
|
|
;; Fold into the cast.
|
2013-08-16 07:11:07 +08:00
|
|
|
%A = getelementptr [10 x i32]* %X, i64 0, i64 0
|
|
|
|
%B = bitcast i32* %A to i8*
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i8* %B
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test8(
|
2009-08-31 04:48:15 +08:00
|
|
|
; CHECK: bitcast [10 x i32]* %X to i8*
|
2003-06-22 06:59:39 +08:00
|
|
|
}
|
2004-10-17 03:44:23 +08:00
|
|
|
|
2008-03-25 12:26:08 +08:00
|
|
|
define i32 @test9() {
|
2009-08-31 05:31:34 +08:00
|
|
|
%A = getelementptr { i32, double }* null, i32 0, i32 1
|
2013-08-16 07:11:07 +08:00
|
|
|
%B = ptrtoint double* %A to i32
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i32 %B
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test9(
|
2009-08-31 04:48:15 +08:00
|
|
|
; CHECK: ret i32 8
|
2004-10-17 03:44:23 +08:00
|
|
|
}
|
2005-04-26 04:17:00 +08:00
|
|
|
|
2008-03-25 12:26:08 +08:00
|
|
|
define i1 @test10({ i32, i32 }* %x, { i32, i32 }* %y) {
|
2009-08-31 05:31:34 +08:00
|
|
|
%tmp.1 = getelementptr { i32, i32 }* %x, i32 0, i32 1
|
|
|
|
%tmp.3 = getelementptr { i32, i32 }* %y, i32 0, i32 1
|
2008-03-25 12:26:08 +08:00
|
|
|
;; seteq x, y
|
2013-08-16 07:11:07 +08:00
|
|
|
%tmp.4 = icmp eq i32* %tmp.1, %tmp.3
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i1 %tmp.4
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test10(
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
; CHECK: icmp eq { i32, i32 }* %x, %y
|
2005-04-26 04:17:00 +08:00
|
|
|
}
|
|
|
|
|
2008-03-25 12:26:08 +08:00
|
|
|
define i1 @test11({ i32, i32 }* %X) {
|
2013-08-16 07:11:07 +08:00
|
|
|
%P = getelementptr { i32, i32 }* %X, i32 0, i32 0
|
|
|
|
%Q = icmp eq i32* %P, null
|
2008-03-25 12:26:08 +08:00
|
|
|
ret i1 %Q
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test11(
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
; CHECK: icmp eq { i32, i32 }* %X, null
|
2005-05-01 12:41:57 +08:00
|
|
|
}
|
2009-08-31 05:02:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
; PR4748
|
|
|
|
define i32 @test12(%struct.A* %a) {
|
|
|
|
entry:
|
|
|
|
%g3 = getelementptr %struct.A* %a, i32 0, i32 1
|
|
|
|
store i32 10, i32* %g3, align 4
|
|
|
|
|
|
|
|
%g4 = getelementptr %struct.A* %a, i32 0, i32 0
|
2013-08-16 07:11:07 +08:00
|
|
|
|
2009-08-31 05:02:36 +08:00
|
|
|
%new_a = bitcast %struct.B* %g4 to %struct.A*
|
|
|
|
|
2013-08-16 07:11:07 +08:00
|
|
|
%g5 = getelementptr %struct.A* %new_a, i32 0, i32 1
|
|
|
|
%a_a = load i32* %g5, align 4
|
2009-08-31 05:02:36 +08:00
|
|
|
ret i32 %a_a
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test12(
|
2009-08-31 05:02:36 +08:00
|
|
|
; CHECK: getelementptr %struct.A* %a, i64 0, i32 1
|
|
|
|
; CHECK-NEXT: store i32 10, i32* %g3
|
|
|
|
; CHECK-NEXT: ret i32 10
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
; PR2235
|
|
|
|
%S = type { i32, [ 100 x i32] }
|
|
|
|
define i1 @test13(i64 %X, %S* %P) {
|
|
|
|
%A = getelementptr inbounds %S* %P, i32 0, i32 1, i64 %X
|
|
|
|
%B = getelementptr inbounds %S* %P, i32 0, i32 0
|
|
|
|
%C = icmp eq i32* %A, %B
|
|
|
|
ret i1 %C
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test13(
|
2009-08-31 05:02:36 +08:00
|
|
|
; CHECK: %C = icmp eq i64 %X, -1
|
|
|
|
}
|
|
|
|
|
2013-08-20 05:43:16 +08:00
|
|
|
define <2 x i1> @test13_vector(<2 x i64> %X, <2 x %S*> %P) nounwind {
|
|
|
|
; CHECK-LABEL: @test13_vector(
|
|
|
|
; CHECK-NEXT: shl nuw <2 x i64> %X, <i64 2, i64 2>
|
|
|
|
; CHECK-NEXT: add <2 x i64> %A.idx, <i64 4, i64 4>
|
|
|
|
; CHECK-NEXT: icmp eq <2 x i64> %A.offs, zeroinitializer
|
|
|
|
%A = getelementptr inbounds <2 x %S*> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, <2 x i64> %X
|
|
|
|
%B = getelementptr inbounds <2 x %S*> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0>
|
|
|
|
%C = icmp eq <2 x i32*> %A, %B
|
|
|
|
ret <2 x i1> %C
|
|
|
|
}
|
|
|
|
|
2013-08-16 07:11:07 +08:00
|
|
|
define i1 @test13_i32(i32 %X, %S* %P) {
|
|
|
|
; CHECK-LABEL: @test13_i32(
|
|
|
|
; CHECK: %C = icmp eq i32 %X, -1
|
|
|
|
%A = getelementptr inbounds %S* %P, i32 0, i32 1, i32 %X
|
|
|
|
%B = getelementptr inbounds %S* %P, i32 0, i32 0
|
|
|
|
%C = icmp eq i32* %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test13_i16(i16 %X, %S* %P) {
|
|
|
|
; CHECK-LABEL: @test13_i16(
|
|
|
|
; CHECK: %C = icmp eq i16 %X, -1
|
|
|
|
%A = getelementptr inbounds %S* %P, i16 0, i32 1, i16 %X
|
|
|
|
%B = getelementptr inbounds %S* %P, i16 0, i32 0
|
|
|
|
%C = icmp eq i32* %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test13_i128(i128 %X, %S* %P) {
|
|
|
|
; CHECK-LABEL: @test13_i128(
|
|
|
|
; CHECK: %C = icmp eq i64 %1, -1
|
|
|
|
%A = getelementptr inbounds %S* %P, i128 0, i32 1, i128 %X
|
|
|
|
%B = getelementptr inbounds %S* %P, i128 0, i32 0
|
|
|
|
%C = icmp eq i32* %A, %B
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
2009-08-31 05:02:36 +08:00
|
|
|
|
2013-08-16 07:11:07 +08:00
|
|
|
@G = external global [3 x i8]
|
2009-08-31 05:02:36 +08:00
|
|
|
define i8* @test14(i32 %Idx) {
|
2009-08-31 05:31:34 +08:00
|
|
|
%idx = zext i32 %Idx to i64
|
2009-08-31 05:02:36 +08:00
|
|
|
%tmp = getelementptr i8* getelementptr ([3 x i8]* @G, i32 0, i32 0), i64 %idx
|
|
|
|
ret i8* %tmp
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test14(
|
2009-08-31 05:02:36 +08:00
|
|
|
; CHECK: getelementptr [3 x i8]* @G, i64 0, i64 %idx
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
; Test folding of constantexpr geps into normal geps.
|
2009-08-31 05:31:34 +08:00
|
|
|
@Array = external global [40 x i32]
|
2009-08-31 05:02:36 +08:00
|
|
|
define i32 *@test15(i64 %X) {
|
|
|
|
%A = getelementptr i32* getelementptr ([40 x i32]* @Array, i64 0, i64 0), i64 %X
|
|
|
|
ret i32* %A
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test15(
|
2009-08-31 05:02:36 +08:00
|
|
|
; CHECK: getelementptr [40 x i32]* @Array, i64 0, i64 %X
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define i32* @test16(i32* %X, i32 %Idx) {
|
2013-08-16 07:11:07 +08:00
|
|
|
%R = getelementptr i32* %X, i32 %Idx
|
2009-08-31 05:02:36 +08:00
|
|
|
ret i32* %R
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test16(
|
2009-08-31 05:02:36 +08:00
|
|
|
; CHECK: sext i32 %Idx to i64
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define i1 @test17(i16* %P, i32 %I, i32 %J) {
|
|
|
|
%X = getelementptr inbounds i16* %P, i32 %I
|
|
|
|
%Y = getelementptr inbounds i16* %P, i32 %J
|
|
|
|
%C = icmp ult i16* %X, %Y
|
|
|
|
ret i1 %C
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test17(
|
2013-08-16 07:11:07 +08:00
|
|
|
; CHECK: %C = icmp slt i32 %I, %J
|
2009-08-31 05:02:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test18(i16* %P, i32 %I) {
|
|
|
|
%X = getelementptr inbounds i16* %P, i32 %I
|
|
|
|
%C = icmp ult i16* %X, %P
|
|
|
|
ret i1 %C
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test18(
|
2009-08-31 05:02:36 +08:00
|
|
|
; CHECK: %C = icmp slt i32 %I, 0
|
|
|
|
}
|
|
|
|
|
2013-08-16 07:11:07 +08:00
|
|
|
; Smaller than pointer size
|
|
|
|
define i1 @test18_i16(i16* %P, i16 %I) {
|
|
|
|
; CHECK-LABEL: @test18_i16(
|
|
|
|
; CHECK: %C = icmp slt i16 %I, 0
|
|
|
|
%X = getelementptr inbounds i16* %P, i16 %I
|
|
|
|
%C = icmp ult i16* %X, %P
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
; Same as pointer size
|
|
|
|
define i1 @test18_i64(i16* %P, i64 %I) {
|
|
|
|
; CHECK-LABEL: @test18_i64(
|
|
|
|
; CHECK: %C = icmp slt i64 %I, 0
|
|
|
|
%X = getelementptr inbounds i16* %P, i64 %I
|
|
|
|
%C = icmp ult i16* %X, %P
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
; Larger than the pointer size
|
|
|
|
define i1 @test18_i128(i16* %P, i128 %I) {
|
|
|
|
; CHECK-LABEL: @test18_i128(
|
|
|
|
; CHECK: %C = icmp slt i64 %1, 0
|
|
|
|
%X = getelementptr inbounds i16* %P, i128 %I
|
|
|
|
%C = icmp ult i16* %X, %P
|
|
|
|
ret i1 %C
|
|
|
|
}
|
|
|
|
|
2009-08-31 05:02:36 +08:00
|
|
|
define i32 @test19(i32* %P, i32 %A, i32 %B) {
|
|
|
|
%tmp.4 = getelementptr inbounds i32* %P, i32 %A
|
|
|
|
%tmp.9 = getelementptr inbounds i32* %P, i32 %B
|
|
|
|
%tmp.10 = icmp eq i32* %tmp.4, %tmp.9
|
|
|
|
%tmp.11 = zext i1 %tmp.10 to i32
|
|
|
|
ret i32 %tmp.11
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test19(
|
2009-08-31 05:02:36 +08:00
|
|
|
; CHECK: icmp eq i32 %A, %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test20(i32* %P, i32 %A, i32 %B) {
|
|
|
|
%tmp.4 = getelementptr inbounds i32* %P, i32 %A
|
|
|
|
%tmp.6 = icmp eq i32* %tmp.4, %P
|
|
|
|
%tmp.7 = zext i1 %tmp.6 to i32
|
|
|
|
ret i32 %tmp.7
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test20(
|
2009-08-31 05:02:36 +08:00
|
|
|
; CHECK: icmp eq i32 %A, 0
|
|
|
|
}
|
|
|
|
|
2013-08-21 05:20:04 +08:00
|
|
|
define i32 @test20_as1(i32 addrspace(1)* %P, i32 %A, i32 %B) {
|
|
|
|
%tmp.4 = getelementptr inbounds i32 addrspace(1)* %P, i32 %A
|
|
|
|
%tmp.6 = icmp eq i32 addrspace(1)* %tmp.4, %P
|
|
|
|
%tmp.7 = zext i1 %tmp.6 to i32
|
|
|
|
ret i32 %tmp.7
|
|
|
|
; CHECK-LABEL: @test20_as1(
|
|
|
|
; CHECK: icmp eq i16 %1, 0
|
|
|
|
}
|
|
|
|
|
2009-08-31 05:02:36 +08:00
|
|
|
|
2009-08-31 05:31:34 +08:00
|
|
|
define i32 @test21() {
|
|
|
|
%pbob1 = alloca %intstruct
|
|
|
|
%pbob2 = getelementptr %intstruct* %pbob1
|
|
|
|
%pbobel = getelementptr %intstruct* %pbob2, i64 0, i32 0
|
|
|
|
%rval = load i32* %pbobel
|
|
|
|
ret i32 %rval
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test21(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: getelementptr %intstruct* %pbob1, i64 0, i32 0
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@A = global i32 1 ; <i32*> [#uses=1]
|
|
|
|
@B = global i32 2 ; <i32*> [#uses=1]
|
|
|
|
|
|
|
|
define i1 @test22() {
|
2013-08-16 07:11:07 +08:00
|
|
|
%C = icmp ult i32* getelementptr (i32* @A, i64 1),
|
|
|
|
getelementptr (i32* @B, i64 2)
|
2009-08-31 05:31:34 +08:00
|
|
|
ret i1 %C
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test22(
|
2009-09-11 08:04:14 +08:00
|
|
|
; CHECK: icmp ult (i32* getelementptr inbounds (i32* @A, i64 1), i32* getelementptr (i32* @B, i64 2))
|
2009-08-31 05:31:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
%X = type { [10 x i32], float }
|
|
|
|
|
|
|
|
define i1 @test23() {
|
|
|
|
%A = getelementptr %X* null, i64 0, i32 0, i64 0 ; <i32*> [#uses=1]
|
|
|
|
%B = icmp ne i32* %A, null ; <i1> [#uses=1]
|
|
|
|
ret i1 %B
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test23(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: ret i1 false
|
|
|
|
}
|
|
|
|
|
|
|
|
define void @test25() {
|
|
|
|
entry:
|
|
|
|
%tmp = getelementptr { i64, i64, i64, i64 }* null, i32 0, i32 3 ; <i64*> [#uses=1]
|
|
|
|
%tmp.upgrd.1 = load i64* %tmp ; <i64> [#uses=1]
|
|
|
|
%tmp8.ui = load i64* null ; <i64> [#uses=1]
|
|
|
|
%tmp8 = bitcast i64 %tmp8.ui to i64 ; <i64> [#uses=1]
|
|
|
|
%tmp9 = and i64 %tmp8, %tmp.upgrd.1 ; <i64> [#uses=1]
|
|
|
|
%sext = trunc i64 %tmp9 to i32 ; <i32> [#uses=1]
|
|
|
|
%tmp27.i = sext i32 %sext to i64 ; <i64> [#uses=1]
|
|
|
|
tail call void @foo25( i32 0, i64 %tmp27.i )
|
|
|
|
unreachable
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test25(
|
2009-08-31 05:31:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
declare void @foo25(i32, i64)
|
|
|
|
|
|
|
|
|
|
|
|
; PR1637
|
|
|
|
define i1 @test26(i8* %arr) {
|
|
|
|
%X = getelementptr i8* %arr, i32 1
|
|
|
|
%Y = getelementptr i8* %arr, i32 1
|
|
|
|
%test = icmp uge i8* %X, %Y
|
|
|
|
ret i1 %test
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test26(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: ret i1 true
|
|
|
|
}
|
|
|
|
|
|
|
|
%struct.__large_struct = type { [100 x i64] }
|
|
|
|
%struct.compat_siginfo = type { i32, i32, i32, { [29 x i32] } }
|
|
|
|
%struct.siginfo_t = type { i32, i32, i32, { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] } }
|
|
|
|
%struct.sigval_t = type { i8* }
|
|
|
|
|
|
|
|
define i32 @test27(%struct.compat_siginfo* %to, %struct.siginfo_t* %from) {
|
|
|
|
entry:
|
2013-08-16 07:11:07 +08:00
|
|
|
%from_addr = alloca %struct.siginfo_t*
|
|
|
|
%tmp344 = load %struct.siginfo_t** %from_addr, align 8
|
2009-08-31 05:31:34 +08:00
|
|
|
%tmp345 = getelementptr %struct.siginfo_t* %tmp344, i32 0, i32 3
|
|
|
|
%tmp346 = getelementptr { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] }* %tmp345, i32 0, i32 0
|
2013-08-16 07:11:07 +08:00
|
|
|
%tmp346347 = bitcast { i32, i32, [0 x i8], %struct.sigval_t, i32 }* %tmp346 to { i32, i32, %struct.sigval_t }*
|
2009-08-31 05:31:34 +08:00
|
|
|
%tmp348 = getelementptr { i32, i32, %struct.sigval_t }* %tmp346347, i32 0, i32 2
|
|
|
|
%tmp349 = getelementptr %struct.sigval_t* %tmp348, i32 0, i32 0
|
|
|
|
%tmp349350 = bitcast i8** %tmp349 to i32*
|
2013-08-16 07:11:07 +08:00
|
|
|
%tmp351 = load i32* %tmp349350, align 8
|
2009-08-31 05:31:34 +08:00
|
|
|
%tmp360 = call i32 asm sideeffect "...",
|
|
|
|
"=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"( i32 %tmp351,
|
|
|
|
%struct.__large_struct* null, i32 -14, i32 0 )
|
|
|
|
unreachable
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test27(
|
2009-08-31 05:31:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
; PR1978
|
|
|
|
%struct.x = type <{ i8 }>
|
2013-08-16 07:11:07 +08:00
|
|
|
@.str = internal constant [6 x i8] c"Main!\00"
|
|
|
|
@.str1 = internal constant [12 x i8] c"destroy %p\0A\00"
|
2009-08-31 05:31:34 +08:00
|
|
|
|
|
|
|
define i32 @test28() nounwind {
|
|
|
|
entry:
|
|
|
|
%orientations = alloca [1 x [1 x %struct.x]]
|
2013-08-16 07:11:07 +08:00
|
|
|
%tmp3 = call i32 @puts( i8* getelementptr ([6 x i8]* @.str, i32 0, i32 0) ) nounwind
|
2009-08-31 05:31:34 +08:00
|
|
|
%tmp45 = getelementptr inbounds [1 x [1 x %struct.x]]* %orientations, i32 1, i32 0, i32 0
|
|
|
|
%orientations62 = getelementptr [1 x [1 x %struct.x]]* %orientations, i32 0, i32 0, i32 0
|
|
|
|
br label %bb10
|
|
|
|
|
|
|
|
bb10:
|
|
|
|
%indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb10 ]
|
2013-08-16 07:11:07 +08:00
|
|
|
%tmp.0.reg2mem.0.rec = mul i32 %indvar, -1
|
|
|
|
%tmp12.rec = add i32 %tmp.0.reg2mem.0.rec, -1
|
2009-08-31 05:31:34 +08:00
|
|
|
%tmp12 = getelementptr inbounds %struct.x* %tmp45, i32 %tmp12.rec
|
|
|
|
%tmp16 = call i32 (i8*, ...)* @printf( i8* getelementptr ([12 x i8]* @.str1, i32 0, i32 0), %struct.x* %tmp12 ) nounwind
|
|
|
|
%tmp84 = icmp eq %struct.x* %tmp12, %orientations62
|
|
|
|
%indvar.next = add i32 %indvar, 1
|
|
|
|
br i1 %tmp84, label %bb17, label %bb10
|
|
|
|
|
2013-08-16 07:11:07 +08:00
|
|
|
bb17:
|
2009-08-31 05:31:34 +08:00
|
|
|
ret i32 0
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test28(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: icmp eq i32 %indvar, 0
|
|
|
|
}
|
|
|
|
|
|
|
|
declare i32 @puts(i8*)
|
|
|
|
|
|
|
|
declare i32 @printf(i8*, ...)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; rdar://6762290
|
|
|
|
%T = type <{ i64, i64, i64 }>
|
|
|
|
define i32 @test29(i8* %start, i32 %X) nounwind {
|
|
|
|
entry:
|
2013-08-16 07:11:07 +08:00
|
|
|
%tmp3 = load i64* null
|
2009-08-31 05:31:34 +08:00
|
|
|
%add.ptr = getelementptr i8* %start, i64 %tmp3
|
|
|
|
%tmp158 = load i32* null
|
|
|
|
%add.ptr159 = getelementptr %T* null, i32 %tmp158
|
|
|
|
%add.ptr209 = getelementptr i8* %start, i64 0
|
|
|
|
%add.ptr212 = getelementptr i8* %add.ptr209, i32 %X
|
|
|
|
%cmp214 = icmp ugt i8* %add.ptr212, %add.ptr
|
|
|
|
br i1 %cmp214, label %if.then216, label %if.end363
|
|
|
|
|
|
|
|
if.then216:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
if.end363:
|
|
|
|
ret i32 0
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test29(
|
2009-08-31 05:31:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
; PR3694
|
|
|
|
define i32 @test30(i32 %m, i32 %n) nounwind {
|
|
|
|
entry:
|
|
|
|
%0 = alloca i32, i32 %n, align 4
|
|
|
|
%1 = bitcast i32* %0 to [0 x i32]*
|
|
|
|
call void @test30f(i32* %0) nounwind
|
|
|
|
%2 = getelementptr [0 x i32]* %1, i32 0, i32 %m
|
|
|
|
%3 = load i32* %2, align 4
|
|
|
|
ret i32 %3
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test30(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: getelementptr i32
|
|
|
|
}
|
|
|
|
|
|
|
|
declare void @test30f(i32*)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
define i1 @test31(i32* %A) {
|
|
|
|
%B = getelementptr i32* %A, i32 1
|
|
|
|
%C = getelementptr i32* %A, i64 1
|
2013-08-16 07:11:07 +08:00
|
|
|
%V = icmp eq i32* %B, %C
|
2009-08-31 05:31:34 +08:00
|
|
|
ret i1 %V
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test31(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: ret i1 true
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
; PR1345
|
|
|
|
define i8* @test32(i8* %v) {
|
|
|
|
%A = alloca [4 x i8*], align 16
|
|
|
|
%B = getelementptr [4 x i8*]* %A, i32 0, i32 0
|
|
|
|
store i8* null, i8** %B
|
|
|
|
%C = bitcast [4 x i8*]* %A to { [16 x i8] }*
|
|
|
|
%D = getelementptr { [16 x i8] }* %C, i32 0, i32 0, i32 8
|
|
|
|
%E = bitcast i8* %D to i8**
|
|
|
|
store i8* %v, i8** %E
|
2013-08-16 07:11:07 +08:00
|
|
|
%F = getelementptr [4 x i8*]* %A, i32 0, i32 2
|
2009-08-31 05:31:34 +08:00
|
|
|
%G = load i8** %F
|
|
|
|
ret i8* %G
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test32(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: %D = getelementptr [4 x i8*]* %A, i64 0, i64 1
|
|
|
|
; CHECK: %F = getelementptr [4 x i8*]* %A, i64 0, i64 2
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR3290
|
|
|
|
%struct.Key = type { { i32, i32 } }
|
|
|
|
%struct.anon = type <{ i8, [3 x i8], i32 }>
|
|
|
|
|
|
|
|
define i32 *@test33(%struct.Key *%A) {
|
|
|
|
%B = bitcast %struct.Key* %A to %struct.anon*
|
2013-08-16 07:11:07 +08:00
|
|
|
%C = getelementptr %struct.anon* %B, i32 0, i32 2
|
2009-08-31 05:31:34 +08:00
|
|
|
ret i32 *%C
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test33(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: getelementptr %struct.Key* %A, i64 0, i32 0, i32 1
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
%T2 = type { i8*, i8 }
|
|
|
|
define i8* @test34(i8* %Val, i64 %V) nounwind {
|
|
|
|
entry:
|
2013-08-16 07:11:07 +08:00
|
|
|
%A = alloca %T2, align 8
|
2009-08-31 05:31:34 +08:00
|
|
|
%mrv_gep = bitcast %T2* %A to i64*
|
|
|
|
%B = getelementptr %T2* %A, i64 0, i32 0
|
2013-08-16 07:11:07 +08:00
|
|
|
|
2009-08-31 05:31:34 +08:00
|
|
|
store i64 %V, i64* %mrv_gep
|
|
|
|
%C = load i8** %B, align 8
|
|
|
|
ret i8* %C
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test34(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: %V.c = inttoptr i64 %V to i8*
|
|
|
|
; CHECK: ret i8* %V.c
|
|
|
|
}
|
|
|
|
|
|
|
|
%t0 = type { i8*, [19 x i8] }
|
|
|
|
%t1 = type { i8*, [0 x i8] }
|
|
|
|
|
|
|
|
@array = external global [11 x i8]
|
|
|
|
|
|
|
|
@s = external global %t0
|
|
|
|
@"\01LC8" = external constant [17 x i8]
|
|
|
|
|
|
|
|
; Instcombine should be able to fold this getelementptr.
|
|
|
|
|
|
|
|
define i32 @test35() nounwind {
|
|
|
|
call i32 (i8*, ...)* @printf(i8* getelementptr ([17 x i8]* @"\01LC8", i32 0, i32 0),
|
|
|
|
i8* getelementptr (%t1* bitcast (%t0* @s to %t1*), i32 0, i32 1, i32 0)) nounwind
|
|
|
|
ret i32 0
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test35(
|
2013-02-22 17:09:42 +08:00
|
|
|
; CHECK: call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([17 x i8]* @"\01LC8", i64 0, i64 0), i8* getelementptr inbounds (%t0* @s, i64 0, i32 1, i64 0)) [[NUW:#[0-9]+]]
|
2009-08-31 05:31:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
; Instcombine should constant-fold the GEP so that indices that have
|
|
|
|
; static array extents are within bounds of those array extents.
|
|
|
|
; In the below, -1 is not in the range [0,11). After the transformation,
|
|
|
|
; the same address is computed, but 3 is in the range of [0,11).
|
|
|
|
|
|
|
|
define i8* @test36() nounwind {
|
|
|
|
ret i8* getelementptr ([11 x i8]* @array, i32 0, i64 -1)
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test36(
|
2009-08-31 05:31:34 +08:00
|
|
|
; CHECK: ret i8* getelementptr ([11 x i8]* @array, i64 1676976733973595601, i64 4)
|
|
|
|
}
|
2009-08-31 05:02:36 +08:00
|
|
|
|
2009-09-11 07:37:55 +08:00
|
|
|
; Instcombine shouldn't assume that gep(A,0,1) != gep(A,1,0).
|
|
|
|
@A37 = external constant [1 x i8]
|
|
|
|
define i1 @test37() nounwind {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test37(
|
2009-09-11 08:04:14 +08:00
|
|
|
; CHECK: ret i1 true
|
2009-09-11 07:37:55 +08:00
|
|
|
%t = icmp eq i8* getelementptr ([1 x i8]* @A37, i64 0, i64 1),
|
|
|
|
getelementptr ([1 x i8]* @A37, i64 1, i64 0)
|
|
|
|
ret i1 %t
|
|
|
|
}
|
2010-05-28 23:07:59 +08:00
|
|
|
|
|
|
|
; Test index promotion
|
|
|
|
define i32* @test38(i32* %I, i32 %n) {
|
|
|
|
%A = getelementptr i32* %I, i32 %n
|
|
|
|
ret i32* %A
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test38(
|
2010-05-28 23:07:59 +08:00
|
|
|
; CHECK: = sext i32 %n to i64
|
|
|
|
; CHECK: %A = getelementptr i32* %I, i64 %
|
|
|
|
}
|
2011-07-11 11:43:47 +08:00
|
|
|
|
|
|
|
; Test that we don't duplicate work when the second gep is a "bitcast".
|
|
|
|
%pr10322_t = type { i8* }
|
|
|
|
declare void @pr10322_f2(%pr10322_t*)
|
|
|
|
declare void @pr10322_f3(i8**)
|
|
|
|
define void @pr10322_f1(%pr10322_t* %foo) {
|
|
|
|
entry:
|
|
|
|
%arrayidx8 = getelementptr inbounds %pr10322_t* %foo, i64 2
|
|
|
|
call void @pr10322_f2(%pr10322_t* %arrayidx8) nounwind
|
|
|
|
%tmp2 = getelementptr inbounds %pr10322_t* %arrayidx8, i64 0, i32 0
|
|
|
|
call void @pr10322_f3(i8** %tmp2) nounwind
|
|
|
|
ret void
|
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @pr10322_f1(
|
2011-07-11 11:43:47 +08:00
|
|
|
; CHECK: %tmp2 = getelementptr inbounds %pr10322_t* %arrayidx8, i64 0, i32 0
|
|
|
|
}
|
2011-07-31 12:43:41 +08:00
|
|
|
|
|
|
|
; Test that we combine the last two geps in this sequence, before we
|
|
|
|
; would wait for gep1 and gep2 to be combined and never combine 2 and 3.
|
|
|
|
%three_gep_t = type {i32}
|
|
|
|
%three_gep_t2 = type {%three_gep_t}
|
|
|
|
|
|
|
|
define void @three_gep_f(%three_gep_t2* %x) {
|
|
|
|
%gep1 = getelementptr %three_gep_t2* %x, i64 2
|
|
|
|
call void @three_gep_h(%three_gep_t2* %gep1)
|
|
|
|
%gep2 = getelementptr %three_gep_t2* %gep1, i64 0, i32 0
|
|
|
|
%gep3 = getelementptr %three_gep_t* %gep2, i64 0, i32 0
|
|
|
|
call void @three_gep_g(i32* %gep3)
|
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @three_gep_f(
|
2011-07-31 12:43:41 +08:00
|
|
|
; CHECK: %gep3 = getelementptr %three_gep_t2* %gep1, i64 0, i32 0, i32 0
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
declare void @three_gep_g(i32*)
|
|
|
|
declare void @three_gep_h(%three_gep_t2*)
|
2013-01-24 01:52:29 +08:00
|
|
|
|
|
|
|
%struct.ham = type { i32, %struct.zot*, %struct.zot*, %struct.zot* }
|
|
|
|
%struct.zot = type { i64, i8 }
|
|
|
|
|
|
|
|
define void @test39(%struct.ham* %arg, i8 %arg1) nounwind {
|
|
|
|
%tmp = getelementptr inbounds %struct.ham* %arg, i64 0, i32 2
|
|
|
|
%tmp2 = load %struct.zot** %tmp, align 8
|
|
|
|
%tmp3 = bitcast %struct.zot* %tmp2 to i8*
|
|
|
|
%tmp4 = getelementptr inbounds i8* %tmp3, i64 -8
|
|
|
|
store i8 %arg1, i8* %tmp4, align 8
|
|
|
|
ret void
|
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test39(
|
2013-01-24 01:52:29 +08:00
|
|
|
; CHECK: getelementptr inbounds %struct.ham* %arg, i64 0, i32 2
|
|
|
|
; CHECK: getelementptr inbounds i8* %tmp3, i64 -8
|
|
|
|
}
|
2013-02-22 17:09:42 +08:00
|
|
|
|
InstCombine: FoldGEPICmp shouldn't change sign of base pointer comparison
Changing the sign when comparing the base pointer would introduce all
sorts of unexpected things like:
%gep.i = getelementptr inbounds [1 x i8]* %a, i32 0, i32 0
%gep2.i = getelementptr inbounds [1 x i8]* %b, i32 0, i32 0
%cmp.i = icmp ult i8* %gep.i, %gep2.i
%cmp.i1 = icmp ult [1 x i8]* %a, %b
%cmp = icmp ne i1 %cmp.i, %cmp.i1
ret i1 %cmp
into:
%cmp.i = icmp slt [1 x i8]* %a, %b
%cmp.i1 = icmp ult [1 x i8]* %a, %b
%cmp = xor i1 %cmp.i, %cmp.i1
ret i1 %cmp
By preserving the original sign, we now get:
ret i1 false
This fixes PR16483.
llvm-svn: 185259
2013-06-29 18:28:04 +08:00
|
|
|
define i1 @pr16483([1 x i8]* %a, [1 x i8]* %b) {
|
|
|
|
%c = getelementptr [1 x i8]* %a, i32 0, i32 0
|
|
|
|
%d = getelementptr [1 x i8]* %b, i32 0, i32 0
|
|
|
|
%cmp = icmp ult i8* %c, %d
|
|
|
|
ret i1 %cmp
|
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @pr16483(
|
InstCombine: FoldGEPICmp shouldn't change sign of base pointer comparison
Changing the sign when comparing the base pointer would introduce all
sorts of unexpected things like:
%gep.i = getelementptr inbounds [1 x i8]* %a, i32 0, i32 0
%gep2.i = getelementptr inbounds [1 x i8]* %b, i32 0, i32 0
%cmp.i = icmp ult i8* %gep.i, %gep2.i
%cmp.i1 = icmp ult [1 x i8]* %a, %b
%cmp = icmp ne i1 %cmp.i, %cmp.i1
ret i1 %cmp
into:
%cmp.i = icmp slt [1 x i8]* %a, %b
%cmp.i1 = icmp ult [1 x i8]* %a, %b
%cmp = xor i1 %cmp.i, %cmp.i1
ret i1 %cmp
By preserving the original sign, we now get:
ret i1 false
This fixes PR16483.
llvm-svn: 185259
2013-06-29 18:28:04 +08:00
|
|
|
; CHECK-NEXT: icmp ult [1 x i8]* %a, %b
|
|
|
|
}
|
|
|
|
|
2013-08-16 10:59:17 +08:00
|
|
|
; The element size of the array matches the element size of the pointer
|
|
|
|
define i64 @test_gep_bitcast_array_same_size_element([100 x double]* %arr, i64 %N) {
|
|
|
|
; CHECK-LABEL: @test_gep_bitcast_array_same_size_element(
|
|
|
|
; CHECK: getelementptr [100 x double]* %arr, i64 0, i64 %V
|
|
|
|
; CHECK: bitcast
|
|
|
|
%cast = bitcast [100 x double]* %arr to i64*
|
|
|
|
%V = mul i64 %N, 8
|
|
|
|
%t = getelementptr i64* %cast, i64 %V
|
|
|
|
%x = load i64* %t
|
|
|
|
ret i64 %x
|
|
|
|
}
|
|
|
|
|
|
|
|
; The element size of the array is different the element size of the pointer
|
|
|
|
define i8 @test_gep_bitcast_array_different_size_element([100 x double]* %arr, i64 %N) {
|
|
|
|
; CHECK-LABEL: @test_gep_bitcast_array_different_size_element(
|
|
|
|
; CHECK: getelementptr [100 x double]* %arr, i64 0, i64 %N
|
|
|
|
; CHECK: bitcast
|
|
|
|
%cast = bitcast [100 x double]* %arr to i8*
|
|
|
|
%V = mul i64 %N, 8
|
|
|
|
%t = getelementptr i8* %cast, i64 %V
|
|
|
|
%x = load i8* %t
|
|
|
|
ret i8 %x
|
|
|
|
}
|
|
|
|
|
2013-08-22 03:09:28 +08:00
|
|
|
define i64 @test_gep_bitcast_array_same_size_element_as1([100 x double] addrspace(1)* %arr, i16 %N) {
|
|
|
|
; CHECK-LABEL: @test_gep_bitcast_array_same_size_element_as1(
|
|
|
|
; CHECK: getelementptr [100 x double] addrspace(1)* %arr, i16 0, i16 %V
|
|
|
|
; CHECK: bitcast
|
|
|
|
%cast = bitcast [100 x double] addrspace(1)* %arr to i64 addrspace(1)*
|
|
|
|
%V = mul i16 %N, 8
|
|
|
|
%t = getelementptr i64 addrspace(1)* %cast, i16 %V
|
|
|
|
%x = load i64 addrspace(1)* %t
|
|
|
|
ret i64 %x
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test_gep_bitcast_array_different_size_element_as1([100 x double] addrspace(1)* %arr, i16 %N) {
|
|
|
|
; CHECK-LABEL: @test_gep_bitcast_array_different_size_element_as1(
|
|
|
|
; CHECK: getelementptr [100 x double] addrspace(1)* %arr, i16 0, i16 %N
|
|
|
|
; CHECK: bitcast
|
|
|
|
%cast = bitcast [100 x double] addrspace(1)* %arr to i8 addrspace(1)*
|
|
|
|
%V = mul i16 %N, 8
|
|
|
|
%t = getelementptr i8 addrspace(1)* %cast, i16 %V
|
|
|
|
%x = load i8 addrspace(1)* %t
|
|
|
|
ret i8 %x
|
|
|
|
}
|
|
|
|
|
2013-02-22 17:09:42 +08:00
|
|
|
; CHECK: attributes [[NUW]] = { nounwind }
|