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:64:64:64-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; For @test11_pattern 6; CHECK: @.memset_pattern = private unnamed_addr constant [4 x i32] [i32 1, i32 1, i32 1, i32 1] 7 8; For @test13_pattern 9; CHECK: @.memset_pattern.1 = private unnamed_addr constant [2 x i32*] [i32* @G, i32* @G] 10 11target triple = "x86_64-apple-darwin10.0.0" 12 13define void @test1(i8* %Base, i64 %Size) nounwind ssp { 14; CHECK-LABEL: @test1( 15; CHECK-NEXT: bb.nph: 16; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[BASE:%.*]], i8 0, i64 [[SIZE:%.*]], i1 false) 17; CHECK-NEXT: br label [[FOR_BODY:%.*]] 18; CHECK: for.body: 19; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 20; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[INDVAR]] 21; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 22; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]] 23; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 24; CHECK: for.end: 25; CHECK-NEXT: ret void 26; 27bb.nph: ; preds = %entry 28 br label %for.body 29 30for.body: ; preds = %bb.nph, %for.body 31 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 32 %I.0.014 = getelementptr i8, i8* %Base, i64 %indvar 33 store i8 0, i8* %I.0.014, align 1 34 %indvar.next = add i64 %indvar, 1 35 %exitcond = icmp eq i64 %indvar.next, %Size 36 br i1 %exitcond, label %for.end, label %for.body 37 38for.end: ; preds = %for.body, %entry 39 ret void 40} 41 42; Make sure memset is formed for larger than 1 byte stores, and that the 43; alignment of the store is preserved 44define void @test1_i16(i16* align 2 %Base, i64 %Size) nounwind ssp { 45; CHECK-LABEL: @test1_i16( 46; CHECK-NEXT: bb.nph: 47; CHECK-NEXT: [[BASE1:%.*]] = bitcast i16* [[BASE:%.*]] to i8* 48; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 1 49; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 2 [[BASE1]], i8 0, i64 [[TMP0]], i1 false) 50; CHECK-NEXT: br label [[FOR_BODY:%.*]] 51; CHECK: for.body: 52; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 53; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i16, i16* [[BASE]], i64 [[INDVAR]] 54; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 55; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]] 56; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 57; CHECK: for.end: 58; CHECK-NEXT: ret void 59; 60bb.nph: ; preds = %entry 61 br label %for.body 62 63for.body: ; preds = %bb.nph, %for.body 64 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 65 %I.0.014 = getelementptr i16, i16* %Base, i64 %indvar 66 store i16 0, i16* %I.0.014, align 2 67 %indvar.next = add i64 %indvar, 1 68 %exitcond = icmp eq i64 %indvar.next, %Size 69 br i1 %exitcond, label %for.end, label %for.body 70 71for.end: ; preds = %for.body, %entry 72 ret void 73} 74 75; This is a loop that was rotated but where the blocks weren't merged. This 76; shouldn't perturb us. 77define void @test1a(i8* %Base, i64 %Size) nounwind ssp { 78; CHECK-LABEL: @test1a( 79; CHECK-NEXT: bb.nph: 80; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[BASE:%.*]], i8 0, i64 [[SIZE:%.*]], i1 false) 81; CHECK-NEXT: br label [[FOR_BODY:%.*]] 82; CHECK: for.body: 83; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY_CONT:%.*]] ] 84; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[INDVAR]] 85; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 86; CHECK-NEXT: br label [[FOR_BODY_CONT]] 87; CHECK: for.body.cont: 88; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]] 89; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 90; CHECK: for.end: 91; CHECK-NEXT: ret void 92; 93bb.nph: ; preds = %entry 94 br label %for.body 95 96for.body: ; preds = %bb.nph, %for.body 97 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body.cont ] 98 %I.0.014 = getelementptr i8, i8* %Base, i64 %indvar 99 store i8 0, i8* %I.0.014, align 1 100 %indvar.next = add i64 %indvar, 1 101 br label %for.body.cont 102for.body.cont: 103 %exitcond = icmp eq i64 %indvar.next, %Size 104 br i1 %exitcond, label %for.end, label %for.body 105 106for.end: ; preds = %for.body, %entry 107 ret void 108} 109 110 111define void @test2(i32* %Base, i64 %Size) nounwind ssp { 112; CHECK-LABEL: @test2( 113; CHECK-NEXT: entry: 114; CHECK-NEXT: [[BASE1:%.*]] = bitcast i32* [[BASE:%.*]] to i8* 115; CHECK-NEXT: [[CMP10:%.*]] = icmp eq i64 [[SIZE:%.*]], 0 116; CHECK-NEXT: br i1 [[CMP10]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] 117; CHECK: for.body.preheader: 118; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE]], 2 119; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[BASE1]], i8 1, i64 [[TMP0]], i1 false) 120; CHECK-NEXT: br label [[FOR_BODY:%.*]] 121; CHECK: for.body: 122; CHECK-NEXT: [[I_011:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] 123; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i32, i32* [[BASE]], i64 [[I_011]] 124; CHECK-NEXT: [[INC]] = add nsw i64 [[I_011]], 1 125; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[SIZE]] 126; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]] 127; CHECK: for.end.loopexit: 128; CHECK-NEXT: br label [[FOR_END]] 129; CHECK: for.end: 130; CHECK-NEXT: ret void 131; 132entry: 133 %cmp10 = icmp eq i64 %Size, 0 134 br i1 %cmp10, label %for.end, label %for.body 135 136for.body: ; preds = %entry, %for.body 137 %i.011 = phi i64 [ %inc, %for.body ], [ 0, %entry ] 138 %add.ptr.i = getelementptr i32, i32* %Base, i64 %i.011 139 store i32 16843009, i32* %add.ptr.i, align 4 140 %inc = add nsw i64 %i.011, 1 141 %exitcond = icmp eq i64 %inc, %Size 142 br i1 %exitcond, label %for.end, label %for.body 143 144for.end: ; preds = %for.body, %entry 145 ret void 146} 147 148; This is a case where there is an extra may-aliased store in the loop, we can't 149; promote the memset. 150define void @test3(i32* %Base, i64 %Size, i8 *%MayAlias) nounwind ssp { 151; CHECK-LABEL: @test3( 152; CHECK-NEXT: entry: 153; CHECK-NEXT: br label [[FOR_BODY:%.*]] 154; CHECK: for.body: 155; CHECK-NEXT: [[I_011:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 156; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[I_011]] 157; CHECK-NEXT: store i32 16843009, i32* [[ADD_PTR_I]], align 4 158; CHECK-NEXT: store i8 42, i8* [[MAYALIAS:%.*]], align 1 159; CHECK-NEXT: [[INC]] = add nsw i64 [[I_011]], 1 160; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[SIZE:%.*]] 161; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 162; CHECK: for.end: 163; CHECK-NEXT: ret void 164; 165entry: 166 br label %for.body 167 168for.body: ; preds = %entry, %for.body 169 %i.011 = phi i64 [ %inc, %for.body ], [ 0, %entry ] 170 %add.ptr.i = getelementptr i32, i32* %Base, i64 %i.011 171 store i32 16843009, i32* %add.ptr.i, align 4 172 173 store i8 42, i8* %MayAlias 174 %inc = add nsw i64 %i.011, 1 175 %exitcond = icmp eq i64 %inc, %Size 176 br i1 %exitcond, label %for.end, label %for.body 177 178for.end: ; preds = %entry 179 ret void 180} 181 182; Make sure the first store in the loop is turned into a memset. 183define void @test4(i8* %Base) nounwind ssp { 184; CHECK-LABEL: @test4( 185; CHECK-NEXT: bb.nph: 186; CHECK-NEXT: [[BASE100:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i64 1000 187; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[BASE]], i8 0, i64 100, i1 false) 188; CHECK-NEXT: br label [[FOR_BODY:%.*]] 189; CHECK: for.body: 190; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 191; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[INDVAR]] 192; CHECK-NEXT: store i8 42, i8* [[BASE100]], align 1 193; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 194; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 100 195; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 196; CHECK: for.end: 197; CHECK-NEXT: ret void 198; 199bb.nph: ; preds = %entry 200 %Base100 = getelementptr i8, i8* %Base, i64 1000 201 br label %for.body 202 203for.body: ; preds = %bb.nph, %for.body 204 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 205 %I.0.014 = getelementptr i8, i8* %Base, i64 %indvar 206 store i8 0, i8* %I.0.014, align 1 207 208 ;; Store beyond the range memset, should be safe to promote. 209 store i8 42, i8* %Base100 210 211 %indvar.next = add i64 %indvar, 1 212 %exitcond = icmp eq i64 %indvar.next, 100 213 br i1 %exitcond, label %for.end, label %for.body 214 215for.end: ; preds = %for.body, %entry 216 ret void 217} 218 219; This can't be promoted: the memset is a store of a loop variant value. 220define void @test5(i8* %Base, i64 %Size) nounwind ssp { 221; CHECK-LABEL: @test5( 222; CHECK-NEXT: bb.nph: 223; CHECK-NEXT: br label [[FOR_BODY:%.*]] 224; CHECK: for.body: 225; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 226; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i64 [[INDVAR]] 227; CHECK-NEXT: [[V:%.*]] = trunc i64 [[INDVAR]] to i8 228; CHECK-NEXT: store i8 [[V]], i8* [[I_0_014]], align 1 229; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 230; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]] 231; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 232; CHECK: for.end: 233; CHECK-NEXT: ret void 234; 235bb.nph: ; preds = %entry 236 br label %for.body 237 238for.body: ; preds = %bb.nph, %for.body 239 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 240 %I.0.014 = getelementptr i8, i8* %Base, i64 %indvar 241 242 %V = trunc i64 %indvar to i8 243 store i8 %V, i8* %I.0.014, align 1 244 %indvar.next = add i64 %indvar, 1 245 %exitcond = icmp eq i64 %indvar.next, %Size 246 br i1 %exitcond, label %for.end, label %for.body 247 248for.end: ; preds = %for.body, %entry 249 ret void 250} 251 252 253;; memcpy formation 254define void @test6(i64 %Size) nounwind ssp { 255; CHECK-LABEL: @test6( 256; CHECK-NEXT: bb.nph: 257; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 1 258; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 1 259; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[DEST]], i8* align 1 [[BASE]], i64 [[SIZE:%.*]], i1 false) 260; CHECK-NEXT: br label [[FOR_BODY:%.*]] 261; CHECK: for.body: 262; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 263; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[INDVAR]] 264; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, i8* [[DEST]], i64 [[INDVAR]] 265; CHECK-NEXT: [[V:%.*]] = load i8, i8* [[I_0_014]], align 1 266; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 267; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]] 268; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 269; CHECK: for.end: 270; CHECK-NEXT: ret void 271; 272bb.nph: 273 %Base = alloca i8, i32 10000 274 %Dest = alloca i8, i32 10000 275 br label %for.body 276 277for.body: ; preds = %bb.nph, %for.body 278 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 279 %I.0.014 = getelementptr i8, i8* %Base, i64 %indvar 280 %DestI = getelementptr i8, i8* %Dest, i64 %indvar 281 %V = load i8, i8* %I.0.014, align 1 282 store i8 %V, i8* %DestI, align 1 283 %indvar.next = add i64 %indvar, 1 284 %exitcond = icmp eq i64 %indvar.next, %Size 285 br i1 %exitcond, label %for.end, label %for.body 286 287for.end: ; preds = %for.body, %entry 288 ret void 289} 290 291;; memcpy formation, check alignment 292define void @test6_dest_align(i32* noalias align 1 %Base, i32* noalias align 4 %Dest, i64 %Size) nounwind ssp { 293; CHECK-LABEL: @test6_dest_align( 294; CHECK-NEXT: bb.nph: 295; CHECK-NEXT: [[DEST1:%.*]] = bitcast i32* [[DEST:%.*]] to i8* 296; CHECK-NEXT: [[BASE2:%.*]] = bitcast i32* [[BASE:%.*]] to i8* 297; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 2 298; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[DEST1]], i8* align 1 [[BASE2]], i64 [[TMP0]], i1 false) 299; CHECK-NEXT: br label [[FOR_BODY:%.*]] 300; CHECK: for.body: 301; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 302; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, i32* [[BASE]], i64 [[INDVAR]] 303; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, i32* [[DEST]], i64 [[INDVAR]] 304; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[I_0_014]], align 1 305; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 306; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]] 307; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 308; CHECK: for.end: 309; CHECK-NEXT: ret void 310; 311bb.nph: 312 br label %for.body 313 314for.body: ; preds = %bb.nph, %for.body 315 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 316 %I.0.014 = getelementptr i32, i32* %Base, i64 %indvar 317 %DestI = getelementptr i32, i32* %Dest, i64 %indvar 318 %V = load i32, i32* %I.0.014, align 1 319 store i32 %V, i32* %DestI, align 4 320 %indvar.next = add i64 %indvar, 1 321 %exitcond = icmp eq i64 %indvar.next, %Size 322 br i1 %exitcond, label %for.end, label %for.body 323 324for.end: ; preds = %for.body, %entry 325 ret void 326} 327 328;; memcpy formation, check alignment 329define void @test6_src_align(i32* noalias align 4 %Base, i32* noalias align 1 %Dest, i64 %Size) nounwind ssp { 330; CHECK-LABEL: @test6_src_align( 331; CHECK-NEXT: bb.nph: 332; CHECK-NEXT: [[DEST1:%.*]] = bitcast i32* [[DEST:%.*]] to i8* 333; CHECK-NEXT: [[BASE2:%.*]] = bitcast i32* [[BASE:%.*]] to i8* 334; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 2 335; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[DEST1]], i8* align 4 [[BASE2]], i64 [[TMP0]], i1 false) 336; CHECK-NEXT: br label [[FOR_BODY:%.*]] 337; CHECK: for.body: 338; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 339; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, i32* [[BASE]], i64 [[INDVAR]] 340; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, i32* [[DEST]], i64 [[INDVAR]] 341; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[I_0_014]], align 4 342; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 343; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]] 344; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 345; CHECK: for.end: 346; CHECK-NEXT: ret void 347; 348bb.nph: 349 br label %for.body 350 351for.body: ; preds = %bb.nph, %for.body 352 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 353 %I.0.014 = getelementptr i32, i32* %Base, i64 %indvar 354 %DestI = getelementptr i32, i32* %Dest, i64 %indvar 355 %V = load i32, i32* %I.0.014, align 4 356 store i32 %V, i32* %DestI, align 1 357 %indvar.next = add i64 %indvar, 1 358 %exitcond = icmp eq i64 %indvar.next, %Size 359 br i1 %exitcond, label %for.end, label %for.body 360 361for.end: ; preds = %for.body, %entry 362 ret void 363} 364 365 366; This is a loop that was rotated but where the blocks weren't merged. This 367; shouldn't perturb us. 368define void @test7(i8* %Base, i64 %Size) nounwind ssp { 369; CHECK-LABEL: @test7( 370; CHECK-NEXT: bb.nph: 371; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[BASE:%.*]], i8 0, i64 [[SIZE:%.*]], i1 false) 372; CHECK-NEXT: br label [[FOR_BODY:%.*]] 373; CHECK: for.body: 374; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY_CONT:%.*]] ] 375; CHECK-NEXT: br label [[FOR_BODY_CONT]] 376; CHECK: for.body.cont: 377; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[INDVAR]] 378; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 379; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]] 380; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 381; CHECK: for.end: 382; CHECK-NEXT: ret void 383; 384bb.nph: ; preds = %entry 385 br label %for.body 386 387for.body: ; preds = %bb.nph, %for.body 388 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body.cont ] 389 br label %for.body.cont 390for.body.cont: 391 %I.0.014 = getelementptr i8, i8* %Base, i64 %indvar 392 store i8 0, i8* %I.0.014, align 1 393 %indvar.next = add i64 %indvar, 1 394 %exitcond = icmp eq i64 %indvar.next, %Size 395 br i1 %exitcond, label %for.end, label %for.body 396 397for.end: ; preds = %for.body, %entry 398 ret void 399} 400 401; This is a loop should not be transformed, it only executes one iteration. 402define void @test8(i64* %Ptr, i64 %Size) nounwind ssp { 403; CHECK-LABEL: @test8( 404; CHECK-NEXT: bb.nph: 405; CHECK-NEXT: br label [[FOR_BODY:%.*]] 406; CHECK: for.body: 407; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 408; CHECK-NEXT: [[PI:%.*]] = getelementptr i64, i64* [[PTR:%.*]], i64 [[INDVAR]] 409; CHECK-NEXT: store i64 0, i64* [[PI]], align 8 410; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 411; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 1 412; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 413; CHECK: for.end: 414; CHECK-NEXT: ret void 415; 416bb.nph: ; preds = %entry 417 br label %for.body 418 419for.body: ; preds = %bb.nph, %for.body 420 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 421 %PI = getelementptr i64, i64* %Ptr, i64 %indvar 422 store i64 0, i64 *%PI 423 %indvar.next = add i64 %indvar, 1 424 %exitcond = icmp eq i64 %indvar.next, 1 425 br i1 %exitcond, label %for.end, label %for.body 426 427for.end: ; preds = %for.body, %entry 428 ret void 429} 430 431declare i8* @external(i8*) 432 433;; This cannot be transformed into a memcpy, because the read-from location is 434;; mutated by the loop. 435define void @test9(i64 %Size) nounwind ssp { 436; CHECK-LABEL: @test9( 437; CHECK-NEXT: bb.nph: 438; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 1 439; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 1 440; CHECK-NEXT: [[BASEALIAS:%.*]] = call i8* @external(i8* [[BASE]]) 441; CHECK-NEXT: br label [[FOR_BODY:%.*]] 442; CHECK: for.body: 443; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 444; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[INDVAR]] 445; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, i8* [[DEST]], i64 [[INDVAR]] 446; CHECK-NEXT: [[V:%.*]] = load i8, i8* [[I_0_014]], align 1 447; CHECK-NEXT: store i8 [[V]], i8* [[DESTI]], align 1 448; CHECK-NEXT: store i8 4, i8* [[BASEALIAS]], align 1 449; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 450; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]] 451; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 452; CHECK: for.end: 453; CHECK-NEXT: ret void 454; 455bb.nph: 456 %Base = alloca i8, i32 10000 457 %Dest = alloca i8, i32 10000 458 459 %BaseAlias = call i8* @external(i8* %Base) 460 br label %for.body 461 462for.body: ; preds = %bb.nph, %for.body 463 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ] 464 %I.0.014 = getelementptr i8, i8* %Base, i64 %indvar 465 %DestI = getelementptr i8, i8* %Dest, i64 %indvar 466 %V = load i8, i8* %I.0.014, align 1 467 store i8 %V, i8* %DestI, align 1 468 469 ;; This store can clobber the input. 470 store i8 4, i8* %BaseAlias 471 472 %indvar.next = add i64 %indvar, 1 473 %exitcond = icmp eq i64 %indvar.next, %Size 474 br i1 %exitcond, label %for.end, label %for.body 475 476for.end: ; preds = %for.body, %entry 477 ret void 478} 479 480; Two dimensional nested loop should be promoted to one big memset. 481define void @test10(i8* %X) nounwind ssp { 482; CHECK-LABEL: @test10( 483; CHECK-NEXT: entry: 484; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[X:%.*]], i8 0, i64 10000, i1 false) 485; CHECK-NEXT: br label [[BB_NPH:%.*]] 486; CHECK: bb.nph: 487; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[FOR_INC10:%.*]] ], [ 0, [[ENTRY:%.*]] ] 488; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC12:%.*]], [[FOR_INC10]] ] 489; CHECK-NEXT: [[TMP0:%.*]] = mul nuw nsw i64 [[INDVAR]], 100 490; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* [[X]], i64 [[TMP0]] 491; CHECK-NEXT: br label [[FOR_BODY5:%.*]] 492; CHECK: for.body5: 493; CHECK-NEXT: [[J_02:%.*]] = phi i32 [ 0, [[BB_NPH]] ], [ [[INC:%.*]], [[FOR_BODY5]] ] 494; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[I_04]], 100 495; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[J_02]], [[MUL]] 496; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[ADD]] to i64 497; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X]], i64 [[IDXPROM]] 498; CHECK-NEXT: [[INC]] = add nsw i32 [[J_02]], 1 499; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i32 [[INC]], 100 500; CHECK-NEXT: br i1 [[CMP4]], label [[FOR_INC10]], label [[FOR_BODY5]] 501; CHECK: for.inc10: 502; CHECK-NEXT: [[INC12]] = add nsw i32 [[I_04]], 1 503; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[INC12]], 100 504; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 505; CHECK-NEXT: br i1 [[CMP]], label [[FOR_END13:%.*]], label [[BB_NPH]] 506; CHECK: for.end13: 507; CHECK-NEXT: ret void 508; 509entry: 510 br label %bb.nph 511 512bb.nph: ; preds = %entry, %for.inc10 513 %i.04 = phi i32 [ 0, %entry ], [ %inc12, %for.inc10 ] 514 br label %for.body5 515 516for.body5: ; preds = %for.body5, %bb.nph 517 %j.02 = phi i32 [ 0, %bb.nph ], [ %inc, %for.body5 ] 518 %mul = mul nsw i32 %i.04, 100 519 %add = add nsw i32 %j.02, %mul 520 %idxprom = sext i32 %add to i64 521 %arrayidx = getelementptr inbounds i8, i8* %X, i64 %idxprom 522 store i8 0, i8* %arrayidx, align 1 523 %inc = add nsw i32 %j.02, 1 524 %cmp4 = icmp eq i32 %inc, 100 525 br i1 %cmp4, label %for.inc10, label %for.body5 526 527for.inc10: ; preds = %for.body5 528 %inc12 = add nsw i32 %i.04, 1 529 %cmp = icmp eq i32 %inc12, 100 530 br i1 %cmp, label %for.end13, label %bb.nph 531 532for.end13: ; preds = %for.inc10 533 ret void 534} 535 536; On darwin10 (which is the triple in this .ll file) this loop can be turned 537; into a memset_pattern call. 538; rdar://9009151 539define void @test11_pattern(i32* nocapture %P) nounwind ssp { 540; CHECK-LABEL: @test11_pattern( 541; CHECK-NEXT: entry: 542; CHECK-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to i8* 543; CHECK-NEXT: call void @memset_pattern16(i8* [[P1]], i8* bitcast ([4 x i32]* @.memset_pattern to i8*), i64 40000) 544; CHECK-NEXT: br label [[FOR_BODY:%.*]] 545; CHECK: for.body: 546; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 547; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P]], i64 [[INDVAR]] 548; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 549; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 10000 550; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 551; CHECK: for.end: 552; CHECK-NEXT: ret void 553; 554entry: 555 br label %for.body 556 557for.body: ; preds = %entry, %for.body 558 %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ] 559 %arrayidx = getelementptr i32, i32* %P, i64 %indvar 560 store i32 1, i32* %arrayidx, align 4 561 %indvar.next = add i64 %indvar, 1 562 %exitcond = icmp eq i64 %indvar.next, 10000 563 br i1 %exitcond, label %for.end, label %for.body 564 565for.end: ; preds = %for.body 566 ret void 567} 568 569; Store of null should turn into memset of zero. 570define void @test12(i32** nocapture %P) nounwind ssp { 571; CHECK-LABEL: @test12( 572; CHECK-NEXT: entry: 573; CHECK-NEXT: [[P1:%.*]] = bitcast i32** [[P:%.*]] to i8* 574; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[P1]], i8 0, i64 80000, i1 false) 575; CHECK-NEXT: br label [[FOR_BODY:%.*]] 576; CHECK: for.body: 577; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 578; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32*, i32** [[P]], i64 [[INDVAR]] 579; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 580; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 10000 581; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 582; CHECK: for.end: 583; CHECK-NEXT: ret void 584; 585entry: 586 br label %for.body 587 588for.body: ; preds = %entry, %for.body 589 %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ] 590 %arrayidx = getelementptr i32*, i32** %P, i64 %indvar 591 store i32* null, i32** %arrayidx, align 4 592 %indvar.next = add i64 %indvar, 1 593 %exitcond = icmp eq i64 %indvar.next, 10000 594 br i1 %exitcond, label %for.end, label %for.body 595 596for.end: ; preds = %for.body 597 ret void 598} 599 600@G = global i32 5 601 602; This store-of-address loop can be turned into a memset_pattern call. 603; rdar://9009151 604define void @test13_pattern(i32** nocapture %P) nounwind ssp { 605; CHECK-LABEL: @test13_pattern( 606; CHECK-NEXT: entry: 607; CHECK-NEXT: [[P1:%.*]] = bitcast i32** [[P:%.*]] to i8* 608; CHECK-NEXT: call void @memset_pattern16(i8* [[P1]], i8* bitcast ([2 x i32*]* @.memset_pattern.1 to i8*), i64 80000) 609; CHECK-NEXT: br label [[FOR_BODY:%.*]] 610; CHECK: for.body: 611; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ] 612; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32*, i32** [[P]], i64 [[INDVAR]] 613; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 614; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 10000 615; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]] 616; CHECK: for.end: 617; CHECK-NEXT: ret void 618; 619entry: 620 br label %for.body 621 622for.body: ; preds = %entry, %for.body 623 %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ] 624 %arrayidx = getelementptr i32*, i32** %P, i64 %indvar 625 store i32* @G, i32** %arrayidx, align 4 626 %indvar.next = add i64 %indvar, 1 627 %exitcond = icmp eq i64 %indvar.next, 10000 628 br i1 %exitcond, label %for.end, label %for.body 629 630for.end: ; preds = %for.body 631 ret void 632} 633 634 635 636; PR9815 - This is a partial overlap case that cannot be safely transformed 637; into a memcpy. 638@g_50 = global [7 x i32] [i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0], align 16 639 640define i32 @test14() nounwind { 641; CHECK-LABEL: @test14( 642; CHECK-NEXT: entry: 643; CHECK-NEXT: br label [[FOR_BODY:%.*]] 644; CHECK: for.body: 645; CHECK-NEXT: [[T5:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 646; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[T5]], 4 647; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[ADD]] to i64 648; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @g_50, i32 0, i64 [[IDXPROM]] 649; CHECK-NEXT: [[T2:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 650; CHECK-NEXT: [[ADD4:%.*]] = add nsw i32 [[T5]], 5 651; CHECK-NEXT: [[IDXPROM5:%.*]] = sext i32 [[ADD4]] to i64 652; CHECK-NEXT: [[ARRAYIDX6:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @g_50, i32 0, i64 [[IDXPROM5]] 653; CHECK-NEXT: store i32 [[T2]], i32* [[ARRAYIDX6]], align 4 654; CHECK-NEXT: [[INC]] = add nsw i32 [[T5]], 1 655; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 2 656; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 657; CHECK: for.end: 658; CHECK-NEXT: [[T8:%.*]] = load i32, i32* getelementptr inbounds ([7 x i32], [7 x i32]* @g_50, i32 0, i64 6), align 4 659; CHECK-NEXT: ret i32 [[T8]] 660; 661entry: 662 br label %for.body 663 664for.body: ; preds = %for.inc, %for.body.lr.ph 665 %t5 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 666 %add = add nsw i32 %t5, 4 667 %idxprom = sext i32 %add to i64 668 %arrayidx = getelementptr inbounds [7 x i32], [7 x i32]* @g_50, i32 0, i64 %idxprom 669 %t2 = load i32, i32* %arrayidx, align 4 670 %add4 = add nsw i32 %t5, 5 671 %idxprom5 = sext i32 %add4 to i64 672 %arrayidx6 = getelementptr inbounds [7 x i32], [7 x i32]* @g_50, i32 0, i64 %idxprom5 673 store i32 %t2, i32* %arrayidx6, align 4 674 %inc = add nsw i32 %t5, 1 675 %cmp = icmp slt i32 %inc, 2 676 br i1 %cmp, label %for.body, label %for.end 677 678for.end: ; preds = %for.inc 679 %t8 = load i32, i32* getelementptr inbounds ([7 x i32], [7 x i32]* @g_50, i32 0, i64 6), align 4 680 ret i32 %t8 681 682} 683 684define void @PR14241(i32* %s, i64 %size) { 685; Ensure that we don't form a memcpy for strided loops. Briefly, when we taught 686; LoopIdiom about memmove and strided loops, this got miscompiled into a memcpy 687; instead of a memmove. If we get the memmove transform back, this will catch 688; regressions. 689; 690; CHECK-LABEL: @PR14241( 691; CHECK-NEXT: entry: 692; CHECK-NEXT: [[END_IDX:%.*]] = add i64 [[SIZE:%.*]], -1 693; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr inbounds i32, i32* [[S:%.*]], i64 [[END_IDX]] 694; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 695; CHECK: while.body: 696; CHECK-NEXT: [[PHI_PTR:%.*]] = phi i32* [ [[S]], [[ENTRY:%.*]] ], [ [[NEXT_PTR:%.*]], [[WHILE_BODY]] ] 697; CHECK-NEXT: [[SRC_PTR:%.*]] = getelementptr inbounds i32, i32* [[PHI_PTR]], i64 1 698; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[SRC_PTR]], align 4 699; CHECK-NEXT: [[DST_PTR:%.*]] = getelementptr inbounds i32, i32* [[PHI_PTR]], i64 0 700; CHECK-NEXT: store i32 [[VAL]], i32* [[DST_PTR]], align 4 701; CHECK-NEXT: [[NEXT_PTR]] = getelementptr inbounds i32, i32* [[PHI_PTR]], i64 1 702; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[NEXT_PTR]], [[END_PTR]] 703; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[WHILE_BODY]] 704; CHECK: exit: 705; CHECK-NEXT: ret void 706; 707 708entry: 709 %end.idx = add i64 %size, -1 710 %end.ptr = getelementptr inbounds i32, i32* %s, i64 %end.idx 711 br label %while.body 712; FIXME: When we regain the ability to form a memmove here, this test should be 713; reversed and turned into a positive assertion. 714 715while.body: 716 %phi.ptr = phi i32* [ %s, %entry ], [ %next.ptr, %while.body ] 717 %src.ptr = getelementptr inbounds i32, i32* %phi.ptr, i64 1 718 %val = load i32, i32* %src.ptr, align 4 719 %dst.ptr = getelementptr inbounds i32, i32* %phi.ptr, i64 0 720 store i32 %val, i32* %dst.ptr, align 4 721 %next.ptr = getelementptr inbounds i32, i32* %phi.ptr, i64 1 722 %cmp = icmp eq i32* %next.ptr, %end.ptr 723 br i1 %cmp, label %exit, label %while.body 724 725exit: 726 ret void 727} 728 729; Recognize loops with a negative stride. 730define void @test15(i32* nocapture %f) { 731; CHECK-LABEL: @test15( 732; CHECK-NEXT: entry: 733; CHECK-NEXT: [[F1:%.*]] = bitcast i32* [[F:%.*]] to i8* 734; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[F1]], i8 0, i64 262148, i1 false) 735; CHECK-NEXT: br label [[FOR_BODY:%.*]] 736; CHECK: for.body: 737; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 65536, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 738; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[F]], i64 [[INDVARS_IV]] 739; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 740; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[INDVARS_IV]], 0 741; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] 742; CHECK: for.cond.cleanup: 743; CHECK-NEXT: ret void 744; 745entry: 746 br label %for.body 747 748for.body: 749 %indvars.iv = phi i64 [ 65536, %entry ], [ %indvars.iv.next, %for.body ] 750 %arrayidx = getelementptr inbounds i32, i32* %f, i64 %indvars.iv 751 store i32 0, i32* %arrayidx, align 4 752 %indvars.iv.next = add nsw i64 %indvars.iv, -1 753 %cmp = icmp sgt i64 %indvars.iv, 0 754 br i1 %cmp, label %for.body, label %for.cond.cleanup 755 756for.cond.cleanup: 757 ret void 758} 759 760; Loop with a negative stride. Verify an aliasing write to f[65536] prevents 761; the creation of a memset. 762define void @test16(i32* nocapture %f) { 763; CHECK-LABEL: @test16( 764; CHECK-NEXT: entry: 765; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[F:%.*]], i64 65536 766; CHECK-NEXT: br label [[FOR_BODY:%.*]] 767; CHECK: for.body: 768; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 65536, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 769; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[F]], i64 [[INDVARS_IV]] 770; CHECK-NEXT: store i32 0, i32* [[ARRAYIDX]], align 4 771; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX1]], align 4 772; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 773; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[INDVARS_IV]], 0 774; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] 775; CHECK: for.cond.cleanup: 776; CHECK-NEXT: ret void 777; 778entry: 779 %arrayidx1 = getelementptr inbounds i32, i32* %f, i64 65536 780 br label %for.body 781 782for.body: ; preds = %entry, %for.body 783 %indvars.iv = phi i64 [ 65536, %entry ], [ %indvars.iv.next, %for.body ] 784 %arrayidx = getelementptr inbounds i32, i32* %f, i64 %indvars.iv 785 store i32 0, i32* %arrayidx, align 4 786 store i32 1, i32* %arrayidx1, align 4 787 %indvars.iv.next = add nsw i64 %indvars.iv, -1 788 %cmp = icmp sgt i64 %indvars.iv, 0 789 br i1 %cmp, label %for.body, label %for.cond.cleanup 790 791for.cond.cleanup: ; preds = %for.body 792 ret void 793} 794 795; Handle memcpy-able loops with negative stride. 796define noalias i32* @test17(i32* nocapture readonly %a, i32 %c) { 797; CHECK-LABEL: @test17( 798; CHECK-NEXT: entry: 799; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[C:%.*]] to i64 800; CHECK-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2 801; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @malloc(i64 [[MUL]]) 802; CHECK-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* 803; CHECK-NEXT: [[TOBOOL_9:%.*]] = icmp eq i32 [[C]], 0 804; CHECK-NEXT: br i1 [[TOBOOL_9]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] 805; CHECK: while.body.preheader: 806; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[C]] to i64 807; CHECK-NEXT: [[TMP2:%.*]] = shl nsw i64 [[TMP1]], 2 808; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[TMP2]], -4 809; CHECK-NEXT: [[TMP4:%.*]] = add nsw i32 [[C]], -1 810; CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[TMP4]] to i64 811; CHECK-NEXT: [[TMP6:%.*]] = shl nuw nsw i64 [[TMP5]], 2 812; CHECK-NEXT: [[TMP7:%.*]] = sub i64 [[TMP3]], [[TMP6]] 813; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* [[CALL]], i64 [[TMP7]] 814; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[TMP1]], -1 815; CHECK-NEXT: [[TMP9:%.*]] = sub i64 [[TMP8]], [[TMP5]] 816; CHECK-NEXT: [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[A:%.*]], i64 [[TMP9]] 817; CHECK-NEXT: [[SCEVGEP12:%.*]] = bitcast i32* [[SCEVGEP1]] to i8* 818; CHECK-NEXT: [[TMP10:%.*]] = zext i32 [[C]] to i64 819; CHECK-NEXT: [[TMP11:%.*]] = shl nuw nsw i64 [[TMP10]], 2 820; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[SCEVGEP]], i8* align 4 [[SCEVGEP12]], i64 [[TMP11]], i1 false) 821; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 822; CHECK: while.body: 823; CHECK-NEXT: [[DEC10_IN:%.*]] = phi i32 [ [[DEC10:%.*]], [[WHILE_BODY]] ], [ [[C]], [[WHILE_BODY_PREHEADER]] ] 824; CHECK-NEXT: [[DEC10]] = add nsw i32 [[DEC10_IN]], -1 825; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[DEC10]] to i64 826; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[IDXPROM]] 827; CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 828; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[IDXPROM]] 829; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[DEC10]], 0 830; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]] 831; CHECK: while.end.loopexit: 832; CHECK-NEXT: br label [[WHILE_END]] 833; CHECK: while.end: 834; CHECK-NEXT: ret i32* [[TMP0]] 835; 836entry: 837 %conv = sext i32 %c to i64 838 %mul = shl nsw i64 %conv, 2 839 %call = tail call noalias i8* @malloc(i64 %mul) 840 %0 = bitcast i8* %call to i32* 841 %tobool.9 = icmp eq i32 %c, 0 842 br i1 %tobool.9, label %while.end, label %while.body.preheader 843 844while.body.preheader: ; preds = %entry 845 br label %while.body 846 847while.body: ; preds = %while.body.preheader, %while.body 848 %dec10.in = phi i32 [ %dec10, %while.body ], [ %c, %while.body.preheader ] 849 %dec10 = add nsw i32 %dec10.in, -1 850 %idxprom = sext i32 %dec10 to i64 851 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom 852 %1 = load i32, i32* %arrayidx, align 4 853 %arrayidx2 = getelementptr inbounds i32, i32* %0, i64 %idxprom 854 store i32 %1, i32* %arrayidx2, align 4 855 %tobool = icmp eq i32 %dec10, 0 856 br i1 %tobool, label %while.end.loopexit, label %while.body 857 858while.end.loopexit: ; preds = %while.body 859 br label %while.end 860 861while.end: ; preds = %while.end.loopexit, %entry 862 ret i32* %0 863} 864 865declare noalias i8* @malloc(i64) 866 867; Handle memcpy-able loops with negative stride. 868; void test18(unsigned *__restrict__ a, unsigned *__restrict__ b) { 869; for (int i = 2047; i >= 0; --i) { 870; a[i] = b[i]; 871; } 872; } 873define void @test18(i32* noalias nocapture %a, i32* noalias nocapture readonly %b) #0 { 874; CHECK-LABEL: @test18( 875; CHECK-NEXT: entry: 876; CHECK-NEXT: [[A1:%.*]] = bitcast i32* [[A:%.*]] to i8* 877; CHECK-NEXT: [[B2:%.*]] = bitcast i32* [[B:%.*]] to i8* 878; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[A1]], i8* align 4 [[B2]], i64 8192, i1 false) 879; CHECK-NEXT: br label [[FOR_BODY:%.*]] 880; CHECK: for.body: 881; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 2047, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 882; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] 883; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 884; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] 885; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 886; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[INDVARS_IV]], 0 887; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] 888; CHECK: for.cond.cleanup: 889; CHECK-NEXT: ret void 890; 891entry: 892 br label %for.body 893 894for.body: ; preds = %entry, %for.body 895 %indvars.iv = phi i64 [ 2047, %entry ], [ %indvars.iv.next, %for.body ] 896 %arrayidx = getelementptr inbounds i32, i32* %b, i64 %indvars.iv 897 %0 = load i32, i32* %arrayidx, align 4 898 %arrayidx2 = getelementptr inbounds i32, i32* %a, i64 %indvars.iv 899 store i32 %0, i32* %arrayidx2, align 4 900 %indvars.iv.next = add nsw i64 %indvars.iv, -1 901 %cmp = icmp sgt i64 %indvars.iv, 0 902 br i1 %cmp, label %for.body, label %for.cond.cleanup 903 904for.cond.cleanup: ; preds = %for.body 905 ret void 906} 907 908; Two dimensional nested loop with negative stride should be promoted to one big memset. 909define void @test19(i8* nocapture %X) { 910; CHECK-LABEL: @test19( 911; CHECK-NEXT: entry: 912; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[X:%.*]], i8 0, i64 10000, i1 false) 913; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]] 914; CHECK: for.cond1.preheader: 915; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[FOR_INC4:%.*]] ], [ 0, [[ENTRY:%.*]] ] 916; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 99, [[ENTRY]] ], [ [[DEC5:%.*]], [[FOR_INC4]] ] 917; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i64 [[INDVAR]], -100 918; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 9900 919; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* [[X]], i64 [[TMP1]] 920; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[I_06]], 100 921; CHECK-NEXT: br label [[FOR_BODY3:%.*]] 922; CHECK: for.body3: 923; CHECK-NEXT: [[J_05:%.*]] = phi i32 [ 99, [[FOR_COND1_PREHEADER]] ], [ [[DEC:%.*]], [[FOR_BODY3]] ] 924; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[J_05]], [[MUL]] 925; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[ADD]] to i64 926; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X]], i64 [[IDXPROM]] 927; CHECK-NEXT: [[DEC]] = add nsw i32 [[J_05]], -1 928; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[J_05]], 0 929; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_INC4]] 930; CHECK: for.inc4: 931; CHECK-NEXT: [[DEC5]] = add nsw i32 [[I_06]], -1 932; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[I_06]], 0 933; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 934; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND1_PREHEADER]], label [[FOR_END6:%.*]] 935; CHECK: for.end6: 936; CHECK-NEXT: ret void 937; 938entry: 939 br label %for.cond1.preheader 940 941for.cond1.preheader: ; preds = %entry, %for.inc4 942 %i.06 = phi i32 [ 99, %entry ], [ %dec5, %for.inc4 ] 943 %mul = mul nsw i32 %i.06, 100 944 br label %for.body3 945 946for.body3: ; preds = %for.cond1.preheader, %for.body3 947 %j.05 = phi i32 [ 99, %for.cond1.preheader ], [ %dec, %for.body3 ] 948 %add = add nsw i32 %j.05, %mul 949 %idxprom = sext i32 %add to i64 950 %arrayidx = getelementptr inbounds i8, i8* %X, i64 %idxprom 951 store i8 0, i8* %arrayidx, align 1 952 %dec = add nsw i32 %j.05, -1 953 %cmp2 = icmp sgt i32 %j.05, 0 954 br i1 %cmp2, label %for.body3, label %for.inc4 955 956for.inc4: ; preds = %for.body3 957 %dec5 = add nsw i32 %i.06, -1 958 %cmp = icmp sgt i32 %i.06, 0 959 br i1 %cmp, label %for.cond1.preheader, label %for.end6 960 961for.end6: ; preds = %for.inc4 962 ret void 963} 964 965; Handle loops where the trip count is a narrow integer that needs to be 966; extended. 967define void @form_memset_narrow_size(i64* %ptr, i32 %size) { 968; CHECK-LABEL: @form_memset_narrow_size( 969; CHECK-NEXT: entry: 970; CHECK-NEXT: [[PTR1:%.*]] = bitcast i64* [[PTR:%.*]] to i8* 971; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[SIZE:%.*]], 0 972; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP_PH:%.*]], label [[EXIT:%.*]] 973; CHECK: loop.ph: 974; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[SIZE]] to i64 975; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 3 976; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[PTR1]], i8 0, i64 [[TMP1]], i1 false) 977; CHECK-NEXT: br label [[LOOP_BODY:%.*]] 978; CHECK: loop.body: 979; CHECK-NEXT: [[STOREMERGE4:%.*]] = phi i32 [ 0, [[LOOP_PH]] ], [ [[INC:%.*]], [[LOOP_BODY]] ] 980; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[STOREMERGE4]] to i64 981; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[PTR]], i64 [[IDXPROM]] 982; CHECK-NEXT: [[INC]] = add nsw i32 [[STOREMERGE4]], 1 983; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[INC]], [[SIZE]] 984; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_BODY]], label [[LOOP_EXIT:%.*]] 985; CHECK: loop.exit: 986; CHECK-NEXT: br label [[EXIT]] 987; CHECK: exit: 988; CHECK-NEXT: ret void 989; 990entry: 991 %cmp1 = icmp sgt i32 %size, 0 992 br i1 %cmp1, label %loop.ph, label %exit 993 994loop.ph: 995 br label %loop.body 996 997loop.body: 998 %storemerge4 = phi i32 [ 0, %loop.ph ], [ %inc, %loop.body ] 999 %idxprom = sext i32 %storemerge4 to i64 1000 %arrayidx = getelementptr inbounds i64, i64* %ptr, i64 %idxprom 1001 store i64 0, i64* %arrayidx, align 8 1002 %inc = add nsw i32 %storemerge4, 1 1003 %cmp2 = icmp slt i32 %inc, %size 1004 br i1 %cmp2, label %loop.body, label %loop.exit 1005 1006loop.exit: 1007 br label %exit 1008 1009exit: 1010 ret void 1011} 1012 1013define void @form_memcpy_narrow_size(i64* noalias %dst, i64* noalias %src, i32 %size) { 1014; CHECK-LABEL: @form_memcpy_narrow_size( 1015; CHECK-NEXT: entry: 1016; CHECK-NEXT: [[DST1:%.*]] = bitcast i64* [[DST:%.*]] to i8* 1017; CHECK-NEXT: [[SRC2:%.*]] = bitcast i64* [[SRC:%.*]] to i8* 1018; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[SIZE:%.*]], 0 1019; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP_PH:%.*]], label [[EXIT:%.*]] 1020; CHECK: loop.ph: 1021; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[SIZE]] to i64 1022; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 3 1023; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[DST1]], i8* align 8 [[SRC2]], i64 [[TMP1]], i1 false) 1024; CHECK-NEXT: br label [[LOOP_BODY:%.*]] 1025; CHECK: loop.body: 1026; CHECK-NEXT: [[STOREMERGE4:%.*]] = phi i32 [ 0, [[LOOP_PH]] ], [ [[INC:%.*]], [[LOOP_BODY]] ] 1027; CHECK-NEXT: [[IDXPROM1:%.*]] = sext i32 [[STOREMERGE4]] to i64 1028; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IDXPROM1]] 1029; CHECK-NEXT: [[V:%.*]] = load i64, i64* [[ARRAYIDX1]], align 8 1030; CHECK-NEXT: [[IDXPROM2:%.*]] = sext i32 [[STOREMERGE4]] to i64 1031; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IDXPROM2]] 1032; CHECK-NEXT: [[INC]] = add nsw i32 [[STOREMERGE4]], 1 1033; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[INC]], [[SIZE]] 1034; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_BODY]], label [[LOOP_EXIT:%.*]] 1035; CHECK: loop.exit: 1036; CHECK-NEXT: br label [[EXIT]] 1037; CHECK: exit: 1038; CHECK-NEXT: ret void 1039; 1040entry: 1041 %cmp1 = icmp sgt i32 %size, 0 1042 br i1 %cmp1, label %loop.ph, label %exit 1043 1044loop.ph: 1045 br label %loop.body 1046 1047loop.body: 1048 %storemerge4 = phi i32 [ 0, %loop.ph ], [ %inc, %loop.body ] 1049 %idxprom1 = sext i32 %storemerge4 to i64 1050 %arrayidx1 = getelementptr inbounds i64, i64* %src, i64 %idxprom1 1051 %v = load i64, i64* %arrayidx1, align 8 1052 %idxprom2 = sext i32 %storemerge4 to i64 1053 %arrayidx2 = getelementptr inbounds i64, i64* %dst, i64 %idxprom2 1054 store i64 %v, i64* %arrayidx2, align 8 1055 %inc = add nsw i32 %storemerge4, 1 1056 %cmp2 = icmp slt i32 %inc, %size 1057 br i1 %cmp2, label %loop.body, label %loop.exit 1058 1059loop.exit: 1060 br label %exit 1061 1062exit: 1063 ret void 1064} 1065 1066; Validate that "memset_pattern" has the proper attributes. 1067; CHECK: declare void @memset_pattern16(i8* nocapture writeonly, i8* nocapture readonly, i64) [[ATTRS:#[0-9]+]] 1068; CHECK: [[ATTRS]] = { argmemonly nofree } 1069