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