1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -S -passes=aggressive-instcombine --memchr-inline-threshold=5 < %s | FileCheck %s 3 4@str = constant [5 x i8] c"01\002\00", align 1 5@str_long = constant [8 x i8] c"0123456\00", align 1 6 7declare ptr @memchr(ptr, i32, i64) 8 9define i1 @test_memchr_null(i32 %x) { 10; CHECK-LABEL: define i1 @test_memchr_null( 11; CHECK-SAME: i32 [[X:%.*]]) { 12; CHECK-NEXT: [[ENTRY:.*]]: 13; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[X]] to i8 14; CHECK-NEXT: switch i8 [[TMP0]], label %[[ENTRY_SPLIT:.*]] [ 15; CHECK-NEXT: i8 48, label %[[MEMCHR_CASE:.*]] 16; CHECK-NEXT: i8 49, label %[[MEMCHR_CASE1:.*]] 17; CHECK-NEXT: i8 0, label %[[MEMCHR_CASE2:.*]] 18; CHECK-NEXT: i8 50, label %[[MEMCHR_CASE3:.*]] 19; CHECK-NEXT: ] 20; CHECK: [[MEMCHR_CASE]]: 21; CHECK-NEXT: br label %[[MEMCHR_SUCCESS:.*]] 22; CHECK: [[MEMCHR_CASE1]]: 23; CHECK-NEXT: br label %[[MEMCHR_SUCCESS]] 24; CHECK: [[MEMCHR_CASE2]]: 25; CHECK-NEXT: br label %[[MEMCHR_SUCCESS]] 26; CHECK: [[MEMCHR_CASE3]]: 27; CHECK-NEXT: br label %[[MEMCHR_SUCCESS]] 28; CHECK: [[MEMCHR_SUCCESS]]: 29; CHECK-NEXT: [[MEMCHR_IDX:%.*]] = phi i64 [ 0, %[[MEMCHR_CASE]] ], [ 1, %[[MEMCHR_CASE1]] ], [ 2, %[[MEMCHR_CASE2]] ], [ 3, %[[MEMCHR_CASE3]] ] 30; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr @str, i64 [[MEMCHR_IDX]] 31; CHECK-NEXT: br label %[[ENTRY_SPLIT]] 32; CHECK: [[ENTRY_SPLIT]]: 33; CHECK-NEXT: [[MEMCHR4:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[TMP1]], %[[MEMCHR_SUCCESS]] ] 34; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[MEMCHR4]], null 35; CHECK-NEXT: ret i1 [[ISNULL]] 36; 37entry: 38 %memchr = call ptr @memchr(ptr @str, i32 %x, i64 5) 39 %isnull = icmp eq ptr %memchr, null 40 ret i1 %isnull 41} 42 43define ptr @test_memchr(i32 %x) { 44; CHECK-LABEL: define ptr @test_memchr( 45; CHECK-SAME: i32 [[X:%.*]]) { 46; CHECK-NEXT: [[ENTRY:.*]]: 47; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[X]] to i8 48; CHECK-NEXT: switch i8 [[TMP0]], label %[[ENTRY_SPLIT:.*]] [ 49; CHECK-NEXT: i8 48, label %[[MEMCHR_CASE:.*]] 50; CHECK-NEXT: i8 49, label %[[MEMCHR_CASE1:.*]] 51; CHECK-NEXT: i8 0, label %[[MEMCHR_CASE2:.*]] 52; CHECK-NEXT: i8 50, label %[[MEMCHR_CASE3:.*]] 53; CHECK-NEXT: ] 54; CHECK: [[MEMCHR_CASE]]: 55; CHECK-NEXT: br label %[[MEMCHR_SUCCESS:.*]] 56; CHECK: [[MEMCHR_CASE1]]: 57; CHECK-NEXT: br label %[[MEMCHR_SUCCESS]] 58; CHECK: [[MEMCHR_CASE2]]: 59; CHECK-NEXT: br label %[[MEMCHR_SUCCESS]] 60; CHECK: [[MEMCHR_CASE3]]: 61; CHECK-NEXT: br label %[[MEMCHR_SUCCESS]] 62; CHECK: [[MEMCHR_SUCCESS]]: 63; CHECK-NEXT: [[MEMCHR_IDX:%.*]] = phi i64 [ 0, %[[MEMCHR_CASE]] ], [ 1, %[[MEMCHR_CASE1]] ], [ 2, %[[MEMCHR_CASE2]] ], [ 3, %[[MEMCHR_CASE3]] ] 64; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr @str, i64 [[MEMCHR_IDX]] 65; CHECK-NEXT: br label %[[ENTRY_SPLIT]] 66; CHECK: [[ENTRY_SPLIT]]: 67; CHECK-NEXT: [[MEMCHR4:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[TMP1]], %[[MEMCHR_SUCCESS]] ] 68; CHECK-NEXT: ret ptr [[MEMCHR4]] 69; 70entry: 71 %memchr = call ptr @memchr(ptr @str, i32 %x, i64 5) 72 ret ptr %memchr 73} 74 75define ptr @test_memchr_smaller_n(i32 %x) { 76; CHECK-LABEL: define ptr @test_memchr_smaller_n( 77; CHECK-SAME: i32 [[X:%.*]]) { 78; CHECK-NEXT: [[ENTRY:.*]]: 79; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[X]] to i8 80; CHECK-NEXT: switch i8 [[TMP0]], label %[[ENTRY_SPLIT:.*]] [ 81; CHECK-NEXT: i8 48, label %[[MEMCHR_CASE:.*]] 82; CHECK-NEXT: i8 49, label %[[MEMCHR_CASE1:.*]] 83; CHECK-NEXT: i8 0, label %[[MEMCHR_CASE2:.*]] 84; CHECK-NEXT: ] 85; CHECK: [[MEMCHR_CASE]]: 86; CHECK-NEXT: br label %[[MEMCHR_SUCCESS:.*]] 87; CHECK: [[MEMCHR_CASE1]]: 88; CHECK-NEXT: br label %[[MEMCHR_SUCCESS]] 89; CHECK: [[MEMCHR_CASE2]]: 90; CHECK-NEXT: br label %[[MEMCHR_SUCCESS]] 91; CHECK: [[MEMCHR_SUCCESS]]: 92; CHECK-NEXT: [[MEMCHR_IDX:%.*]] = phi i64 [ 0, %[[MEMCHR_CASE]] ], [ 1, %[[MEMCHR_CASE1]] ], [ 2, %[[MEMCHR_CASE2]] ] 93; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr @str, i64 [[MEMCHR_IDX]] 94; CHECK-NEXT: br label %[[ENTRY_SPLIT]] 95; CHECK: [[ENTRY_SPLIT]]: 96; CHECK-NEXT: [[MEMCHR3:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[TMP1]], %[[MEMCHR_SUCCESS]] ] 97; CHECK-NEXT: ret ptr [[MEMCHR3]] 98; 99entry: 100 %memchr = call ptr @memchr(ptr @str, i32 %x, i64 3) 101 ret ptr %memchr 102} 103 104; negative tests 105 106define ptr @test_memchr_larger_n(i32 %x) { 107; CHECK-LABEL: define ptr @test_memchr_larger_n( 108; CHECK-SAME: i32 [[X:%.*]]) { 109; CHECK-NEXT: [[ENTRY:.*:]] 110; CHECK-NEXT: [[MEMCHR:%.*]] = call ptr @memchr(ptr @str, i32 [[X]], i64 6) 111; CHECK-NEXT: ret ptr [[MEMCHR]] 112; 113entry: 114 %memchr = call ptr @memchr(ptr @str, i32 %x, i64 6) 115 ret ptr %memchr 116} 117 118define ptr @test_memchr_non_constant(i32 %x, ptr %str) { 119; CHECK-LABEL: define ptr @test_memchr_non_constant( 120; CHECK-SAME: i32 [[X:%.*]], ptr [[STR:%.*]]) { 121; CHECK-NEXT: [[ENTRY:.*:]] 122; CHECK-NEXT: [[MEMCHR:%.*]] = call ptr @memchr(ptr [[STR]], i32 [[X]], i64 5) 123; CHECK-NEXT: ret ptr [[MEMCHR]] 124; 125entry: 126 %memchr = call ptr @memchr(ptr %str, i32 %x, i64 5) 127 ret ptr %memchr 128} 129 130define ptr @test_memchr_constant_ch() { 131; CHECK-LABEL: define ptr @test_memchr_constant_ch() { 132; CHECK-NEXT: [[ENTRY:.*:]] 133; CHECK-NEXT: [[MEMCHR:%.*]] = call ptr @memchr(ptr @str, i32 49, i64 5) 134; CHECK-NEXT: ret ptr [[MEMCHR]] 135; 136entry: 137 %memchr = call ptr @memchr(ptr @str, i32 49, i64 5) 138 ret ptr %memchr 139} 140 141define ptr @test_memchr_dynamic_n(i32 %x, i32 %y) { 142; CHECK-LABEL: define ptr @test_memchr_dynamic_n( 143; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 144; CHECK-NEXT: [[ENTRY:.*:]] 145; CHECK-NEXT: [[MEMCHR:%.*]] = call ptr @memchr(ptr @str, i32 [[X]], i32 [[Y]]) 146; CHECK-NEXT: ret ptr [[MEMCHR]] 147; 148entry: 149 %memchr = call ptr @memchr(ptr @str, i32 %x, i32 %y) 150 ret ptr %memchr 151} 152 153define ptr @test_memchr_long(i32 %x) { 154; CHECK-LABEL: define ptr @test_memchr_long( 155; CHECK-SAME: i32 [[X:%.*]]) { 156; CHECK-NEXT: [[ENTRY:.*:]] 157; CHECK-NEXT: [[MEMCHR:%.*]] = call ptr @memchr(ptr @str_long, i32 [[X]], i64 8) 158; CHECK-NEXT: ret ptr [[MEMCHR]] 159; 160entry: 161 %memchr = call ptr @memchr(ptr @str_long, i32 %x, i64 8) 162 ret ptr %memchr 163} 164 165; We want to check that the compiler still calls memchr if the length is non-constant: 166define ptr @test_memchr_non_constant_length2(i32 %x, i64 %len) { 167; CHECK-LABEL: define ptr @test_memchr_non_constant_length2( 168; CHECK-SAME: i32 [[X:%.*]], i64 [[LEN:%.*]]) { 169; CHECK-NEXT: [[ENTRY:.*:]] 170; CHECK-NEXT: [[MEMCHR:%.*]] = call ptr @memchr(ptr @str, i32 [[X]], i64 [[LEN]]) 171; CHECK-NEXT: ret ptr [[MEMCHR]] 172; 173entry: 174 %memchr = call ptr @memchr(ptr @str, i32 %x, i64 %len) 175 ret ptr %memchr 176} 177