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(i8*, i8*, i64) 12 13define void @fold_strncmp_Aa_b(i32* %pcmp) { 14; CHECK-LABEL: @fold_strncmp_Aa_b( 15; CHECK-NEXT: store i32 0, i32* [[PCMP:%.*]], align 4 16; CHECK-NEXT: [[PCMP1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1 17; CHECK-NEXT: store i32 0, i32* [[PCMP1]], align 4 18; CHECK-NEXT: [[CMP2:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A:%.*]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 2) 19; CHECK-NEXT: [[PCMP2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2 20; CHECK-NEXT: store i32 [[CMP2]], i32* [[PCMP2]], align 4 21; CHECK-NEXT: [[CMP3:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 3) 22; CHECK-NEXT: [[PCMP3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3 23; CHECK-NEXT: store i32 [[CMP3]], i32* [[PCMP3]], align 4 24; CHECK-NEXT: [[CMP4:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 4) 25; CHECK-NEXT: [[PCMP4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4 26; CHECK-NEXT: store i32 [[CMP4]], i32* [[PCMP4]], align 4 27; CHECK-NEXT: [[CMP5:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 5) 28; CHECK-NEXT: [[PCMP5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5 29; CHECK-NEXT: store i32 [[CMP5]], i32* [[PCMP5]], align 4 30; CHECK-NEXT: [[CMP6:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 6) 31; CHECK-NEXT: [[PCMP6:%.*]] = getelementptr i32, i32* [[PCMP]], i64 6 32; CHECK-NEXT: store i32 [[CMP6]], i32* [[PCMP6]], align 4 33; CHECK-NEXT: [[CMP7:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 7) 34; CHECK-NEXT: [[PCMP7:%.*]] = getelementptr i32, i32* [[PCMP]], i64 7 35; CHECK-NEXT: store i32 [[CMP7]], i32* [[PCMP7]], align 4 36; CHECK-NEXT: [[CMP8:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 8) 37; CHECK-NEXT: [[PCMP8:%.*]] = getelementptr i32, i32* [[PCMP]], i64 8 38; CHECK-NEXT: store i32 [[CMP8]], i32* [[PCMP8]], align 4 39; CHECK-NEXT: [[CMP9:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 0), i64 9) 40; CHECK-NEXT: [[PCMP9:%.*]] = getelementptr i32, i32* [[PCMP]], i64 9 41; CHECK-NEXT: store i32 [[CMP9]], i32* [[PCMP9]], align 4 42; CHECK-NEXT: ret void 43; 44; p1 = a.a 45 %p1 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 0, i32 0 46; p2 = a.b 47 %p2 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 1, i32 0 48 49; Fold strncmp(a.a = "123", a.b = "1231", 0) to 0. 50 %cmp0 = call i32 @strncmp(i8* %p1, i8* %p2, i64 0) 51 %pcmp0 = getelementptr i32, i32* %pcmp, i64 0 52 store i32 %cmp0, i32* %pcmp0 53 54; Fold strncmp(a.a = "123", a.b = "1231", 1) to 0. 55 %cmp1 = call i32 @strncmp(i8* %p1, i8* %p2, i64 1) 56 %pcmp1 = getelementptr i32, i32* %pcmp, i64 1 57 store i32 %cmp1, i32* %pcmp1 58 59; Fold strncmp(a.a = "123", a.b = "1231", 2) to 0. 60 %cmp2 = call i32 @strncmp(i8* %p1, i8* %p2, i64 2) 61 %pcmp2 = getelementptr i32, i32* %pcmp, i64 2 62 store i32 %cmp2, i32* %pcmp2 63 64; Fold strncmp(a.a = "123", a.b = "1231", 3) to 0. 65 %cmp3 = call i32 @strncmp(i8* %p1, i8* %p2, i64 3) 66 %pcmp3 = getelementptr i32, i32* %pcmp, i64 3 67 store i32 %cmp3, i32* %pcmp3 68 69; Fold strncmp(a.a = "123", a.b = "1231", 4) to 0. 70; In this and the subsequent tests, reading past the end of a.a is 71; strictly undefined in C/C++ (because it forms a pointer to a distinct 72; subobject) but handling such cases as if they were well-defined is 73; simpler than trying to exclude them. 74 75 %cmp4 = call i32 @strncmp(i8* %p1, i8* %p2, i64 4) 76 %pcmp4 = getelementptr i32, i32* %pcmp, i64 4 77 store i32 %cmp4, i32* %pcmp4 78 79; Fold strncmp("123", "1231" "2", 5) to 0. 80 %cmp5 = call i32 @strncmp(i8* %p1, i8* %p2, i64 5) 81 %pcmp5 = getelementptr i32, i32* %pcmp, i64 5 82 store i32 %cmp5, i32* %pcmp5 83 84; Fold strncmp("123", "1231" "23", 6) to 0. 85 %cmp6 = call i32 @strncmp(i8* %p1, i8* %p2, i64 6) 86 %pcmp6 = getelementptr i32, i32* %pcmp, i64 6 87 store i32 %cmp6, i32* %pcmp6 88 89; Fold strncmp("123", "1231" "2345", 7) to 1. 90 %cmp7 = call i32 @strncmp(i8* %p1, i8* %p2, i64 7) 91 %pcmp7 = getelementptr i32, i32* %pcmp, i64 7 92 store i32 %cmp7, i32* %pcmp7 93 94; Fold strncmp("123", "1231" "2345", 8) to 1. 95 %cmp8 = call i32 @strncmp(i8* %p1, i8* %p2, i64 8) 96 %pcmp8 = getelementptr i32, i32* %pcmp, i64 8 97 store i32 %cmp8, i32* %pcmp8 98 99; Fold strncmp("123", "1231" "2345", 9) to 1. 100 %cmp9 = call i32 @strncmp(i8* %p1, i8* %p2, i64 9) 101 %pcmp9 = getelementptr i32, i32* %pcmp, i64 9 102 store i32 %cmp9, i32* %pcmp9 103 104 ret void 105} 106 107 108define void @fold_strncmp_Ab_a(i32* %pcmp) { 109; CHECK-LABEL: @fold_strncmp_Ab_a( 110; CHECK-NEXT: store i32 0, i32* [[PCMP:%.*]], align 4 111; CHECK-NEXT: [[PCMP1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1 112; CHECK-NEXT: store i32 0, i32* [[PCMP1]], align 4 113; CHECK-NEXT: [[CMP2:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A:%.*]], %struct.A* @a, i64 0, i32 1, i64 3), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i64 2) 114; CHECK-NEXT: [[PCMP2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2 115; CHECK-NEXT: store i32 [[CMP2]], i32* [[PCMP2]], align 4 116; CHECK-NEXT: [[CMP3:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 3), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i64 3) 117; CHECK-NEXT: [[PCMP3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3 118; CHECK-NEXT: store i32 [[CMP3]], i32* [[PCMP3]], align 4 119; CHECK-NEXT: [[CMP4:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 3), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i64 4) 120; CHECK-NEXT: [[PCMP4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4 121; CHECK-NEXT: store i32 [[CMP4]], i32* [[PCMP4]], align 4 122; CHECK-NEXT: [[CMP5:%.*]] = call i32 @strncmp(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 1, i64 3), i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([[STRUCT_A]], %struct.A* @a, i64 0, i32 0, i64 0), i64 5) 123; CHECK-NEXT: [[PCMP5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5 124; CHECK-NEXT: store i32 [[CMP5]], i32* [[PCMP5]], align 4 125; CHECK-NEXT: ret void 126; 127; p1 = &a.b[3] 128 %p1 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 1, i32 3 129; p2 = &a.a 130 %p2 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 0, i32 0 131 132; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 0) to 0. 133 %cmp0 = call i32 @strncmp(i8* %p1, i8* %p2, i64 0) 134 %pcmp0 = getelementptr i32, i32* %pcmp, i64 0 135 store i32 %cmp0, i32* %pcmp0 136 137; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 1) to 0. 138 %cmp1 = call i32 @strncmp(i8* %p1, i8* %p2, i64 1) 139 %pcmp1 = getelementptr i32, i32* %pcmp, i64 1 140 store i32 %cmp1, i32* %pcmp1 141 142; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 2) to 0. 143 %cmp2 = call i32 @strncmp(i8* %p1, i8* %p2, i64 2) 144 %pcmp2 = getelementptr i32, i32* %pcmp, i64 2 145 store i32 %cmp2, i32* %pcmp2 146 147; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 3) to 0. 148 %cmp3 = call i32 @strncmp(i8* %p1, i8* %p2, i64 3) 149 %pcmp3 = getelementptr i32, i32* %pcmp, i64 3 150 store i32 %cmp3, i32* %pcmp3 151 152; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 4) to 1. 153 %cmp4 = call i32 @strncmp(i8* %p1, i8* %p2, i64 4) 154 %pcmp4 = getelementptr i32, i32* %pcmp, i64 4 155 store i32 %cmp4, i32* %pcmp4 156 157; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 5) to 1. 158 %cmp5 = call i32 @strncmp(i8* %p1, i8* %p2, i64 5) 159 %pcmp5 = getelementptr i32, i32* %pcmp, i64 5 160 store i32 %cmp5, i32* %pcmp5 161 162 ret void 163} 164