1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Verify that strlen calls with members of constant structs are folded. 3; 4; RUN: opt < %s -passes=instcombine -S | FileCheck %s 5 6declare i64 @strlen(i8*) 7 8%struct.A = type { [4 x i8], [5 x i8] } 9 10@a = constant [2 x %struct.A] [%struct.A { [4 x i8] c"1\00\00\00", [5 x i8] c"12\00\00\00" }, %struct.A { [4 x i8] c"123\00", [5 x i8] c"1234\00" }], align 16 11 12 13; Fold strlen(a[I].a + J) and strlen(a[I].b + J) with constant I and J 14; to constants. 15 16define void @fold_strlen_A(i64* %plen) { 17; CHECK-LABEL: @fold_strlen_A( 18; CHECK-NEXT: [[LENA0A:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0)) 19; CHECK-NEXT: store i64 [[LENA0A]], i64* [[PLEN:%.*]], align 4 20; CHECK-NEXT: [[LENA0AP1:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 1)) 21; CHECK-NEXT: [[PLEN1:%.*]] = getelementptr i64, i64* [[PLEN]], i64 1 22; CHECK-NEXT: store i64 [[LENA0AP1]], i64* [[PLEN1]], align 4 23; CHECK-NEXT: [[LENA0AP2:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 2)) 24; CHECK-NEXT: [[PLEN2:%.*]] = getelementptr i64, i64* [[PLEN]], i64 2 25; CHECK-NEXT: store i64 [[LENA0AP2]], i64* [[PLEN2]], align 4 26; CHECK-NEXT: [[LENA0AP3:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 3)) 27; CHECK-NEXT: [[PLEN3:%.*]] = getelementptr i64, i64* [[PLEN]], i64 3 28; CHECK-NEXT: store i64 [[LENA0AP3]], i64* [[PLEN3]], align 4 29; CHECK-NEXT: [[LENA0B:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0)) 30; CHECK-NEXT: [[PLEN4:%.*]] = getelementptr i64, i64* [[PLEN]], i64 4 31; CHECK-NEXT: store i64 [[LENA0B]], i64* [[PLEN4]], align 4 32; CHECK-NEXT: [[LENA0BP1:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1)) 33; CHECK-NEXT: [[PLEN5:%.*]] = getelementptr i64, i64* [[PLEN]], i64 5 34; CHECK-NEXT: store i64 [[LENA0BP1]], i64* [[PLEN5]], align 4 35; CHECK-NEXT: [[LENA0BP2:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 2)) 36; CHECK-NEXT: [[PLEN6:%.*]] = getelementptr i64, i64* [[PLEN]], i64 6 37; CHECK-NEXT: store i64 [[LENA0BP2]], i64* [[PLEN6]], align 4 38; CHECK-NEXT: [[LENA0BP3:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 3)) 39; CHECK-NEXT: [[PLEN7:%.*]] = getelementptr i64, i64* [[PLEN]], i64 7 40; CHECK-NEXT: store i64 [[LENA0BP3]], i64* [[PLEN7]], align 4 41; CHECK-NEXT: [[LENA0BP4:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 4)) 42; CHECK-NEXT: [[PLEN8:%.*]] = getelementptr i64, i64* [[PLEN]], i64 8 43; CHECK-NEXT: store i64 [[LENA0BP4]], i64* [[PLEN8]], align 4 44; CHECK-NEXT: [[LENA1A:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0)) 45; CHECK-NEXT: [[PLEN9:%.*]] = getelementptr i64, i64* [[PLEN]], i64 9 46; CHECK-NEXT: store i64 [[LENA1A]], i64* [[PLEN9]], align 4 47; CHECK-NEXT: [[LENA1AP1:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 1)) 48; CHECK-NEXT: [[PLEN10:%.*]] = getelementptr i64, i64* [[PLEN]], i64 10 49; CHECK-NEXT: store i64 [[LENA1AP1]], i64* [[PLEN10]], align 4 50; CHECK-NEXT: [[LENA1AP2:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 2)) 51; CHECK-NEXT: [[PLEN11:%.*]] = getelementptr i64, i64* [[PLEN]], i64 11 52; CHECK-NEXT: store i64 [[LENA1AP2]], i64* [[PLEN11]], align 4 53; CHECK-NEXT: [[LENA1AP3:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 3)) 54; CHECK-NEXT: [[PLEN12:%.*]] = getelementptr i64, i64* [[PLEN]], i64 12 55; CHECK-NEXT: store i64 [[LENA1AP3]], i64* [[PLEN12]], align 4 56; CHECK-NEXT: [[LENA1B:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0)) 57; CHECK-NEXT: [[PLEN14:%.*]] = getelementptr i64, i64* [[PLEN]], i64 14 58; CHECK-NEXT: store i64 [[LENA1B]], i64* [[PLEN14]], align 4 59; CHECK-NEXT: [[LENA1BP1:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 1)) 60; CHECK-NEXT: [[PLEN15:%.*]] = getelementptr i64, i64* [[PLEN]], i64 15 61; CHECK-NEXT: store i64 [[LENA1BP1]], i64* [[PLEN15]], align 4 62; CHECK-NEXT: [[LENA1BP2:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 2)) 63; CHECK-NEXT: [[PLEN16:%.*]] = getelementptr i64, i64* [[PLEN]], i64 16 64; CHECK-NEXT: store i64 [[LENA1BP2]], i64* [[PLEN16]], align 4 65; CHECK-NEXT: [[LENA1BP3:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 3)) 66; CHECK-NEXT: [[PLEN17:%.*]] = getelementptr i64, i64* [[PLEN]], i64 17 67; CHECK-NEXT: store i64 [[LENA1BP3]], i64* [[PLEN17]], align 4 68; CHECK-NEXT: [[LENA1BP4:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 4)) 69; CHECK-NEXT: [[PLEN18:%.*]] = getelementptr i64, i64* [[PLEN]], i64 18 70; CHECK-NEXT: store i64 [[LENA1BP4]], i64* [[PLEN18]], align 4 71; CHECK-NEXT: ret void 72; 73; Fold strlen(a[0].a) to 1. 74 %pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0 75 %lena0a = call i64 @strlen(i8* %pa0a) 76 %plen0 = getelementptr i64, i64* %plen, i32 0 77 store i64 %lena0a, i64* %plen0 78 79; Fold strlen(a[0].a + 1) to 0. 80 %pa0ap1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 1 81 %lena0ap1 = call i64 @strlen(i8* %pa0ap1) 82 %plen1 = getelementptr i64, i64* %plen, i32 1 83 store i64 %lena0ap1, i64* %plen1 84 85; Fold strlen(a[0].a + 2) to 0. 86 %pa0ap2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 2 87 %lena0ap2 = call i64 @strlen(i8* %pa0ap2) 88 %plen2 = getelementptr i64, i64* %plen, i32 2 89 store i64 %lena0ap2, i64* %plen2 90 91; Fold strlen(a[0].a + 3) to 0. 92 %pa0ap3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 3 93 %lena0ap3 = call i64 @strlen(i8* %pa0ap3) 94 %plen3 = getelementptr i64, i64* %plen, i32 3 95 store i64 %lena0ap3, i64* %plen3 96 97; Fold strlen(a[0].b) to 2. 98 %pa0b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0 99 %lena0b = call i64 @strlen(i8* %pa0b) 100 %plen4 = getelementptr i64, i64* %plen, i32 4 101 store i64 %lena0b, i64* %plen4 102 103; Fold strlen(a[0].b + 1) to 1. 104 %pa0bp1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1 105 %lena0bp1 = call i64 @strlen(i8* %pa0bp1) 106 %plen5 = getelementptr i64, i64* %plen, i32 5 107 store i64 %lena0bp1, i64* %plen5 108 109; Fold strlen(a[0].b + 2) to 0. 110 %pa0bp2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 2 111 %lena0bp2 = call i64 @strlen(i8* %pa0bp2) 112 %plen6 = getelementptr i64, i64* %plen, i32 6 113 store i64 %lena0bp2, i64* %plen6 114 115; Fold strlen(a[0].b + 3) to 0. 116 %pa0bp3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 3 117 %lena0bp3 = call i64 @strlen(i8* %pa0bp3) 118 %plen7 = getelementptr i64, i64* %plen, i32 7 119 store i64 %lena0bp3, i64* %plen7 120 121; Fold strlen(a[0].b + 4) to 0. 122 %pa0bp4 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 4 123 %lena0bp4 = call i64 @strlen(i8* %pa0bp4) 124 %plen8 = getelementptr i64, i64* %plen, i32 8 125 store i64 %lena0bp4, i64* %plen8 126 127; Fold strlen(a[1].a) to 3. 128 %pa1a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0 129 %lena1a = call i64 @strlen(i8* %pa1a) 130 %plen9 = getelementptr i64, i64* %plen, i32 9 131 store i64 %lena1a, i64* %plen9 132 133; Fold strlen(a[1].a + 1) to 2. 134 %pa1ap1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 1 135 %lena1ap1 = call i64 @strlen(i8* %pa1ap1) 136 %plen10 = getelementptr i64, i64* %plen, i32 10 137 store i64 %lena1ap1, i64* %plen10 138 139; Fold strlen(a[1].a + 2) to 1. 140 %pa1ap2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 2 141 %lena1ap2 = call i64 @strlen(i8* %pa1ap2) 142 %plen11 = getelementptr i64, i64* %plen, i32 11 143 store i64 %lena1ap2, i64* %plen11 144 145; Fold strlen(a[1].a + 3) to 0. 146 %pa1ap3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 3 147 %lena1ap3 = call i64 @strlen(i8* %pa1ap3) 148 %plen12 = getelementptr i64, i64* %plen, i32 12 149 store i64 %lena1ap3, i64* %plen12 150 151; Fold strlen(a[1].b) to 4. 152 %pa1b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0 153 %lena1b = call i64 @strlen(i8* %pa1b) 154 %plen14 = getelementptr i64, i64* %plen, i32 14 155 store i64 %lena1b, i64* %plen14 156 157; Fold strlen(a[1].b + 1) to 3. 158 %pa1bp1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 1 159 %lena1bp1 = call i64 @strlen(i8* %pa1bp1) 160 %plen15 = getelementptr i64, i64* %plen, i32 15 161 store i64 %lena1bp1, i64* %plen15 162 163; Fold strlen(a[1].b + 2) to 2. 164 %pa1bp2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 2 165 %lena1bp2 = call i64 @strlen(i8* %pa1bp2) 166 %plen16 = getelementptr i64, i64* %plen, i32 16 167 store i64 %lena1bp2, i64* %plen16 168 169; Fold strlen(a[1].b + 3) to 1. 170 %pa1bp3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 3 171 %lena1bp3 = call i64 @strlen(i8* %pa1bp3) 172 %plen17 = getelementptr i64, i64* %plen, i32 17 173 store i64 %lena1bp3, i64* %plen17 174 175; Fold strlen(a[1].b + 4) to 0. 176 %pa1bp4 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 4 177 %lena1bp4 = call i64 @strlen(i8* %pa1bp4) 178 %plen18 = getelementptr i64, i64* %plen, i32 18 179 store i64 %lena1bp4, i64* %plen18 180 181 ret void 182} 183 184 185; TODO: Fold strlen(a[I].a + X) and strlen(a[I].b + X) with constant I and 186; variable X to (X - strlen(a[I].a)) and (X - strlen(a[I].b)) respectively. 187 188define void @fold_strlen_A_pI(i64* %plen, i64 %I) { 189; CHECK-LABEL: @fold_strlen_A_pI( 190; CHECK-NEXT: [[PA0A:%.*]] = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 [[I:%.*]] 191; CHECK-NEXT: [[LENA0A:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) [[PA0A]]) 192; CHECK-NEXT: store i64 [[LENA0A]], i64* [[PLEN:%.*]], align 4 193; CHECK-NEXT: [[PA0B:%.*]] = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 [[I]] 194; CHECK-NEXT: [[LENA0B:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) [[PA0B]]) 195; CHECK-NEXT: [[PLEN1:%.*]] = getelementptr i64, i64* [[PLEN]], i64 1 196; CHECK-NEXT: store i64 [[LENA0B]], i64* [[PLEN1]], align 4 197; CHECK-NEXT: [[PA1A:%.*]] = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 [[I]] 198; CHECK-NEXT: [[LENA1A:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) [[PA1A]]) 199; CHECK-NEXT: [[PLEN2:%.*]] = getelementptr i64, i64* [[PLEN]], i64 2 200; CHECK-NEXT: store i64 [[LENA1A]], i64* [[PLEN2]], align 4 201; CHECK-NEXT: [[PA1B:%.*]] = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 [[I]] 202; CHECK-NEXT: [[LENA1B:%.*]] = call i64 @strlen(i8* noundef nonnull dereferenceable(1) [[PA1B]]) 203; CHECK-NEXT: [[PLEN3:%.*]] = getelementptr i64, i64* [[PLEN]], i64 3 204; CHECK-NEXT: store i64 [[LENA1B]], i64* [[PLEN3]], align 4 205; CHECK-NEXT: ret void 206; 207 %pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 %I 208 %lena0a = call i64 @strlen(i8* %pa0a) 209 %plen0 = getelementptr i64, i64* %plen, i32 0 210 store i64 %lena0a, i64* %plen0 211 212 %pa0b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 %I 213 %lena0b = call i64 @strlen(i8* %pa0b) 214 %plen1 = getelementptr i64, i64* %plen, i32 1 215 store i64 %lena0b, i64* %plen1 216 217 %pa1a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 %I 218 %lena1a = call i64 @strlen(i8* %pa1a) 219 %plen2 = getelementptr i64, i64* %plen, i32 2 220 store i64 %lena1a, i64* %plen2 221 222 %pa1b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 %I 223 %lena1b = call i64 @strlen(i8* %pa1b) 224 %plen3 = getelementptr i64, i64* %plen, i32 3 225 store i64 %lena1b, i64* %plen3 226 227 ret void 228} 229