Sanjoy Das | a085cfc | 2016-04-21 19:26:45 +0000 | [diff] [blame] | 1 | ; RUN: opt -instcombine -S < %s | FileCheck %s |
| 2 | |
| 3 | @gp = global i32* null, align 8 |
| 4 | |
| 5 | declare i8* @malloc(i64) #1 |
| 6 | |
| 7 | define i1 @compare_global_trivialeq() { |
| 8 | %m = call i8* @malloc(i64 4) |
| 9 | %bc = bitcast i8* %m to i32* |
| 10 | %lgp = load i32*, i32** @gp, align 8 |
| 11 | %cmp = icmp eq i32* %bc, %lgp |
| 12 | ret i1 %cmp |
| 13 | ; CHECK-LABEL: compare_global_trivialeq |
| 14 | ; CHECK: ret i1 false |
| 15 | } |
| 16 | |
| 17 | define i1 @compare_global_trivialne() { |
| 18 | %m = call i8* @malloc(i64 4) |
| 19 | %bc = bitcast i8* %m to i32* |
| 20 | %lgp = load i32*, i32** @gp, align 8 |
| 21 | %cmp = icmp ne i32* %bc, %lgp |
| 22 | ret i1 %cmp |
| 23 | ; CHECK-LABEL: compare_global_trivialne |
Anna Thomas | 43d7e1c | 2016-05-03 14:58:21 +0000 | [diff] [blame] | 24 | ; CHECK: ret i1 true |
Sanjoy Das | a085cfc | 2016-04-21 19:26:45 +0000 | [diff] [blame] | 25 | } |
| 26 | |
| 27 | |
| 28 | ; Although the %m is marked nocapture in the deopt operand in call to function f, |
| 29 | ; we cannot remove the alloc site: call to malloc |
Anna Thomas | 43d7e1c | 2016-05-03 14:58:21 +0000 | [diff] [blame] | 30 | ; The comparison should fold to false irrespective of whether the call to malloc can be elided or not |
Sanjoy Das | a085cfc | 2016-04-21 19:26:45 +0000 | [diff] [blame] | 31 | declare void @f() |
Anna Thomas | 43d7e1c | 2016-05-03 14:58:21 +0000 | [diff] [blame] | 32 | define i1 @compare_and_call_with_deopt() { |
Sanjoy Das | a085cfc | 2016-04-21 19:26:45 +0000 | [diff] [blame] | 33 | ; CHECK-LABEL: compare_and_call_with_deopt |
| 34 | %m = call i8* @malloc(i64 24) |
| 35 | %bc = bitcast i8* %m to i32* |
Anna Thomas | 43d7e1c | 2016-05-03 14:58:21 +0000 | [diff] [blame] | 36 | %lgp = load i32*, i32** @gp, align 8, !nonnull !0 |
| 37 | %cmp = icmp eq i32* %lgp, %bc |
Sanjoy Das | a085cfc | 2016-04-21 19:26:45 +0000 | [diff] [blame] | 38 | tail call void @f() [ "deopt"(i8* %m) ] |
Anna Thomas | 43d7e1c | 2016-05-03 14:58:21 +0000 | [diff] [blame] | 39 | ret i1 %cmp |
| 40 | ; CHECK: ret i1 false |
| 41 | } |
| 42 | |
| 43 | ; Same functon as above with deopt operand in function f, but comparison is NE |
| 44 | define i1 @compare_ne_and_call_with_deopt() { |
| 45 | ; CHECK-LABEL: compare_ne_and_call_with_deopt |
| 46 | %m = call i8* @malloc(i64 24) |
| 47 | %bc = bitcast i8* %m to i32* |
| 48 | %lgp = load i32*, i32** @gp, align 8, !nonnull !0 |
| 49 | %cmp = icmp ne i32* %lgp, %bc |
| 50 | tail call void @f() [ "deopt"(i8* %m) ] |
| 51 | ret i1 %cmp |
| 52 | ; CHECK: ret i1 true |
| 53 | } |
| 54 | |
| 55 | ; Same function as above, but global not marked nonnull, and we cannot fold the comparison |
| 56 | define i1 @compare_ne_global_maybe_null() { |
| 57 | ; CHECK-LABEL: compare_ne_global_maybe_null |
| 58 | %m = call i8* @malloc(i64 24) |
| 59 | %bc = bitcast i8* %m to i32* |
| 60 | %lgp = load i32*, i32** @gp |
| 61 | %cmp = icmp ne i32* %lgp, %bc |
| 62 | tail call void @f() [ "deopt"(i8* %m) ] |
| 63 | ret i1 %cmp |
| 64 | ; CHECK: ret i1 %cmp |
| 65 | } |
| 66 | |
| 67 | ; FIXME: The comparison should fold to false since %m escapes (call to function escape) |
| 68 | ; after the comparison. |
| 69 | declare void @escape(i8*) |
| 70 | define i1 @compare_and_call_after() { |
| 71 | ; CHECK-LABEL: compare_and_call_after |
| 72 | %m = call i8* @malloc(i64 24) |
| 73 | %bc = bitcast i8* %m to i32* |
| 74 | %lgp = load i32*, i32** @gp, align 8, !nonnull !0 |
| 75 | %cmp = icmp eq i32* %bc, %lgp |
| 76 | br i1 %cmp, label %escape_call, label %just_return |
| 77 | |
| 78 | escape_call: |
| 79 | call void @escape(i8* %m) |
| 80 | ret i1 true |
| 81 | |
| 82 | just_return: |
| 83 | ret i1 %cmp |
Sanjoy Das | a085cfc | 2016-04-21 19:26:45 +0000 | [diff] [blame] | 84 | } |
Sanjoy Das | f97229d | 2016-04-22 20:52:25 +0000 | [diff] [blame] | 85 | |
| 86 | define i1 @compare_distinct_mallocs() { |
| 87 | %m = call i8* @malloc(i64 4) |
| 88 | %n = call i8* @malloc(i64 4) |
| 89 | %cmp = icmp eq i8* %m, %n |
| 90 | ret i1 %cmp |
| 91 | ; CHECK-LABEL: compare_distinct_mallocs |
| 92 | ; CHECK: ret i1 false |
| 93 | } |
| 94 | |
| 95 | ; the compare is folded to true since the folding compare looks through bitcasts. |
| 96 | ; call to malloc and the bitcast instructions are elided after that since there are no uses of the malloc |
| 97 | define i1 @compare_samepointer_under_bitcast() { |
| 98 | %m = call i8* @malloc(i64 4) |
| 99 | %bc = bitcast i8* %m to i32* |
| 100 | %bcback = bitcast i32* %bc to i8* |
| 101 | %cmp = icmp eq i8* %m, %bcback |
| 102 | ret i1 %cmp |
| 103 | ; CHECK-LABEL: compare_samepointer_under_bitcast |
| 104 | ; CHECK: ret i1 true |
| 105 | } |
| 106 | |
| 107 | ; the compare is folded to true since the folding compare looks through bitcasts. |
Anna Thomas | 43d7e1c | 2016-05-03 14:58:21 +0000 | [diff] [blame] | 108 | ; The malloc call for %m cannot be elided since it is used in the call to function f. |
Sanjoy Das | f97229d | 2016-04-22 20:52:25 +0000 | [diff] [blame] | 109 | define i1 @compare_samepointer_escaped() { |
| 110 | %m = call i8* @malloc(i64 4) |
| 111 | %bc = bitcast i8* %m to i32* |
| 112 | %bcback = bitcast i32* %bc to i8* |
| 113 | %cmp = icmp eq i8* %m, %bcback |
| 114 | call void @f() [ "deopt"(i8* %m) ] |
| 115 | ret i1 %cmp |
| 116 | ; CHECK-LABEL: compare_samepointer_escaped |
| 117 | ; CHECK-NEXT: %m = call i8* @malloc(i64 4) |
| 118 | ; CHECK-NEXT: call void @f() [ "deopt"(i8* %m) ] |
| 119 | ; CHECK: ret i1 true |
| 120 | } |
| 121 | |
Anna Thomas | 43d7e1c | 2016-05-03 14:58:21 +0000 | [diff] [blame] | 122 | ; Technically, we can fold the %cmp2 comparison, even though %m escapes through |
| 123 | ; the ret statement since `ret` terminates the function and we cannot reach from |
| 124 | ; the ret to cmp. |
| 125 | ; FIXME: Folding this %cmp2 when %m escapes through ret could be an issue with |
| 126 | ; cross-threading data dependencies since we do not make the distinction between |
| 127 | ; atomic and non-atomic loads in capture tracking. |
| 128 | define i8* @compare_ret_escape(i8* %c) { |
| 129 | %m = call i8* @malloc(i64 4) |
| 130 | %n = call i8* @malloc(i64 4) |
| 131 | %cmp = icmp eq i8* %n, %c |
| 132 | br i1 %cmp, label %retst, label %chk |
| 133 | |
| 134 | retst: |
| 135 | ret i8* %m |
| 136 | |
| 137 | chk: |
| 138 | %bc = bitcast i8* %m to i32* |
| 139 | %lgp = load i32*, i32** @gp, align 8, !nonnull !0 |
| 140 | %cmp2 = icmp eq i32* %bc, %lgp |
| 141 | br i1 %cmp2, label %retst, label %chk2 |
| 142 | |
| 143 | chk2: |
| 144 | ret i8* %n |
| 145 | ; CHECK-LABEL: compare_ret_escape |
| 146 | ; CHECK: %cmp = icmp eq i8* %n, %c |
| 147 | ; CHECK: %cmp2 = icmp eq i32* %bc, %lgp |
| 148 | } |
| 149 | |
Sanjoy Das | f97229d | 2016-04-22 20:52:25 +0000 | [diff] [blame] | 150 | ; The malloc call for %m cannot be elided since it is used in the call to function f. |
| 151 | ; However, the cmp can be folded to true as %n doesnt escape and %m, %n are distinct allocations |
| 152 | define i1 @compare_distinct_pointer_escape() { |
| 153 | %m = call i8* @malloc(i64 4) |
| 154 | %n = call i8* @malloc(i64 4) |
| 155 | tail call void @f() [ "deopt"(i8* %m) ] |
| 156 | %cmp = icmp ne i8* %m, %n |
| 157 | ret i1 %cmp |
| 158 | ; CHECK-LABEL: compare_distinct_pointer_escape |
| 159 | ; CHECK-NEXT: %m = call i8* @malloc(i64 4) |
| 160 | ; CHECK-NEXT: tail call void @f() [ "deopt"(i8* %m) ] |
| 161 | ; CHECK-NEXT: ret i1 true |
| 162 | } |
Anna Thomas | 43d7e1c | 2016-05-03 14:58:21 +0000 | [diff] [blame] | 163 | |
| 164 | !0 = !{} |