1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -basic-aa -loop-idiom < %s -S | FileCheck %s 3target datalayout = "e-p:40:64:64:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 4 5%struct.foo = type { i32, i32 } 6%struct.foo1 = type { i32, i32, i32 } 7%struct.foo2 = type { i32, i16, i16 } 8 9;void bar1(foo_t *f, unsigned n) { 10; for (unsigned i = 0; i < n; ++i) { 11; f[i].a = 0; 12; f[i].b = 0; 13; } 14;} 15define void @bar1(%struct.foo* %f, i32 %n) nounwind ssp { 16; CHECK-LABEL: @bar1( 17; CHECK-NEXT: entry: 18; CHECK-NEXT: [[F1:%.*]] = bitcast %struct.foo* [[F:%.*]] to i8* 19; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0 20; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] 21; CHECK: for.body.preheader: 22; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i32 [[N]], 3 23; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 4 [[F1]], i8 0, i32 [[TMP0]], i1 false) 24; CHECK-NEXT: br label [[FOR_BODY:%.*]] 25; CHECK: for.body: 26; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 27; CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 0 28; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 1 29; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1 30; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]] 31; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 32; CHECK: for.end.loopexit: 33; CHECK-NEXT: br label [[FOR_END]] 34; CHECK: for.end: 35; CHECK-NEXT: ret void 36; 37entry: 38 %cmp1 = icmp eq i32 %n, 0 39 br i1 %cmp1, label %for.end, label %for.body.preheader 40 41for.body.preheader: ; preds = %entry 42 br label %for.body 43 44for.body: ; preds = %for.body.preheader, %for.body 45 %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] 46 %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 0 47 store i32 0, i32* %a, align 4 48 %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 1 49 store i32 0, i32* %b, align 4 50 %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1 51 %exitcond = icmp ne i32 %indvars.iv.next, %n 52 br i1 %exitcond, label %for.body, label %for.end.loopexit 53 54for.end.loopexit: ; preds = %for.body 55 br label %for.end 56 57for.end: ; preds = %for.end.loopexit, %entry 58 ret void 59} 60 61;void bar2(foo_t *f, unsigned n) { 62; for (unsigned i = 0; i < n; ++i) { 63; f[i].b = 0; 64; f[i].a = 0; 65; } 66;} 67define void @bar2(%struct.foo* %f, i32 %n) nounwind ssp { 68; CHECK-LABEL: @bar2( 69; CHECK-NEXT: entry: 70; CHECK-NEXT: [[F1:%.*]] = bitcast %struct.foo* [[F:%.*]] to i8* 71; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0 72; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] 73; CHECK: for.body.preheader: 74; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i32 [[N]], 3 75; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 4 [[F1]], i8 0, i32 [[TMP0]], i1 false) 76; CHECK-NEXT: br label [[FOR_BODY:%.*]] 77; CHECK: for.body: 78; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 79; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 1 80; CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 0 81; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1 82; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]] 83; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 84; CHECK: for.end.loopexit: 85; CHECK-NEXT: br label [[FOR_END]] 86; CHECK: for.end: 87; CHECK-NEXT: ret void 88; 89entry: 90 %cmp1 = icmp eq i32 %n, 0 91 br i1 %cmp1, label %for.end, label %for.body.preheader 92 93for.body.preheader: ; preds = %entry 94 br label %for.body 95 96for.body: ; preds = %for.body.preheader, %for.body 97 %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] 98 %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 1 99 store i32 0, i32* %b, align 4 100 %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 0 101 store i32 0, i32* %a, align 4 102 %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1 103 %exitcond = icmp ne i32 %indvars.iv.next, %n 104 br i1 %exitcond, label %for.body, label %for.end.loopexit 105 106for.end.loopexit: ; preds = %for.body 107 br label %for.end 108 109for.end: ; preds = %for.end.loopexit, %entry 110 ret void 111} 112 113;void bar3(foo_t *f, unsigned n) { 114; for (unsigned i = n; i > 0; --i) { 115; f[i].a = 0; 116; f[i].b = 0; 117; } 118;} 119define void @bar3(%struct.foo* nocapture %f, i32 %n) nounwind ssp { 120; CHECK-LABEL: @bar3( 121; CHECK-NEXT: entry: 122; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0 123; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] 124; CHECK: for.body.preheader: 125; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr [[STRUCT_FOO:%.*]], %struct.foo* [[F:%.*]], i32 1 126; CHECK-NEXT: [[SCEVGEP1:%.*]] = bitcast %struct.foo* [[SCEVGEP]] to i8* 127; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i32 [[N]], 3 128; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 4 [[SCEVGEP1]], i8 0, i32 [[TMP0]], i1 false) 129; CHECK-NEXT: br label [[FOR_BODY:%.*]] 130; CHECK: for.body: 131; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[N]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 132; CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 0 133; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 1 134; CHECK-NEXT: [[DEC:%.*]] = add i32 [[INDVARS_IV]], -1 135; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[DEC]], 0 136; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i32 [[INDVARS_IV]], -1 137; CHECK-NEXT: br i1 [[CMP]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]] 138; CHECK: for.end.loopexit: 139; CHECK-NEXT: br label [[FOR_END]] 140; CHECK: for.end: 141; CHECK-NEXT: ret void 142; 143entry: 144 %cmp1 = icmp eq i32 %n, 0 145 br i1 %cmp1, label %for.end, label %for.body.preheader 146 147for.body.preheader: ; preds = %entry 148 br label %for.body 149 150for.body: ; preds = %for.body.preheader, %for.body 151 %indvars.iv = phi i32 [ %n, %for.body.preheader ], [ %indvars.iv.next, %for.body ] 152 %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 0 153 store i32 0, i32* %a, align 4 154 %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 1 155 store i32 0, i32* %b, align 4 156 %dec = add i32 %indvars.iv, -1 157 %cmp = icmp eq i32 %dec, 0 158 %indvars.iv.next = add nsw i32 %indvars.iv, -1 159 br i1 %cmp, label %for.end.loopexit, label %for.body 160 161for.end.loopexit: ; preds = %for.body 162 br label %for.end 163 164for.end: ; preds = %for.end.loopexit, %entry 165 ret void 166} 167 168;void bar4(foo_t *f, unsigned n) { 169; for (unsigned i = 0; i < n; ++i) { 170; f[i].a = 0; 171; f[i].b = 1; 172; } 173;} 174define void @bar4(%struct.foo* nocapture %f, i32 %n) nounwind ssp { 175; CHECK-LABEL: @bar4( 176; CHECK-NEXT: entry: 177; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0 178; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] 179; CHECK: for.body.preheader: 180; CHECK-NEXT: br label [[FOR_BODY:%.*]] 181; CHECK: for.body: 182; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 183; CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], %struct.foo* [[F:%.*]], i32 [[INDVARS_IV]], i32 0 184; CHECK-NEXT: store i32 0, i32* [[A]], align 4 185; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 1 186; CHECK-NEXT: store i32 1, i32* [[B]], align 4 187; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1 188; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]] 189; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 190; CHECK: for.end.loopexit: 191; CHECK-NEXT: br label [[FOR_END]] 192; CHECK: for.end: 193; CHECK-NEXT: ret void 194; 195entry: 196 %cmp1 = icmp eq i32 %n, 0 197 br i1 %cmp1, label %for.end, label %for.body.preheader 198 199for.body.preheader: ; preds = %entry 200 br label %for.body 201 202for.body: ; preds = %for.body.preheader, %for.body 203 %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] 204 %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 0 205 store i32 0, i32* %a, align 4 206 %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 1 207 store i32 1, i32* %b, align 4 208 %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1 209 %exitcond = icmp ne i32 %indvars.iv.next, %n 210 br i1 %exitcond, label %for.body, label %for.end.loopexit 211 212for.end.loopexit: ; preds = %for.body 213 br label %for.end 214 215for.end: ; preds = %for.end.loopexit, %entry 216 ret void 217} 218 219;void bar5(foo1_t *f, unsigned n) { 220; for (unsigned i = 0; i < n; ++i) { 221; f[i].a = 0; 222; f[i].b = 0; 223; } 224;} 225define void @bar5(%struct.foo1* nocapture %f, i32 %n) nounwind ssp { 226; CHECK-LABEL: @bar5( 227; CHECK-NEXT: entry: 228; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0 229; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] 230; CHECK: for.body.preheader: 231; CHECK-NEXT: br label [[FOR_BODY:%.*]] 232; CHECK: for.body: 233; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 234; CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO1:%.*]], %struct.foo1* [[F:%.*]], i32 [[INDVARS_IV]], i32 0 235; CHECK-NEXT: store i32 0, i32* [[A]], align 4 236; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO1]], %struct.foo1* [[F]], i32 [[INDVARS_IV]], i32 1 237; CHECK-NEXT: store i32 0, i32* [[B]], align 4 238; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1 239; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]] 240; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 241; CHECK: for.end.loopexit: 242; CHECK-NEXT: br label [[FOR_END]] 243; CHECK: for.end: 244; CHECK-NEXT: ret void 245; 246entry: 247 %cmp1 = icmp eq i32 %n, 0 248 br i1 %cmp1, label %for.end, label %for.body.preheader 249 250for.body.preheader: ; preds = %entry 251 br label %for.body 252 253for.body: ; preds = %for.body.preheader, %for.body 254 %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] 255 %a = getelementptr inbounds %struct.foo1, %struct.foo1* %f, i32 %indvars.iv, i32 0 256 store i32 0, i32* %a, align 4 257 %b = getelementptr inbounds %struct.foo1, %struct.foo1* %f, i32 %indvars.iv, i32 1 258 store i32 0, i32* %b, align 4 259 %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1 260 %exitcond = icmp ne i32 %indvars.iv.next, %n 261 br i1 %exitcond, label %for.body, label %for.end.loopexit 262 263for.end.loopexit: ; preds = %for.body 264 br label %for.end 265 266for.end: ; preds = %for.end.loopexit, %entry 267 ret void 268} 269 270;void bar6(foo2_t *f, unsigned n) { 271; for (unsigned i = 0; i < n; ++i) { 272; f[i].a = 0; 273; f[i].b = 0; 274; f[i].c = 0; 275; } 276;} 277define void @bar6(%struct.foo2* nocapture %f, i32 %n) nounwind ssp { 278; CHECK-LABEL: @bar6( 279; CHECK-NEXT: entry: 280; CHECK-NEXT: [[F1:%.*]] = bitcast %struct.foo2* [[F:%.*]] to i8* 281; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0 282; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] 283; CHECK: for.body.preheader: 284; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i32 [[N]], 3 285; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 4 [[F1]], i8 0, i32 [[TMP0]], i1 false) 286; CHECK-NEXT: br label [[FOR_BODY:%.*]] 287; CHECK: for.body: 288; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 289; CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO2:%.*]], %struct.foo2* [[F]], i32 [[INDVARS_IV]], i32 0 290; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO2]], %struct.foo2* [[F]], i32 [[INDVARS_IV]], i32 1 291; CHECK-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_FOO2]], %struct.foo2* [[F]], i32 [[INDVARS_IV]], i32 2 292; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1 293; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]] 294; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 295; CHECK: for.end.loopexit: 296; CHECK-NEXT: br label [[FOR_END]] 297; CHECK: for.end: 298; CHECK-NEXT: ret void 299; 300entry: 301 %cmp1 = icmp eq i32 %n, 0 302 br i1 %cmp1, label %for.end, label %for.body.preheader 303 304for.body.preheader: ; preds = %entry 305 br label %for.body 306 307for.body: ; preds = %for.body.preheader, %for.body 308 %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] 309 %a = getelementptr inbounds %struct.foo2, %struct.foo2* %f, i32 %indvars.iv, i32 0 310 store i32 0, i32* %a, align 4 311 %b = getelementptr inbounds %struct.foo2, %struct.foo2* %f, i32 %indvars.iv, i32 1 312 store i16 0, i16* %b, align 4 313 %c = getelementptr inbounds %struct.foo2, %struct.foo2* %f, i32 %indvars.iv, i32 2 314 store i16 0, i16* %c, align 2 315 %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1 316 %exitcond = icmp ne i32 %indvars.iv.next, %n 317 br i1 %exitcond, label %for.body, label %for.end.loopexit 318 319for.end.loopexit: ; preds = %for.body 320 br label %for.end 321 322for.end: ; preds = %for.end.loopexit, %entry 323 ret void 324} 325