1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Verify that strncmp calls with members of constant structs are folded. 3; 4; RUN: opt < %s -passes=instcombine -S | FileCheck %s 5 6; struct A { char a[3], b[4], c[4]; }; 7%struct.A = type { [3 x i8], [4 x i8], [4 x i8] } 8 9@a = constant %struct.A { [3 x i8] c"123", [4 x i8] c"1231", [4 x i8] c"2345" } 10 11declare i32 @strncmp(ptr, ptr, i64) 12 13define void @fold_strncmp_Aa_b(ptr %pcmp) { 14; CHECK-LABEL: @fold_strncmp_Aa_b( 15; CHECK-NEXT: store i32 0, ptr [[PCMP:%.*]], align 4 16; CHECK-NEXT: [[PCMP1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 17; CHECK-NEXT: store i32 0, ptr [[PCMP1]], align 4 18; CHECK-NEXT: [[PCMP2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 19; CHECK-NEXT: store i32 0, ptr [[PCMP2]], align 4 20; CHECK-NEXT: [[PCMP3:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 21; CHECK-NEXT: store i32 0, ptr [[PCMP3]], align 4 22; CHECK-NEXT: [[PCMP4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16 23; CHECK-NEXT: store i32 0, ptr [[PCMP4]], align 4 24; CHECK-NEXT: [[PCMP5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20 25; CHECK-NEXT: store i32 0, ptr [[PCMP5]], align 4 26; CHECK-NEXT: [[PCMP6:%.*]] = getelementptr i8, ptr [[PCMP]], i64 24 27; CHECK-NEXT: store i32 0, ptr [[PCMP6]], align 4 28; CHECK-NEXT: [[PCMP7:%.*]] = getelementptr i8, ptr [[PCMP]], i64 28 29; CHECK-NEXT: store i32 -1, ptr [[PCMP7]], align 4 30; CHECK-NEXT: [[PCMP8:%.*]] = getelementptr i8, ptr [[PCMP]], i64 32 31; CHECK-NEXT: store i32 -1, ptr [[PCMP8]], align 4 32; CHECK-NEXT: [[PCMP9:%.*]] = getelementptr i8, ptr [[PCMP]], i64 36 33; CHECK-NEXT: store i32 -1, ptr [[PCMP9]], align 4 34; CHECK-NEXT: ret void 35; 36; p1 = a.a 37; p2 = a.b 38 %p2 = getelementptr %struct.A, ptr @a, i32 0, i32 1, i32 0 39 40; Fold strncmp(a.a = "123", a.b = "1231", 0) to 0. 41 %cmp0 = call i32 @strncmp(ptr @a, ptr %p2, i64 0) 42 store i32 %cmp0, ptr %pcmp 43 44; Fold strncmp(a.a = "123", a.b = "1231", 1) to 0. 45 %cmp1 = call i32 @strncmp(ptr @a, ptr %p2, i64 1) 46 %pcmp1 = getelementptr i32, ptr %pcmp, i64 1 47 store i32 %cmp1, ptr %pcmp1 48 49; Fold strncmp(a.a = "123", a.b = "1231", 2) to 0. 50 %cmp2 = call i32 @strncmp(ptr @a, ptr %p2, i64 2) 51 %pcmp2 = getelementptr i32, ptr %pcmp, i64 2 52 store i32 %cmp2, ptr %pcmp2 53 54; Fold strncmp(a.a = "123", a.b = "1231", 3) to 0. 55 %cmp3 = call i32 @strncmp(ptr @a, ptr %p2, i64 3) 56 %pcmp3 = getelementptr i32, ptr %pcmp, i64 3 57 store i32 %cmp3, ptr %pcmp3 58 59; Fold strncmp(a.a = "123", a.b = "1231", 4) to 0. 60; In this and the subsequent tests, reading past the end of a.a is 61; strictly undefined in C/C++ (because it forms a pointer to a distinct 62; subobject) but handling such cases as if they were well-defined is 63; simpler than trying to exclude them. 64 65 %cmp4 = call i32 @strncmp(ptr @a, ptr %p2, i64 4) 66 %pcmp4 = getelementptr i32, ptr %pcmp, i64 4 67 store i32 %cmp4, ptr %pcmp4 68 69; Fold strncmp("123", "1231" "2", 5) to 0. 70 %cmp5 = call i32 @strncmp(ptr @a, ptr %p2, i64 5) 71 %pcmp5 = getelementptr i32, ptr %pcmp, i64 5 72 store i32 %cmp5, ptr %pcmp5 73 74; Fold strncmp("123", "1231" "23", 6) to 0. 75 %cmp6 = call i32 @strncmp(ptr @a, ptr %p2, i64 6) 76 %pcmp6 = getelementptr i32, ptr %pcmp, i64 6 77 store i32 %cmp6, ptr %pcmp6 78 79; Fold strncmp("123", "1231" "2345", 7) to 1. 80 %cmp7 = call i32 @strncmp(ptr @a, ptr %p2, i64 7) 81 %pcmp7 = getelementptr i32, ptr %pcmp, i64 7 82 store i32 %cmp7, ptr %pcmp7 83 84; Fold strncmp("123", "1231" "2345", 8) to 1. 85 %cmp8 = call i32 @strncmp(ptr @a, ptr %p2, i64 8) 86 %pcmp8 = getelementptr i32, ptr %pcmp, i64 8 87 store i32 %cmp8, ptr %pcmp8 88 89; Fold strncmp("123", "1231" "2345", 9) to 1. 90 %cmp9 = call i32 @strncmp(ptr @a, ptr %p2, i64 9) 91 %pcmp9 = getelementptr i32, ptr %pcmp, i64 9 92 store i32 %cmp9, ptr %pcmp9 93 94 ret void 95} 96 97 98define void @fold_strncmp_Ab_a(ptr %pcmp) { 99; CHECK-LABEL: @fold_strncmp_Ab_a( 100; CHECK-NEXT: store i32 0, ptr [[PCMP:%.*]], align 4 101; CHECK-NEXT: [[PCMP1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 102; CHECK-NEXT: store i32 0, ptr [[PCMP1]], align 4 103; CHECK-NEXT: [[PCMP2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 104; CHECK-NEXT: store i32 0, ptr [[PCMP2]], align 4 105; CHECK-NEXT: [[PCMP3:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 106; CHECK-NEXT: store i32 0, ptr [[PCMP3]], align 4 107; CHECK-NEXT: [[PCMP4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16 108; CHECK-NEXT: store i32 1, ptr [[PCMP4]], align 4 109; CHECK-NEXT: [[PCMP5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20 110; CHECK-NEXT: store i32 1, ptr [[PCMP5]], align 4 111; CHECK-NEXT: ret void 112; 113; p1 = &a.b[3] 114 %p1 = getelementptr %struct.A, ptr @a, i32 0, i32 1, i32 3 115; p2 = &a.a 116 117; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 0) to 0. 118 %cmp0 = call i32 @strncmp(ptr %p1, ptr @a, i64 0) 119 store i32 %cmp0, ptr %pcmp 120 121; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 1) to 0. 122 %cmp1 = call i32 @strncmp(ptr %p1, ptr @a, i64 1) 123 %pcmp1 = getelementptr i32, ptr %pcmp, i64 1 124 store i32 %cmp1, ptr %pcmp1 125 126; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 2) to 0. 127 %cmp2 = call i32 @strncmp(ptr %p1, ptr @a, i64 2) 128 %pcmp2 = getelementptr i32, ptr %pcmp, i64 2 129 store i32 %cmp2, ptr %pcmp2 130 131; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 3) to 0. 132 %cmp3 = call i32 @strncmp(ptr %p1, ptr @a, i64 3) 133 %pcmp3 = getelementptr i32, ptr %pcmp, i64 3 134 store i32 %cmp3, ptr %pcmp3 135 136; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 4) to 1. 137 %cmp4 = call i32 @strncmp(ptr %p1, ptr @a, i64 4) 138 %pcmp4 = getelementptr i32, ptr %pcmp, i64 4 139 store i32 %cmp4, ptr %pcmp4 140 141; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 5) to 1. 142 %cmp5 = call i32 @strncmp(ptr %p1, ptr @a, i64 5) 143 %pcmp5 = getelementptr i32, ptr %pcmp, i64 5 144 store i32 %cmp5, ptr %pcmp5 145 146 ret void 147} 148