| Benjamin Kramer | 691363e | 2015-03-21 15:36:21 +0000 | [diff] [blame] | 1 | ; Test that the memchr library call simplifier works correctly. | 
|  | 2 | ; RUN: opt < %s -instcombine -S | FileCheck %s | 
|  | 3 |  | 
| Benjamin Kramer | 7857d72 | 2015-03-21 21:09:33 +0000 | [diff] [blame] | 4 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" | 
| Benjamin Kramer | 691363e | 2015-03-21 15:36:21 +0000 | [diff] [blame] | 5 |  | 
|  | 6 | @hello = constant [14 x i8] c"hello world\5Cn\00" | 
|  | 7 | @hellonull = constant [14 x i8] c"hello\00world\5Cn\00" | 
|  | 8 | @null = constant [1 x i8] zeroinitializer | 
| Benjamin Kramer | 7857d72 | 2015-03-21 21:09:33 +0000 | [diff] [blame] | 9 | @newlines = constant [3 x i8] c"\0D\0A\00" | 
|  | 10 | @single = constant [2 x i8] c"\1F\00" | 
|  | 11 | @spaces = constant [4 x i8] c" \0D\0A\00" | 
| Benjamin Kramer | d6aa0ec | 2015-03-21 22:04:26 +0000 | [diff] [blame] | 12 | @negative = constant [3 x i8] c"\FF\FE\00" | 
| Benjamin Kramer | 691363e | 2015-03-21 15:36:21 +0000 | [diff] [blame] | 13 | @chp = global i8* zeroinitializer | 
|  | 14 |  | 
|  | 15 | declare i8* @memchr(i8*, i32, i32) | 
|  | 16 |  | 
|  | 17 | define void @test1() { | 
|  | 18 | ; CHECK-LABEL: @test1 | 
|  | 19 | ; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 6) | 
|  | 20 | ; CHECK-NOT: call i8* @memchr | 
|  | 21 | ; CHECK: ret void | 
|  | 22 |  | 
|  | 23 | %str = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 | 
|  | 24 | %dst = call i8* @memchr(i8* %str, i32 119, i32 14) | 
|  | 25 | store i8* %dst, i8** @chp | 
|  | 26 | ret void | 
|  | 27 | } | 
|  | 28 |  | 
|  | 29 | define void @test2() { | 
|  | 30 | ; CHECK-LABEL: @test2 | 
|  | 31 | ; CHECK: store i8* null, i8** @chp, align 4 | 
|  | 32 | ; CHECK-NOT: call i8* @memchr | 
|  | 33 | ; CHECK: ret void | 
|  | 34 |  | 
|  | 35 | %str = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 | 
|  | 36 | %dst = call i8* @memchr(i8* %str, i32 119, i32 1) | 
|  | 37 | store i8* %dst, i8** @chp | 
|  | 38 | ret void | 
|  | 39 | } | 
|  | 40 |  | 
|  | 41 | define void @test3() { | 
|  | 42 | ; CHECK-LABEL: @test3 | 
|  | 43 | ; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13) | 
|  | 44 | ; CHECK-NOT: call i8* @memchr | 
|  | 45 | ; CHECK: ret void | 
|  | 46 |  | 
|  | 47 | %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 | 
|  | 48 | %dst = call i8* @memchr(i8* %src, i32 0, i32 14) | 
|  | 49 | store i8* %dst, i8** @chp | 
|  | 50 | ret void | 
|  | 51 | } | 
|  | 52 |  | 
|  | 53 | define void @test4(i32 %chr) { | 
|  | 54 | ; CHECK-LABEL: @test4 | 
|  | 55 | ; CHECK: call i8* @memchr | 
|  | 56 | ; CHECK-NOT: call i8* @memchr | 
|  | 57 | ; CHECK: ret void | 
|  | 58 |  | 
|  | 59 | %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 | 
|  | 60 | %dst = call i8* @memchr(i8* %src, i32 %chr, i32 14) | 
|  | 61 | store i8* %dst, i8** @chp | 
|  | 62 | ret void | 
|  | 63 | } | 
|  | 64 |  | 
|  | 65 | define void @test5() { | 
|  | 66 | ; CHECK-LABEL: @test5 | 
|  | 67 | ; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13) | 
|  | 68 | ; CHECK-NOT: call i8* @memchr | 
|  | 69 | ; CHECK: ret void | 
|  | 70 |  | 
|  | 71 | %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 | 
|  | 72 | %dst = call i8* @memchr(i8* %src, i32 65280, i32 14) | 
|  | 73 | store i8* %dst, i8** @chp | 
|  | 74 | ret void | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | define void @test6() { | 
|  | 78 | ; CHECK-LABEL: @test6 | 
|  | 79 | ; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 6) | 
|  | 80 | ; CHECK-NOT: call i8* @memchr | 
|  | 81 | ; CHECK: ret void | 
|  | 82 |  | 
|  | 83 | %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 | 
|  | 84 | ; Overflow, but we still find the right thing. | 
|  | 85 | %dst = call i8* @memchr(i8* %src, i32 119, i32 100) | 
|  | 86 | store i8* %dst, i8** @chp | 
|  | 87 | ret void | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | define void @test7() { | 
|  | 91 | ; CHECK-LABEL: @test7 | 
|  | 92 | ; CHECK: store i8* null, i8** @chp, align 4 | 
|  | 93 | ; CHECK-NOT: call i8* @memchr | 
|  | 94 | ; CHECK: ret void | 
|  | 95 |  | 
|  | 96 | %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 | 
|  | 97 | ; Overflow | 
|  | 98 | %dst = call i8* @memchr(i8* %src, i32 120, i32 100) | 
|  | 99 | store i8* %dst, i8** @chp | 
|  | 100 | ret void | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | define void @test8() { | 
|  | 104 | ; CHECK-LABEL: @test8 | 
|  | 105 | ; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hellonull, i32 0, i32 6) | 
|  | 106 | ; CHECK-NOT: call i8* @memchr | 
|  | 107 | ; CHECK: ret void | 
|  | 108 |  | 
|  | 109 | %str = getelementptr [14 x i8], [14 x i8]* @hellonull, i32 0, i32 0 | 
|  | 110 | %dst = call i8* @memchr(i8* %str, i32 119, i32 14) | 
|  | 111 | store i8* %dst, i8** @chp | 
|  | 112 | ret void | 
|  | 113 | } | 
|  | 114 |  | 
|  | 115 | define void @test9() { | 
|  | 116 | ; CHECK-LABEL: @test9 | 
|  | 117 | ; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hellonull, i32 0, i32 6) | 
|  | 118 | ; CHECK-NOT: call i8* @memchr | 
|  | 119 | ; CHECK: ret void | 
|  | 120 |  | 
|  | 121 | %str = getelementptr [14 x i8], [14 x i8]* @hellonull, i32 0, i32 2 | 
|  | 122 | %dst = call i8* @memchr(i8* %str, i32 119, i32 12) | 
|  | 123 | store i8* %dst, i8** @chp | 
|  | 124 | ret void | 
|  | 125 | } | 
| Benjamin Kramer | 7857d72 | 2015-03-21 21:09:33 +0000 | [diff] [blame] | 126 |  | 
|  | 127 | define void @test10() { | 
|  | 128 | ; CHECK-LABEL: @test10 | 
|  | 129 | ; CHECK: store i8* null, i8** @chp, align 4 | 
|  | 130 | ; CHECK-NOT: call i8* @memchr | 
|  | 131 | ; CHECK: ret void | 
|  | 132 |  | 
|  | 133 | %str = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 | 
|  | 134 | %dst = call i8* @memchr(i8* %str, i32 119, i32 6) | 
|  | 135 | store i8* %dst, i8** @chp | 
|  | 136 | ret void | 
|  | 137 | } | 
|  | 138 |  | 
|  | 139 | ; Check transformation memchr("\r\n", C, 2) != nullptr -> (C & 9216) != 0 | 
|  | 140 | define i1 @test11(i32 %C) { | 
|  | 141 | ; CHECK-LABEL: @test11 | 
|  | 142 | ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 %C to i16 | 
|  | 143 | ; CHECK-NEXT: %memchr.bounds = icmp ult i16 [[TRUNC]], 16 | 
|  | 144 | ; CHECK-NEXT: [[SHL:%.*]] = shl i16 1, [[TRUNC]] | 
|  | 145 | ; CHECK-NEXT: [[AND:%.*]] = and i16 [[SHL]], 9216 | 
|  | 146 | ; CHECK-NEXT: %memchr.bits = icmp ne i16 [[AND]], 0 | 
|  | 147 | ; CHECK-NEXT: %memchr = and i1 %memchr.bounds, %memchr.bits | 
|  | 148 | ; CHECK-NEXT: ret i1 %memchr | 
|  | 149 |  | 
|  | 150 | %dst = call i8* @memchr(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @newlines, i64 0, i64 0), i32 %C, i32 2) | 
|  | 151 | %cmp = icmp ne i8* %dst, null | 
|  | 152 | ret i1 %cmp | 
|  | 153 | } | 
|  | 154 |  | 
|  | 155 | ; No 64 bits here | 
|  | 156 | define i1 @test12(i32 %C) { | 
|  | 157 | ; CHECK-LABEL: @test12 | 
|  | 158 | ; CHECK-NEXT: %dst = call i8* @memchr(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @spaces, i32 0, i32 0), i32 %C, i32 3) | 
|  | 159 | ; CHECK-NEXT: %cmp = icmp ne i8* %dst, null | 
|  | 160 | ; CHECK-NEXT: ret i1 %cmp | 
|  | 161 |  | 
|  | 162 | %dst = call i8* @memchr(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @spaces, i64 0, i64 0), i32 %C, i32 3) | 
|  | 163 | %cmp = icmp ne i8* %dst, null | 
|  | 164 | ret i1 %cmp | 
|  | 165 | } | 
|  | 166 |  | 
|  | 167 | define i1 @test13(i32 %C) { | 
|  | 168 | ; CHECK-LABEL: @test13 | 
|  | 169 | ; CHECK-NEXT: %memchr.bounds = icmp ult i32 %C, 32 | 
|  | 170 | ; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, %C | 
|  | 171 | ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], -2147483647 | 
|  | 172 | ; CHECK-NEXT: %memchr.bits = icmp ne i32 [[AND]], 0 | 
|  | 173 | ; CHECK-NEXT: %memchr = and i1 %memchr.bounds, %memchr.bits | 
|  | 174 | ; CHECK-NEXT: ret i1 %memchr | 
|  | 175 |  | 
|  | 176 | %dst = call i8* @memchr(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @single, i64 0, i64 0), i32 %C, i32 2) | 
|  | 177 | %cmp = icmp ne i8* %dst, null | 
|  | 178 | ret i1 %cmp | 
|  | 179 | } | 
|  | 180 |  | 
|  | 181 | define i1 @test14(i32 %C) { | 
|  | 182 | ; CHECK-LABEL: @test14 | 
|  | 183 | ; CHECK-NEXT: icmp eq i32 %C, 31 | 
|  | 184 | ; CHECK-NEXT: ret | 
|  | 185 |  | 
|  | 186 | %dst = call i8* @memchr(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @single, i64 0, i64 0), i32 %C, i32 1) | 
|  | 187 | %cmp = icmp ne i8* %dst, null | 
|  | 188 | ret i1 %cmp | 
|  | 189 | } | 
| Benjamin Kramer | d6aa0ec | 2015-03-21 22:04:26 +0000 | [diff] [blame] | 190 |  | 
|  | 191 | define i1 @test15(i32 %C) { | 
|  | 192 | ; CHECK-LABEL: @test15 | 
|  | 193 | ; CHECK-NEXT: %dst = call i8* @memchr(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @negative, i32 0, i32 0), i32 %C, i32 3) | 
|  | 194 | ; CHECK-NEXT: %cmp = icmp ne i8* %dst, null | 
|  | 195 | ; CHECK-NEXT: ret i1 %cmp | 
|  | 196 |  | 
|  | 197 | %dst = call i8* @memchr(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @negative, i64 0, i64 0), i32 %C, i32 3) | 
|  | 198 | %cmp = icmp ne i8* %dst, null | 
|  | 199 | ret i1 %cmp | 
|  | 200 | } |