1; Test that the memchr library call simplifier works correctly. 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4target 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" 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 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" 12@negative = constant [3 x i8] c"\FF\FE\00" 13@chp = global i8* zeroinitializer 14 15declare i8* @memchr(i8*, i32, i32) 16 17define 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 29define 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 41define 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 53define 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 65define 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 77define 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 90define 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 103define 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 115define 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} 126 127define 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 140define 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 156define 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 167define 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 181define 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} 190 191define 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} 201