1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Verify that strlen calls with elements of constant arrays are folded. 3; 4; RUN: opt < %s -passes=instcombine -S | FileCheck %s 5 6declare i32 @strcmp(ptr, ptr) 7 8@a5 = constant [5 x [4 x i8]] [[4 x i8] c"123\00", [4 x i8] c"123\00", [4 x i8] c"12\00\00", [4 x i8] zeroinitializer, [4 x i8] zeroinitializer] 9 10 11; Fold strcmp(a5[0], a5[1]) to '1' - '1'. 12 13define i32 @fold_strcmp_a5i0_a5i1_to_0() { 14; CHECK-LABEL: @fold_strcmp_a5i0_a5i1_to_0( 15; CHECK-NEXT: ret i32 0 16; 17 %q = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 1, i64 0 18 19 %cmp = call i32 @strcmp(ptr @a5, ptr %q) 20 ret i32 %cmp 21} 22 23 24; Do not fold strcmp(a5[0], a5[I]) where the index I is not constant. 25 26define i32 @call_strcmp_a5i0_a5iI(i64 %I) { 27; CHECK-LABEL: @call_strcmp_a5i0_a5iI( 28; CHECK-NEXT: [[Q:%.*]] = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 [[I:%.*]], i64 0 29; CHECK-NEXT: [[CMP:%.*]] = call i32 @strcmp(ptr noundef nonnull dereferenceable(4) @a5, ptr noundef nonnull dereferenceable(1) [[Q]]) 30; CHECK-NEXT: ret i32 [[CMP]] 31; 32 %q = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 %I, i64 0 33 34 %cmp = call i32 @strcmp(ptr @a5, ptr %q) 35 ret i32 %cmp 36} 37 38 39; Same as above but for strcmp(a5[I], a5[0]). 40 41define i32 @call_strcmp_a5iI_a5i0(i64 %I) { 42; CHECK-LABEL: @call_strcmp_a5iI_a5i0( 43; CHECK-NEXT: [[P:%.*]] = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 [[I:%.*]], i64 0 44; CHECK-NEXT: [[CMP:%.*]] = call i32 @strcmp(ptr noundef nonnull dereferenceable(1) [[P]], ptr noundef nonnull dereferenceable(4) @a5) 45; CHECK-NEXT: ret i32 [[CMP]] 46; 47 %p = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 %I, i64 0 48 49 %cmp = call i32 @strcmp(ptr %p, ptr @a5) 50 ret i32 %cmp 51} 52 53 54; Fold strcmp(a5[0], &a5[1][1]) to '1' - '2'. 55 56define i32 @fold_strcmp_a5i0_a5i1_p1_to_0() { 57; CHECK-LABEL: @fold_strcmp_a5i0_a5i1_p1_to_0( 58; CHECK-NEXT: ret i32 -1 59; 60 %q = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 1, i64 1 61 62 %cmp = call i32 @strcmp(ptr @a5, ptr %q) 63 ret i32 %cmp 64} 65 66 67; Do not fold strcmp(a5[0], &a5[1][I]) when the index I is not constant. 68 69define i32 @call_strcmp_a5i0_a5i1_pI(i64 %I) { 70; CHECK-LABEL: @call_strcmp_a5i0_a5i1_pI( 71; CHECK-NEXT: [[Q:%.*]] = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 1, i64 [[I:%.*]] 72; CHECK-NEXT: [[CMP:%.*]] = call i32 @strcmp(ptr noundef nonnull dereferenceable(4) @a5, ptr noundef nonnull dereferenceable(1) [[Q]]) 73; CHECK-NEXT: ret i32 [[CMP]] 74; 75 %q = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 1, i64 %I 76 77 %cmp = call i32 @strcmp(ptr @a5, ptr %q) 78 ret i32 %cmp 79} 80 81 82; Fold strcmp(&a5[0][1], a5[1]) to '2' - '1'. 83 84define i32 @fold_strcmp_a5i0_p1_a5i1_to_0() { 85; CHECK-LABEL: @fold_strcmp_a5i0_p1_a5i1_to_0( 86; CHECK-NEXT: ret i32 1 87; 88 %p = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 0, i64 1 89 %q = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 1, i64 0 90 91 %cmp = call i32 @strcmp(ptr %p, ptr %q) 92 ret i32 %cmp 93} 94 95 96; Fold strcmp(a5[0], a5[2]) to a5[0][2] - a5[2][2] or 1. 97 98define i32 @fold_strcmp_a5i0_a5i2_to_0() { 99; CHECK-LABEL: @fold_strcmp_a5i0_a5i2_to_0( 100; CHECK-NEXT: ret i32 1 101; 102 %q = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 2, i64 0 103 104 %cmp = call i32 @strcmp(ptr @a5, ptr %q) 105 ret i32 %cmp 106} 107 108 109; Fold strcmp(a5[2], a5[0]) to a5[0][2] - a5[2][2] or 1. 110 111define i32 @fold_strcmp_a5i2_a5i0_to_m1() { 112; CHECK-LABEL: @fold_strcmp_a5i2_a5i0_to_m1( 113; CHECK-NEXT: ret i32 -1 114; 115 %q = getelementptr [5 x [4 x i8]], ptr @a5, i64 0, i64 2, i64 0 116 117 %cmp = call i32 @strcmp(ptr %q, ptr @a5) 118 ret i32 %cmp 119} 120