1625 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals2; RUN: opt -passes=loop-idiom < %s -S | FileCheck %s3target 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 5target triple = "x86_64-apple-darwin10.0.0"6 7;.8; CHECK: @G = global i32 59; CHECK: @g_50 = global [7 x i32] [i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0], align 1610;.11define void @test1(ptr %Base, i64 %Size) nounwind ssp {12; CHECK-LABEL: @test1(13; CHECK-NEXT: bb.nph:14; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[BASE:%.*]], i8 0, i64 [[SIZE:%.*]], i1 false)15; CHECK-NEXT: br label [[FOR_BODY:%.*]]16; CHECK: for.body:17; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]18; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]19; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 120; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]21; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]22; CHECK: for.end:23; CHECK-NEXT: ret void24;25bb.nph: ; preds = %entry26 br label %for.body27 28for.body: ; preds = %bb.nph, %for.body29 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]30 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar31 store i8 0, ptr %I.0.014, align 132 %indvar.next = add i64 %indvar, 133 %exitcond = icmp eq i64 %indvar.next, %Size34 br i1 %exitcond, label %for.end, label %for.body35 36for.end: ; preds = %for.body, %entry37 ret void38}39 40; Make sure memset is formed for larger than 1 byte stores, and that the41; alignment of the store is preserved42define void @test1_i16(ptr align 2 %Base, i64 %Size) nounwind ssp {43; CHECK-LABEL: @test1_i16(44; CHECK-NEXT: bb.nph:45; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 146; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 2 [[BASE:%.*]], i8 0, i64 [[TMP0]], i1 false)47; CHECK-NEXT: br label [[FOR_BODY:%.*]]48; CHECK: for.body:49; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]50; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i16, ptr [[BASE]], i64 [[INDVAR]]51; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 152; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]53; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]54; CHECK: for.end:55; CHECK-NEXT: ret void56;57bb.nph: ; preds = %entry58 br label %for.body59 60for.body: ; preds = %bb.nph, %for.body61 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]62 %I.0.014 = getelementptr i16, ptr %Base, i64 %indvar63 store i16 0, ptr %I.0.014, align 264 %indvar.next = add i64 %indvar, 165 %exitcond = icmp eq i64 %indvar.next, %Size66 br i1 %exitcond, label %for.end, label %for.body67 68for.end: ; preds = %for.body, %entry69 ret void70}71 72; This is a loop that was rotated but where the blocks weren't merged. This73; shouldn't perturb us.74define void @test1a(ptr %Base, i64 %Size) nounwind ssp {75; CHECK-LABEL: @test1a(76; CHECK-NEXT: bb.nph:77; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[BASE:%.*]], i8 0, i64 [[SIZE:%.*]], i1 false)78; CHECK-NEXT: br label [[FOR_BODY:%.*]]79; CHECK: for.body:80; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY_CONT:%.*]] ]81; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]82; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 183; CHECK-NEXT: br label [[FOR_BODY_CONT]]84; CHECK: for.body.cont:85; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]86; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]87; CHECK: for.end:88; CHECK-NEXT: ret void89;90bb.nph: ; preds = %entry91 br label %for.body92 93for.body: ; preds = %bb.nph, %for.body94 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body.cont ]95 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar96 store i8 0, ptr %I.0.014, align 197 %indvar.next = add i64 %indvar, 198 br label %for.body.cont99for.body.cont:100 %exitcond = icmp eq i64 %indvar.next, %Size101 br i1 %exitcond, label %for.end, label %for.body102 103for.end: ; preds = %for.body, %entry104 ret void105}106 107 108define void @test2(ptr %Base, i64 %Size) nounwind ssp {109; CHECK-LABEL: @test2(110; CHECK-NEXT: entry:111; CHECK-NEXT: [[CMP10:%.*]] = icmp eq i64 [[SIZE:%.*]], 0112; CHECK-NEXT: br i1 [[CMP10]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]113; CHECK: for.body.preheader:114; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE]], 2115; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[BASE:%.*]], i8 1, i64 [[TMP0]], i1 false)116; CHECK-NEXT: br label [[FOR_BODY:%.*]]117; CHECK: for.body:118; CHECK-NEXT: [[I_011:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]119; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[I_011]]120; CHECK-NEXT: [[INC]] = add nsw i64 [[I_011]], 1121; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[SIZE]]122; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]123; CHECK: for.end.loopexit:124; CHECK-NEXT: br label [[FOR_END]]125; CHECK: for.end:126; CHECK-NEXT: ret void127;128entry:129 %cmp10 = icmp eq i64 %Size, 0130 br i1 %cmp10, label %for.end, label %for.body131 132for.body: ; preds = %entry, %for.body133 %i.011 = phi i64 [ %inc, %for.body ], [ 0, %entry ]134 %add.ptr.i = getelementptr i32, ptr %Base, i64 %i.011135 store i32 16843009, ptr %add.ptr.i, align 4136 %inc = add nsw i64 %i.011, 1137 %exitcond = icmp eq i64 %inc, %Size138 br i1 %exitcond, label %for.end, label %for.body139 140for.end: ; preds = %for.body, %entry141 ret void142}143 144; This is a case where there is an extra may-aliased store in the loop, we can't145; promote the memset.146define void @test3(ptr %Base, i64 %Size, ptr %MayAlias) nounwind ssp {147; CHECK-LABEL: @test3(148; CHECK-NEXT: entry:149; CHECK-NEXT: br label [[FOR_BODY:%.*]]150; CHECK: for.body:151; CHECK-NEXT: [[I_011:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]152; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[I_011]]153; CHECK-NEXT: store i32 16843009, ptr [[ADD_PTR_I]], align 4154; CHECK-NEXT: store i8 42, ptr [[MAYALIAS:%.*]], align 1155; CHECK-NEXT: [[INC]] = add nsw i64 [[I_011]], 1156; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[SIZE:%.*]]157; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]158; CHECK: for.end:159; CHECK-NEXT: ret void160;161entry:162 br label %for.body163 164for.body: ; preds = %entry, %for.body165 %i.011 = phi i64 [ %inc, %for.body ], [ 0, %entry ]166 %add.ptr.i = getelementptr i32, ptr %Base, i64 %i.011167 store i32 16843009, ptr %add.ptr.i, align 4168 169 store i8 42, ptr %MayAlias170 %inc = add nsw i64 %i.011, 1171 %exitcond = icmp eq i64 %inc, %Size172 br i1 %exitcond, label %for.end, label %for.body173 174for.end: ; preds = %entry175 ret void176}177 178; Make sure the first store in the loop is turned into a memset.179define void @test4(ptr %Base) nounwind ssp {180; CHECK-LABEL: @test4(181; CHECK-NEXT: bb.nph:182; CHECK-NEXT: [[BASE100:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 1000183; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[BASE]], i8 0, i64 100, i1 false)184; CHECK-NEXT: br label [[FOR_BODY:%.*]]185; CHECK: for.body:186; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]187; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]188; CHECK-NEXT: store i8 42, ptr [[BASE100]], align 1189; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1190; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 100191; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]192; CHECK: for.end:193; CHECK-NEXT: ret void194;195bb.nph: ; preds = %entry196 %Base100 = getelementptr i8, ptr %Base, i64 1000197 br label %for.body198 199for.body: ; preds = %bb.nph, %for.body200 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]201 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar202 store i8 0, ptr %I.0.014, align 1203 204 ;; Store beyond the range memset, should be safe to promote.205 store i8 42, ptr %Base100206 207 %indvar.next = add i64 %indvar, 1208 %exitcond = icmp eq i64 %indvar.next, 100209 br i1 %exitcond, label %for.end, label %for.body210 211for.end: ; preds = %for.body, %entry212 ret void213}214 215; This can't be promoted: the memset is a store of a loop variant value.216define void @test5(ptr %Base, i64 %Size) nounwind ssp {217; CHECK-LABEL: @test5(218; CHECK-NEXT: bb.nph:219; CHECK-NEXT: br label [[FOR_BODY:%.*]]220; CHECK: for.body:221; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]222; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 [[INDVAR]]223; CHECK-NEXT: [[V:%.*]] = trunc i64 [[INDVAR]] to i8224; CHECK-NEXT: store i8 [[V]], ptr [[I_0_014]], align 1225; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1226; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]227; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]228; CHECK: for.end:229; CHECK-NEXT: ret void230;231bb.nph: ; preds = %entry232 br label %for.body233 234for.body: ; preds = %bb.nph, %for.body235 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]236 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar237 238 %V = trunc i64 %indvar to i8239 store i8 %V, ptr %I.0.014, align 1240 %indvar.next = add i64 %indvar, 1241 %exitcond = icmp eq i64 %indvar.next, %Size242 br i1 %exitcond, label %for.end, label %for.body243 244for.end: ; preds = %for.body, %entry245 ret void246}247 248 249;; memcpy formation250define void @test6(i64 %Size) nounwind ssp {251; CHECK-LABEL: @test6(252; CHECK-NEXT: bb.nph:253; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 1254; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 1255; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[BASE]], i64 [[SIZE:%.*]], i1 false)256; CHECK-NEXT: br label [[FOR_BODY:%.*]]257; CHECK: for.body:258; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]259; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]260; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]261; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[I_0_014]], align 1262; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1263; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]264; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]265; CHECK: for.end:266; CHECK-NEXT: ret void267;268bb.nph:269 %Base = alloca i8, i32 10000270 %Dest = alloca i8, i32 10000271 br label %for.body272 273for.body: ; preds = %bb.nph, %for.body274 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]275 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar276 %DestI = getelementptr i8, ptr %Dest, i64 %indvar277 %V = load i8, ptr %I.0.014, align 1278 store i8 %V, ptr %DestI, align 1279 %indvar.next = add i64 %indvar, 1280 %exitcond = icmp eq i64 %indvar.next, %Size281 br i1 %exitcond, label %for.end, label %for.body282 283for.end: ; preds = %for.body, %entry284 ret void285}286 287;; memcpy formation, check alignment288define void @test6_dest_align(ptr noalias align 1 %Base, ptr noalias align 4 %Dest, i64 %Size) nounwind ssp {289; CHECK-LABEL: @test6_dest_align(290; CHECK-NEXT: bb.nph:291; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 2292; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST:%.*]], ptr align 1 [[BASE:%.*]], i64 [[TMP0]], i1 false)293; CHECK-NEXT: br label [[FOR_BODY:%.*]]294; CHECK: for.body:295; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]296; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[INDVAR]]297; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, ptr [[DEST]], i64 [[INDVAR]]298; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[I_0_014]], align 1299; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1300; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]301; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]302; CHECK: for.end:303; CHECK-NEXT: ret void304;305bb.nph:306 br label %for.body307 308for.body: ; preds = %bb.nph, %for.body309 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]310 %I.0.014 = getelementptr i32, ptr %Base, i64 %indvar311 %DestI = getelementptr i32, ptr %Dest, i64 %indvar312 %V = load i32, ptr %I.0.014, align 1313 store i32 %V, ptr %DestI, align 4314 %indvar.next = add i64 %indvar, 1315 %exitcond = icmp eq i64 %indvar.next, %Size316 br i1 %exitcond, label %for.end, label %for.body317 318for.end: ; preds = %for.body, %entry319 ret void320}321 322;; memcpy formation, check alignment323define void @test6_src_align(ptr noalias align 4 %Base, ptr noalias align 1 %Dest, i64 %Size) nounwind ssp {324; CHECK-LABEL: @test6_src_align(325; CHECK-NEXT: bb.nph:326; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 2327; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEST:%.*]], ptr align 4 [[BASE:%.*]], i64 [[TMP0]], i1 false)328; CHECK-NEXT: br label [[FOR_BODY:%.*]]329; CHECK: for.body:330; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]331; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[INDVAR]]332; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, ptr [[DEST]], i64 [[INDVAR]]333; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[I_0_014]], align 4334; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1335; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]336; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]337; CHECK: for.end:338; CHECK-NEXT: ret void339;340bb.nph:341 br label %for.body342 343for.body: ; preds = %bb.nph, %for.body344 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]345 %I.0.014 = getelementptr i32, ptr %Base, i64 %indvar346 %DestI = getelementptr i32, ptr %Dest, i64 %indvar347 %V = load i32, ptr %I.0.014, align 4348 store i32 %V, ptr %DestI, align 1349 %indvar.next = add i64 %indvar, 1350 %exitcond = icmp eq i64 %indvar.next, %Size351 br i1 %exitcond, label %for.end, label %for.body352 353for.end: ; preds = %for.body, %entry354 ret void355}356 357 358; This is a loop that was rotated but where the blocks weren't merged. This359; shouldn't perturb us.360define void @test7(ptr %Base, i64 %Size) nounwind ssp {361; CHECK-LABEL: @test7(362; CHECK-NEXT: bb.nph:363; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[BASE:%.*]], i8 0, i64 [[SIZE:%.*]], i1 false)364; CHECK-NEXT: br label [[FOR_BODY:%.*]]365; CHECK: for.body:366; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY_CONT:%.*]] ]367; CHECK-NEXT: br label [[FOR_BODY_CONT]]368; CHECK: for.body.cont:369; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]370; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1371; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]372; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]373; CHECK: for.end:374; CHECK-NEXT: ret void375;376bb.nph: ; preds = %entry377 br label %for.body378 379for.body: ; preds = %bb.nph, %for.body380 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body.cont ]381 br label %for.body.cont382for.body.cont:383 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar384 store i8 0, ptr %I.0.014, align 1385 %indvar.next = add i64 %indvar, 1386 %exitcond = icmp eq i64 %indvar.next, %Size387 br i1 %exitcond, label %for.end, label %for.body388 389for.end: ; preds = %for.body, %entry390 ret void391}392 393; This is a loop should not be transformed, it only executes one iteration.394define void @test8(ptr %Ptr, i64 %Size) nounwind ssp {395; CHECK-LABEL: @test8(396; CHECK-NEXT: bb.nph:397; CHECK-NEXT: br label [[FOR_BODY:%.*]]398; CHECK: for.body:399; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]400; CHECK-NEXT: [[PI:%.*]] = getelementptr i64, ptr [[PTR:%.*]], i64 [[INDVAR]]401; CHECK-NEXT: store i64 0, ptr [[PI]], align 8402; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1403; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 1404; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]405; CHECK: for.end:406; CHECK-NEXT: ret void407;408bb.nph: ; preds = %entry409 br label %for.body410 411for.body: ; preds = %bb.nph, %for.body412 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]413 %PI = getelementptr i64, ptr %Ptr, i64 %indvar414 store i64 0, ptr %PI415 %indvar.next = add i64 %indvar, 1416 %exitcond = icmp eq i64 %indvar.next, 1417 br i1 %exitcond, label %for.end, label %for.body418 419for.end: ; preds = %for.body, %entry420 ret void421}422 423declare ptr @external(ptr)424 425;; This cannot be transformed into a memcpy, because the read-from location is426;; mutated by the loop.427define void @test9(i64 %Size) nounwind ssp {428; CHECK-LABEL: @test9(429; CHECK-NEXT: bb.nph:430; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 1431; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 1432; CHECK-NEXT: [[BASEALIAS:%.*]] = call ptr @external(ptr [[BASE]])433; CHECK-NEXT: br label [[FOR_BODY:%.*]]434; CHECK: for.body:435; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]436; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]437; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]438; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[I_0_014]], align 1439; CHECK-NEXT: store i8 [[V]], ptr [[DESTI]], align 1440; CHECK-NEXT: store i8 4, ptr [[BASEALIAS]], align 1441; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1442; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]443; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]444; CHECK: for.end:445; CHECK-NEXT: ret void446;447bb.nph:448 %Base = alloca i8, i32 10000449 %Dest = alloca i8, i32 10000450 451 %BaseAlias = call ptr @external(ptr %Base)452 br label %for.body453 454for.body: ; preds = %bb.nph, %for.body455 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]456 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar457 %DestI = getelementptr i8, ptr %Dest, i64 %indvar458 %V = load i8, ptr %I.0.014, align 1459 store i8 %V, ptr %DestI, align 1460 461 ;; This store can clobber the input.462 store i8 4, ptr %BaseAlias463 464 %indvar.next = add i64 %indvar, 1465 %exitcond = icmp eq i64 %indvar.next, %Size466 br i1 %exitcond, label %for.end, label %for.body467 468for.end: ; preds = %for.body, %entry469 ret void470}471 472; Two dimensional nested loop should be promoted to one big memset.473define void @test10(ptr %X) nounwind ssp {474; CHECK-LABEL: @test10(475; CHECK-NEXT: entry:476; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[X:%.*]], i8 0, i64 10000, i1 false)477; CHECK-NEXT: br label [[BB_NPH:%.*]]478; CHECK: bb.nph:479; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[FOR_INC10:%.*]] ], [ 0, [[ENTRY:%.*]] ]480; CHECK-NEXT: [[I_04:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC12:%.*]], [[FOR_INC10]] ]481; CHECK-NEXT: [[TMP0:%.*]] = mul nuw nsw i64 [[INDVAR]], 100482; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr nuw i8, ptr [[X]], i64 [[TMP0]]483; CHECK-NEXT: br label [[FOR_BODY5:%.*]]484; CHECK: for.body5:485; CHECK-NEXT: [[J_02:%.*]] = phi i32 [ 0, [[BB_NPH]] ], [ [[INC:%.*]], [[FOR_BODY5]] ]486; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[I_04]], 100487; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[J_02]], [[MUL]]488; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[ADD]] to i64489; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[IDXPROM]]490; CHECK-NEXT: [[INC]] = add nsw i32 [[J_02]], 1491; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i32 [[INC]], 100492; CHECK-NEXT: br i1 [[CMP4]], label [[FOR_INC10]], label [[FOR_BODY5]]493; CHECK: for.inc10:494; CHECK-NEXT: [[INC12]] = add nsw i32 [[I_04]], 1495; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[INC12]], 100496; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1497; CHECK-NEXT: br i1 [[CMP]], label [[FOR_END13:%.*]], label [[BB_NPH]]498; CHECK: for.end13:499; CHECK-NEXT: ret void500;501entry:502 br label %bb.nph503 504bb.nph: ; preds = %entry, %for.inc10505 %i.04 = phi i32 [ 0, %entry ], [ %inc12, %for.inc10 ]506 br label %for.body5507 508for.body5: ; preds = %for.body5, %bb.nph509 %j.02 = phi i32 [ 0, %bb.nph ], [ %inc, %for.body5 ]510 %mul = mul nsw i32 %i.04, 100511 %add = add nsw i32 %j.02, %mul512 %idxprom = sext i32 %add to i64513 %arrayidx = getelementptr inbounds i8, ptr %X, i64 %idxprom514 store i8 0, ptr %arrayidx, align 1515 %inc = add nsw i32 %j.02, 1516 %cmp4 = icmp eq i32 %inc, 100517 br i1 %cmp4, label %for.inc10, label %for.body5518 519for.inc10: ; preds = %for.body5520 %inc12 = add nsw i32 %i.04, 1521 %cmp = icmp eq i32 %inc12, 100522 br i1 %cmp, label %for.end13, label %bb.nph523 524for.end13: ; preds = %for.inc10525 ret void526}527 528; On darwin10 (which is the triple in this .ll file) this loop can be turned529; into a memset_pattern call.530; rdar://9009151531define void @test11_pattern(ptr nocapture %P) nounwind ssp {532; CHECK-LABEL: @test11_pattern(533; CHECK-NEXT: entry:534; CHECK-NEXT: call void @llvm.experimental.memset.pattern.p0.i32.i64(ptr align 4 [[P:%.*]], i32 1, i64 10000, i1 false)535; CHECK-NEXT: br label [[FOR_BODY:%.*]]536; CHECK: for.body:537; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]538; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[P]], i64 [[INDVAR]]539; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1540; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 10000541; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]542; CHECK: for.end:543; CHECK-NEXT: ret void544;545entry:546 br label %for.body547 548for.body: ; preds = %entry, %for.body549 %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ]550 %arrayidx = getelementptr i32, ptr %P, i64 %indvar551 store i32 1, ptr %arrayidx, align 4552 %indvar.next = add i64 %indvar, 1553 %exitcond = icmp eq i64 %indvar.next, 10000554 br i1 %exitcond, label %for.end, label %for.body555 556for.end: ; preds = %for.body557 ret void558}559 560; Store of null should turn into memset of zero.561define void @test12(ptr nocapture %P) nounwind ssp {562; CHECK-LABEL: @test12(563; CHECK-NEXT: entry:564; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[P:%.*]], i8 0, i64 80000, i1 false)565; CHECK-NEXT: br label [[FOR_BODY:%.*]]566; CHECK: for.body:567; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]568; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr ptr, ptr [[P]], i64 [[INDVAR]]569; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1570; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 10000571; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]572; CHECK: for.end:573; CHECK-NEXT: ret void574;575entry:576 br label %for.body577 578for.body: ; preds = %entry, %for.body579 %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ]580 %arrayidx = getelementptr ptr, ptr %P, i64 %indvar581 store ptr null, ptr %arrayidx, align 4582 %indvar.next = add i64 %indvar, 1583 %exitcond = icmp eq i64 %indvar.next, 10000584 br i1 %exitcond, label %for.end, label %for.body585 586for.end: ; preds = %for.body587 ret void588}589 590@G = global i32 5591 592; This store-of-address loop can be turned into a memset_pattern call.593; rdar://9009151594define void @test13_pattern(ptr nocapture %P) nounwind ssp {595; CHECK-LABEL: @test13_pattern(596; CHECK-NEXT: entry:597; CHECK-NEXT: call void @llvm.experimental.memset.pattern.p0.p0.i64(ptr align 4 [[P:%.*]], ptr @G, i64 10000, i1 false)598; CHECK-NEXT: br label [[FOR_BODY:%.*]]599; CHECK: for.body:600; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]601; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr ptr, ptr [[P]], i64 [[INDVAR]]602; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1603; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 10000604; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]605; CHECK: for.end:606; CHECK-NEXT: ret void607;608entry:609 br label %for.body610 611for.body: ; preds = %entry, %for.body612 %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ]613 %arrayidx = getelementptr ptr, ptr %P, i64 %indvar614 store ptr @G, ptr %arrayidx, align 4615 %indvar.next = add i64 %indvar, 1616 %exitcond = icmp eq i64 %indvar.next, 10000617 br i1 %exitcond, label %for.end, label %for.body618 619for.end: ; preds = %for.body620 ret void621}622 623 624 625; PR9815 - This is a partial overlap case that cannot be safely transformed626; into a memcpy.627@g_50 = global [7 x i32] [i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0], align 16628 629define i32 @test14() nounwind {630; CHECK-LABEL: @test14(631; CHECK-NEXT: entry:632; CHECK-NEXT: br label [[FOR_BODY:%.*]]633; CHECK: for.body:634; CHECK-NEXT: [[T5:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]635; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[T5]], 4636; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[ADD]] to i64637; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [7 x i32], ptr @g_50, i32 0, i64 [[IDXPROM]]638; CHECK-NEXT: [[T2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4639; CHECK-NEXT: [[ADD4:%.*]] = add nsw i32 [[T5]], 5640; CHECK-NEXT: [[IDXPROM5:%.*]] = sext i32 [[ADD4]] to i64641; CHECK-NEXT: [[ARRAYIDX6:%.*]] = getelementptr inbounds [7 x i32], ptr @g_50, i32 0, i64 [[IDXPROM5]]642; CHECK-NEXT: store i32 [[T2]], ptr [[ARRAYIDX6]], align 4643; CHECK-NEXT: [[INC]] = add nsw i32 [[T5]], 1644; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 2645; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]646; CHECK: for.end:647; CHECK-NEXT: [[T8:%.*]] = load i32, ptr getelementptr inbounds ([7 x i32], ptr @g_50, i32 0, i64 6), align 4648; CHECK-NEXT: ret i32 [[T8]]649;650entry:651 br label %for.body652 653for.body: ; preds = %for.inc, %for.body.lr.ph654 %t5 = phi i32 [ %inc, %for.body ], [ 0, %entry ]655 %add = add nsw i32 %t5, 4656 %idxprom = sext i32 %add to i64657 %arrayidx = getelementptr inbounds [7 x i32], ptr @g_50, i32 0, i64 %idxprom658 %t2 = load i32, ptr %arrayidx, align 4659 %add4 = add nsw i32 %t5, 5660 %idxprom5 = sext i32 %add4 to i64661 %arrayidx6 = getelementptr inbounds [7 x i32], ptr @g_50, i32 0, i64 %idxprom5662 store i32 %t2, ptr %arrayidx6, align 4663 %inc = add nsw i32 %t5, 1664 %cmp = icmp slt i32 %inc, 2665 br i1 %cmp, label %for.body, label %for.end666 667for.end: ; preds = %for.inc668 %t8 = load i32, ptr getelementptr inbounds ([7 x i32], ptr @g_50, i32 0, i64 6), align 4669 ret i32 %t8670 671}672 673define void @PR14241(ptr %s, i64 %size) {674; Ensure that we don't form a memcpy for strided loops. Briefly, when we taught675; LoopIdiom about memmove and strided loops, this got miscompiled into a memcpy676; instead of a memmove. If we get the memmove transform back, this will catch677; regressions.678;679; CHECK-LABEL: @PR14241(680; CHECK-NEXT: entry:681; CHECK-NEXT: [[END_IDX:%.*]] = add i64 [[SIZE:%.*]], -1682; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i64 [[END_IDX]]683; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr nuw i8, ptr [[S]], i64 4684; CHECK-NEXT: [[TMP0:%.*]] = shl i64 [[SIZE]], 2685; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[TMP0]], -4686; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 4 [[S]], ptr align 4 [[SCEVGEP]], i64 [[TMP4]], i1 false)687; CHECK-NEXT: br label [[WHILE_BODY:%.*]]688; CHECK: while.body:689; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[S]], [[ENTRY:%.*]] ], [ [[NEXT_PTR:%.*]], [[WHILE_BODY]] ]690; CHECK-NEXT: [[SRC_PTR:%.*]] = getelementptr inbounds i32, ptr [[PHI_PTR]], i64 1691; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[SRC_PTR]], align 4692; CHECK-NEXT: [[NEXT_PTR]] = getelementptr inbounds i32, ptr [[PHI_PTR]], i64 1693; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[NEXT_PTR]], [[END_PTR]]694; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[WHILE_BODY]]695; CHECK: exit:696; CHECK-NEXT: ret void697;698 699entry:700 %end.idx = add i64 %size, -1701 %end.ptr = getelementptr inbounds i32, ptr %s, i64 %end.idx702 br label %while.body703 704while.body:705 %phi.ptr = phi ptr [ %s, %entry ], [ %next.ptr, %while.body ]706 %src.ptr = getelementptr inbounds i32, ptr %phi.ptr, i64 1707 %val = load i32, ptr %src.ptr, align 4708 store i32 %val, ptr %phi.ptr, align 4709 %next.ptr = getelementptr inbounds i32, ptr %phi.ptr, i64 1710 %cmp = icmp eq ptr %next.ptr, %end.ptr711 br i1 %cmp, label %exit, label %while.body712 713exit:714 ret void715}716 717; Recognize loops with a negative stride.718define void @test15(ptr nocapture %f) {719; CHECK-LABEL: @test15(720; CHECK-NEXT: entry:721; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[F:%.*]], i8 0, i64 262148, i1 false)722; CHECK-NEXT: br label [[FOR_BODY:%.*]]723; CHECK: for.body:724; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 65536, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]725; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[F]], i64 [[INDVARS_IV]]726; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1727; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[INDVARS_IV]], 0728; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]729; CHECK: for.cond.cleanup:730; CHECK-NEXT: ret void731;732entry:733 br label %for.body734 735for.body:736 %indvars.iv = phi i64 [ 65536, %entry ], [ %indvars.iv.next, %for.body ]737 %arrayidx = getelementptr inbounds i32, ptr %f, i64 %indvars.iv738 store i32 0, ptr %arrayidx, align 4739 %indvars.iv.next = add nsw i64 %indvars.iv, -1740 %cmp = icmp sgt i64 %indvars.iv, 0741 br i1 %cmp, label %for.body, label %for.cond.cleanup742 743for.cond.cleanup:744 ret void745}746 747; Loop with a negative stride. Verify an aliasing write to f[65536] prevents748; the creation of a memset.749define void @test16(ptr nocapture %f) {750; CHECK-LABEL: @test16(751; CHECK-NEXT: entry:752; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[F:%.*]], i64 65536753; CHECK-NEXT: br label [[FOR_BODY:%.*]]754; CHECK: for.body:755; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 65536, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]756; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[F]], i64 [[INDVARS_IV]]757; CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4758; CHECK-NEXT: store i32 1, ptr [[ARRAYIDX1]], align 4759; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1760; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[INDVARS_IV]], 0761; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]762; CHECK: for.cond.cleanup:763; CHECK-NEXT: ret void764;765entry:766 %arrayidx1 = getelementptr inbounds i32, ptr %f, i64 65536767 br label %for.body768 769for.body: ; preds = %entry, %for.body770 %indvars.iv = phi i64 [ 65536, %entry ], [ %indvars.iv.next, %for.body ]771 %arrayidx = getelementptr inbounds i32, ptr %f, i64 %indvars.iv772 store i32 0, ptr %arrayidx, align 4773 store i32 1, ptr %arrayidx1, align 4774 %indvars.iv.next = add nsw i64 %indvars.iv, -1775 %cmp = icmp sgt i64 %indvars.iv, 0776 br i1 %cmp, label %for.body, label %for.cond.cleanup777 778for.cond.cleanup: ; preds = %for.body779 ret void780}781 782; Handle memcpy-able loops with negative stride.783define noalias ptr @test17(ptr nocapture readonly %a, i32 %c) {784; CHECK-LABEL: @test17(785; CHECK-NEXT: entry:786; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[C:%.*]] to i64787; CHECK-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2788; CHECK-NEXT: [[CALL:%.*]] = tail call noalias ptr @malloc(i64 [[MUL]])789; CHECK-NEXT: [[TOBOOL_9:%.*]] = icmp eq i32 [[C]], 0790; CHECK-NEXT: br i1 [[TOBOOL_9]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]791; CHECK: while.body.preheader:792; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[C]], -1793; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[TMP0]] to i64794; CHECK-NEXT: [[TMP2:%.*]] = shl nsw i64 [[TMP1]], 2795; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP0]] to i64796; CHECK-NEXT: [[TMP4:%.*]] = shl nuw nsw i64 [[TMP3]], 2797; CHECK-NEXT: [[TMP5:%.*]] = sub i64 [[TMP2]], [[TMP4]]798; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[CALL]], i64 [[TMP5]]799; CHECK-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP5]]800; CHECK-NEXT: [[TMP6:%.*]] = zext i32 [[C]] to i64801; CHECK-NEXT: [[TMP7:%.*]] = shl nuw nsw i64 [[TMP6]], 2802; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[SCEVGEP]], ptr align 4 [[SCEVGEP1]], i64 [[TMP7]], i1 false)803; CHECK-NEXT: br label [[WHILE_BODY:%.*]]804; CHECK: while.body:805; CHECK-NEXT: [[DEC10_IN:%.*]] = phi i32 [ [[DEC10:%.*]], [[WHILE_BODY]] ], [ [[C]], [[WHILE_BODY_PREHEADER]] ]806; CHECK-NEXT: [[DEC10]] = add nsw i32 [[DEC10_IN]], -1807; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[DEC10]] to i64808; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM]]809; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[ARRAYIDX]], align 4810; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[CALL]], i64 [[IDXPROM]]811; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[DEC10]], 0812; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]813; CHECK: while.end.loopexit:814; CHECK-NEXT: br label [[WHILE_END]]815; CHECK: while.end:816; CHECK-NEXT: ret ptr [[CALL]]817;818entry:819 %conv = sext i32 %c to i64820 %mul = shl nsw i64 %conv, 2821 %call = tail call noalias ptr @malloc(i64 %mul)822 %tobool.9 = icmp eq i32 %c, 0823 br i1 %tobool.9, label %while.end, label %while.body.preheader824 825while.body.preheader: ; preds = %entry826 br label %while.body827 828while.body: ; preds = %while.body.preheader, %while.body829 %dec10.in = phi i32 [ %dec10, %while.body ], [ %c, %while.body.preheader ]830 %dec10 = add nsw i32 %dec10.in, -1831 %idxprom = sext i32 %dec10 to i64832 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom833 %0 = load i32, ptr %arrayidx, align 4834 %arrayidx2 = getelementptr inbounds i32, ptr %call, i64 %idxprom835 store i32 %0, ptr %arrayidx2, align 4836 %tobool = icmp eq i32 %dec10, 0837 br i1 %tobool, label %while.end.loopexit, label %while.body838 839while.end.loopexit: ; preds = %while.body840 br label %while.end841 842while.end: ; preds = %while.end.loopexit, %entry843 ret ptr %call844}845 846declare noalias ptr @malloc(i64)847 848; Handle memcpy-able loops with negative stride.849; void test18(unsigned *__restrict__ a, unsigned *__restrict__ b) {850; for (int i = 2047; i >= 0; --i) {851; a[i] = b[i];852; }853; }854define void @test18(ptr noalias nocapture %a, ptr noalias nocapture readonly %b) #0 {855; CHECK-LABEL: @test18(856; CHECK-NEXT: entry:857; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A:%.*]], ptr align 4 [[B:%.*]], i64 8192, i1 false)858; CHECK-NEXT: br label [[FOR_BODY:%.*]]859; CHECK: for.body:860; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 2047, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]861; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDVARS_IV]]862; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4863; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INDVARS_IV]]864; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1865; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[INDVARS_IV]], 0866; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]867; CHECK: for.cond.cleanup:868; CHECK-NEXT: ret void869;870entry:871 br label %for.body872 873for.body: ; preds = %entry, %for.body874 %indvars.iv = phi i64 [ 2047, %entry ], [ %indvars.iv.next, %for.body ]875 %arrayidx = getelementptr inbounds i32, ptr %b, i64 %indvars.iv876 %0 = load i32, ptr %arrayidx, align 4877 %arrayidx2 = getelementptr inbounds i32, ptr %a, i64 %indvars.iv878 store i32 %0, ptr %arrayidx2, align 4879 %indvars.iv.next = add nsw i64 %indvars.iv, -1880 %cmp = icmp sgt i64 %indvars.iv, 0881 br i1 %cmp, label %for.body, label %for.cond.cleanup882 883for.cond.cleanup: ; preds = %for.body884 ret void885}886 887; Two dimensional nested loop with negative stride should be promoted to one big memset.888define void @test19(ptr nocapture %X) {889; CHECK-LABEL: @test19(890; CHECK-NEXT: entry:891; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[X:%.*]], i8 0, i64 10000, i1 false)892; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]]893; CHECK: for.cond1.preheader:894; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[FOR_INC4:%.*]] ], [ 0, [[ENTRY:%.*]] ]895; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 99, [[ENTRY]] ], [ [[DEC5:%.*]], [[FOR_INC4]] ]896; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i64 [[INDVAR]], -100897; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 9900898; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[X]], i64 [[TMP1]]899; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[I_06]], 100900; CHECK-NEXT: br label [[FOR_BODY3:%.*]]901; CHECK: for.body3:902; CHECK-NEXT: [[J_05:%.*]] = phi i32 [ 99, [[FOR_COND1_PREHEADER]] ], [ [[DEC:%.*]], [[FOR_BODY3]] ]903; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[J_05]], [[MUL]]904; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[ADD]] to i64905; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[IDXPROM]]906; CHECK-NEXT: [[DEC]] = add nsw i32 [[J_05]], -1907; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[J_05]], 0908; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_INC4]]909; CHECK: for.inc4:910; CHECK-NEXT: [[DEC5]] = add nsw i32 [[I_06]], -1911; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[I_06]], 0912; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1913; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND1_PREHEADER]], label [[FOR_END6:%.*]]914; CHECK: for.end6:915; CHECK-NEXT: ret void916;917entry:918 br label %for.cond1.preheader919 920for.cond1.preheader: ; preds = %entry, %for.inc4921 %i.06 = phi i32 [ 99, %entry ], [ %dec5, %for.inc4 ]922 %mul = mul nsw i32 %i.06, 100923 br label %for.body3924 925for.body3: ; preds = %for.cond1.preheader, %for.body3926 %j.05 = phi i32 [ 99, %for.cond1.preheader ], [ %dec, %for.body3 ]927 %add = add nsw i32 %j.05, %mul928 %idxprom = sext i32 %add to i64929 %arrayidx = getelementptr inbounds i8, ptr %X, i64 %idxprom930 store i8 0, ptr %arrayidx, align 1931 %dec = add nsw i32 %j.05, -1932 %cmp2 = icmp sgt i32 %j.05, 0933 br i1 %cmp2, label %for.body3, label %for.inc4934 935for.inc4: ; preds = %for.body3936 %dec5 = add nsw i32 %i.06, -1937 %cmp = icmp sgt i32 %i.06, 0938 br i1 %cmp, label %for.cond1.preheader, label %for.end6939 940for.end6: ; preds = %for.inc4941 ret void942}943 944; Handle loops where the trip count is a narrow integer that needs to be945; extended.946define void @form_memset_narrow_size(ptr %ptr, i32 %size) {947; CHECK-LABEL: @form_memset_narrow_size(948; CHECK-NEXT: entry:949; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[SIZE:%.*]], 0950; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP_PH:%.*]], label [[EXIT:%.*]]951; CHECK: loop.ph:952; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[SIZE]] to i64953; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 3954; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[PTR:%.*]], i8 0, i64 [[TMP1]], i1 false)955; CHECK-NEXT: br label [[LOOP_BODY:%.*]]956; CHECK: loop.body:957; CHECK-NEXT: [[STOREMERGE4:%.*]] = phi i32 [ 0, [[LOOP_PH]] ], [ [[INC:%.*]], [[LOOP_BODY]] ]958; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[STOREMERGE4]] to i64959; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[PTR]], i64 [[IDXPROM]]960; CHECK-NEXT: [[INC]] = add nsw i32 [[STOREMERGE4]], 1961; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[INC]], [[SIZE]]962; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_BODY]], label [[LOOP_EXIT:%.*]]963; CHECK: loop.exit:964; CHECK-NEXT: br label [[EXIT]]965; CHECK: exit:966; CHECK-NEXT: ret void967;968entry:969 %cmp1 = icmp sgt i32 %size, 0970 br i1 %cmp1, label %loop.ph, label %exit971 972loop.ph:973 br label %loop.body974 975loop.body:976 %storemerge4 = phi i32 [ 0, %loop.ph ], [ %inc, %loop.body ]977 %idxprom = sext i32 %storemerge4 to i64978 %arrayidx = getelementptr inbounds i64, ptr %ptr, i64 %idxprom979 store i64 0, ptr %arrayidx, align 8980 %inc = add nsw i32 %storemerge4, 1981 %cmp2 = icmp slt i32 %inc, %size982 br i1 %cmp2, label %loop.body, label %loop.exit983 984loop.exit:985 br label %exit986 987exit:988 ret void989}990 991define void @form_memcpy_narrow_size(ptr noalias %dst, ptr noalias %src, i32 %size) {992; CHECK-LABEL: @form_memcpy_narrow_size(993; CHECK-NEXT: entry:994; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[SIZE:%.*]], 0995; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP_PH:%.*]], label [[EXIT:%.*]]996; CHECK: loop.ph:997; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[SIZE]] to i64998; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 3999; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DST:%.*]], ptr align 8 [[SRC:%.*]], i64 [[TMP1]], i1 false)1000; CHECK-NEXT: br label [[LOOP_BODY:%.*]]1001; CHECK: loop.body:1002; CHECK-NEXT: [[STOREMERGE4:%.*]] = phi i32 [ 0, [[LOOP_PH]] ], [ [[INC:%.*]], [[LOOP_BODY]] ]1003; CHECK-NEXT: [[IDXPROM1:%.*]] = sext i32 [[STOREMERGE4]] to i641004; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IDXPROM1]]1005; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[ARRAYIDX1]], align 81006; CHECK-NEXT: [[IDXPROM2:%.*]] = sext i32 [[STOREMERGE4]] to i641007; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IDXPROM2]]1008; CHECK-NEXT: [[INC]] = add nsw i32 [[STOREMERGE4]], 11009; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[INC]], [[SIZE]]1010; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_BODY]], label [[LOOP_EXIT:%.*]]1011; CHECK: loop.exit:1012; CHECK-NEXT: br label [[EXIT]]1013; CHECK: exit:1014; CHECK-NEXT: ret void1015;1016entry:1017 %cmp1 = icmp sgt i32 %size, 01018 br i1 %cmp1, label %loop.ph, label %exit1019 1020loop.ph:1021 br label %loop.body1022 1023loop.body:1024 %storemerge4 = phi i32 [ 0, %loop.ph ], [ %inc, %loop.body ]1025 %idxprom1 = sext i32 %storemerge4 to i641026 %arrayidx1 = getelementptr inbounds i64, ptr %src, i64 %idxprom11027 %v = load i64, ptr %arrayidx1, align 81028 %idxprom2 = sext i32 %storemerge4 to i641029 %arrayidx2 = getelementptr inbounds i64, ptr %dst, i64 %idxprom21030 store i64 %v, ptr %arrayidx2, align 81031 %inc = add nsw i32 %storemerge4, 11032 %cmp2 = icmp slt i32 %inc, %size1033 br i1 %cmp2, label %loop.body, label %loop.exit1034 1035loop.exit:1036 br label %exit1037 1038exit:1039 ret void1040}1041 1042;; Memmove formation.1043define void @PR46179_positive_stride(ptr %Src, i64 %Size) {1044; CHECK-LABEL: @PR46179_positive_stride(1045; CHECK-NEXT: bb.nph:1046; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 11047; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[SRC]], ptr align 1 [[SCEVGEP]], i64 [[SIZE:%.*]], i1 false)1048; CHECK-NEXT: br label [[FOR_BODY:%.*]]1049; CHECK: for.body:1050; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]1051; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], 11052; CHECK-NEXT: [[SRCI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[STEP]]1053; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[INDVAR]]1054; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[SRCI]], align 11055; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 11056; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]1057; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]1058; CHECK: for.end:1059; CHECK-NEXT: ret void1060;1061bb.nph:1062 br label %for.body1063 1064for.body: ; preds = %bb.nph, %for.body1065 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]1066 %Step = add nuw nsw i64 %indvar, 11067 %SrcI = getelementptr i8, ptr %Src, i64 %Step1068 %DestI = getelementptr i8, ptr %Src, i64 %indvar1069 %V = load i8, ptr %SrcI, align 11070 store i8 %V, ptr %DestI, align 11071 %indvar.next = add i64 %indvar, 11072 %exitcond = icmp eq i64 %indvar.next, %Size1073 br i1 %exitcond, label %for.end, label %for.body1074 1075for.end: ; preds = %for.body, %entry1076 ret void1077}1078 1079declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)1080 1081;; Memmove formation. We expect exactly same memmove result like in PR46179_positive_stride output.1082define void @loop_with_memcpy_PR46179_positive_stride(ptr %Src, i64 %Size) {1083; CHECK-LABEL: @loop_with_memcpy_PR46179_positive_stride(1084; CHECK-NEXT: bb.nph:1085; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 11086; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[SRC]], ptr align 1 [[SCEVGEP]], i64 [[SIZE:%.*]], i1 false)1087; CHECK-NEXT: br label [[FOR_BODY:%.*]]1088; CHECK: for.body:1089; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]1090; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], 11091; CHECK-NEXT: [[SRCI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[STEP]]1092; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[INDVAR]]1093; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 11094; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]1095; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]1096; CHECK: for.end:1097; CHECK-NEXT: ret void1098;1099bb.nph:1100 br label %for.body1101 1102for.body: ; preds = %bb.nph, %for.body1103 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]1104 %Step = add nuw nsw i64 %indvar, 11105 %SrcI = getelementptr i8, ptr %Src, i64 %Step1106 %DestI = getelementptr i8, ptr %Src, i64 %indvar1107 call void @llvm.memcpy.p0.p0.i64(ptr align 1 %DestI, ptr align 1 %SrcI, i64 1, i1 false)1108 %indvar.next = add i64 %indvar, 11109 %exitcond = icmp eq i64 %indvar.next, %Size1110 br i1 %exitcond, label %for.end, label %for.body1111 1112for.end: ; preds = %for.body, %entry1113 ret void1114}1115 1116;; Memmove formation.1117define void @PR46179_negative_stride(ptr %Src, i64 %Size) {1118; CHECK-LABEL: @PR46179_negative_stride(1119; CHECK-NEXT: bb.nph:1120; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[SIZE:%.*]], 01121; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]1122; CHECK: for.body.preheader:1123; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 11124; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[SCEVGEP]], ptr align 1 [[SRC]], i64 [[SIZE]], i1 false)1125; CHECK-NEXT: br label [[FOR_BODY:%.*]]1126; CHECK: for.body:1127; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[STEP:%.*]], [[FOR_BODY]] ], [ [[SIZE]], [[FOR_BODY_PREHEADER]] ]1128; CHECK-NEXT: [[STEP]] = add nsw i64 [[INDVAR]], -11129; CHECK-NEXT: [[SRCI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[STEP]]1130; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[SRCI]], align 11131; CHECK-NEXT: [[DESTI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[INDVAR]]1132; CHECK-NEXT: [[EXITCOND:%.*]] = icmp sgt i64 [[INDVAR]], 11133; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]1134; CHECK: for.end.loopexit:1135; CHECK-NEXT: br label [[FOR_END]]1136; CHECK: for.end:1137; CHECK-NEXT: ret void1138;1139bb.nph:1140 %cmp1 = icmp sgt i64 %Size, 01141 br i1 %cmp1, label %for.body, label %for.end1142 1143for.body: ; preds = %bb.nph, %.for.body1144 %indvar = phi i64 [ %Step, %for.body ], [ %Size, %bb.nph ]1145 %Step = add nsw i64 %indvar, -11146 %SrcI = getelementptr inbounds i8, ptr %Src, i64 %Step1147 %V = load i8, ptr %SrcI, align 11148 %DestI = getelementptr inbounds i8, ptr %Src, i64 %indvar1149 store i8 %V, ptr %DestI, align 11150 %exitcond = icmp sgt i64 %indvar, 11151 br i1 %exitcond, label %for.body, label %for.end1152 1153for.end: ; preds = %.for.body, %bb.nph1154 ret void1155}1156 1157;; Memmove formation. We expect exactly same memmove result like in PR46179_negative_stride output.1158define void @loop_with_memcpy_PR46179_negative_stride(ptr %Src, i64 %Size) {1159; CHECK-LABEL: @loop_with_memcpy_PR46179_negative_stride(1160; CHECK-NEXT: bb.nph:1161; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[SIZE:%.*]], 01162; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]1163; CHECK: for.body.preheader:1164; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 11165; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[SCEVGEP]], ptr align 1 [[SRC]], i64 [[SIZE]], i1 false)1166; CHECK-NEXT: br label [[FOR_BODY:%.*]]1167; CHECK: for.body:1168; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[STEP:%.*]], [[FOR_BODY]] ], [ [[SIZE]], [[FOR_BODY_PREHEADER]] ]1169; CHECK-NEXT: [[STEP]] = add nsw i64 [[INDVAR]], -11170; CHECK-NEXT: [[SRCI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[STEP]]1171; CHECK-NEXT: [[DESTI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[INDVAR]]1172; CHECK-NEXT: [[EXITCOND:%.*]] = icmp sgt i64 [[INDVAR]], 11173; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]1174; CHECK: for.end.loopexit:1175; CHECK-NEXT: br label [[FOR_END]]1176; CHECK: for.end:1177; CHECK-NEXT: ret void1178;1179bb.nph:1180 %cmp1 = icmp sgt i64 %Size, 01181 br i1 %cmp1, label %for.body, label %for.end1182 1183for.body: ; preds = %bb.nph, %.for.body1184 %indvar = phi i64 [ %Step, %for.body ], [ %Size, %bb.nph ]1185 %Step = add nsw i64 %indvar, -11186 %SrcI = getelementptr inbounds i8, ptr %Src, i64 %Step1187 %DestI = getelementptr inbounds i8, ptr %Src, i64 %indvar1188 call void @llvm.memcpy.p0.p0.i64(ptr align 1 %DestI, ptr align 1 %SrcI, i64 1, i1 false)1189 %exitcond = icmp sgt i64 %indvar, 11190 br i1 %exitcond, label %for.body, label %for.end1191 1192for.end: ; preds = %.for.body, %bb.nph1193 ret void1194}1195 1196;; Memmove formation.1197define void @loop_with_memcpy_stride16(ptr %Src, i64 %Size) {1198; CHECK-LABEL: @loop_with_memcpy_stride16(1199; CHECK-NEXT: bb.nph:1200; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 161201; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[SIZE:%.*]], i64 16)1202; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[SMAX]], -11203; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 41204; CHECK-NEXT: [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 41205; CHECK-NEXT: [[TMP3:%.*]] = add nuw i64 [[TMP2]], 161206; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[SRC]], ptr align 1 [[SCEVGEP]], i64 [[TMP3]], i1 false)1207; CHECK-NEXT: br label [[FOR_BODY:%.*]]1208; CHECK: for.body:1209; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[STEP:%.*]], [[FOR_BODY]] ], [ 0, [[BB_NPH:%.*]] ]1210; CHECK-NEXT: [[STEP]] = add nuw nsw i64 [[INDVAR]], 161211; CHECK-NEXT: [[SRCI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[STEP]]1212; CHECK-NEXT: [[DESTI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[INDVAR]]1213; CHECK-NEXT: [[EXITCOND:%.*]] = icmp slt i64 [[STEP]], [[SIZE]]1214; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]1215; CHECK: for.end:1216; CHECK-NEXT: ret void1217;1218bb.nph:1219 br label %for.body1220 1221for.body: ; preds = %for.body, %bb.nph1222 %indvar = phi i64 [ %Step, %for.body ], [ 0, %bb.nph ]1223 %Step = add nuw nsw i64 %indvar, 161224 %SrcI = getelementptr inbounds i8, ptr %Src, i64 %Step1225 %DestI = getelementptr inbounds i8, ptr %Src, i64 %indvar1226 call void @llvm.memcpy.p0.p0.i64(ptr align 1 %DestI, ptr align 1 %SrcI, i64 16, i1 false)1227 %exitcond = icmp slt i64 %Step, %Size1228 br i1 %exitcond, label %for.body, label %for.end1229 1230for.end: ; preds = %for.body1231 ret void1232}1233 1234;; Do not form memmove from previous load when stride is positive.1235define void @do_not_form_memmove1(ptr %Src, i64 %Size) {1236; CHECK-LABEL: @do_not_form_memmove1(1237; CHECK-NEXT: bb.nph:1238; CHECK-NEXT: br label [[FOR_BODY:%.*]]1239; CHECK: for.body:1240; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 1, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]1241; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], -11242; CHECK-NEXT: [[SRCI:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[STEP]]1243; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[INDVAR]]1244; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[SRCI]], align 11245; CHECK-NEXT: store i8 [[V]], ptr [[DESTI]], align 11246; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 11247; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]1248; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]1249; CHECK: for.end:1250; CHECK-NEXT: ret void1251;1252bb.nph:1253 br label %for.body1254 1255for.body: ; preds = %bb.nph, %for.body1256 %indvar = phi i64 [ 1, %bb.nph ], [ %indvar.next, %for.body ]1257 %Step = add nuw nsw i64 %indvar, -11258 %SrcI = getelementptr i8, ptr %Src, i64 %Step1259 %DestI = getelementptr i8, ptr %Src, i64 %indvar1260 %V = load i8, ptr %SrcI, align 11261 store i8 %V, ptr %DestI, align 11262 %indvar.next = add i64 %indvar, 11263 %exitcond = icmp eq i64 %indvar.next, %Size1264 br i1 %exitcond, label %for.end, label %for.body1265 1266for.end: ; preds = %for.body, %entry1267 ret void1268}1269 1270;; Do not form memmove from previous load in memcpy when stride is positive.1271define void @do_not_form_memmove2(ptr %Src, i64 %Size) {1272; CHECK-LABEL: @do_not_form_memmove2(1273; CHECK-NEXT: bb.nph:1274; CHECK-NEXT: br label [[FOR_BODY:%.*]]1275; CHECK: for.body:1276; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 1, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]1277; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], -11278; CHECK-NEXT: [[SRCI:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[STEP]]1279; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[INDVAR]]1280; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DESTI]], ptr align 1 [[SRCI]], i64 1, i1 false)1281; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 11282; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]1283; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]1284; CHECK: for.end:1285; CHECK-NEXT: ret void1286;1287bb.nph:1288 br label %for.body1289 1290for.body: ; preds = %bb.nph, %for.body1291 %indvar = phi i64 [ 1, %bb.nph ], [ %indvar.next, %for.body ]1292 %Step = add nuw nsw i64 %indvar, -11293 %SrcI = getelementptr i8, ptr %Src, i64 %Step1294 %DestI = getelementptr i8, ptr %Src, i64 %indvar1295 call void @llvm.memcpy.p0.p0.i64(ptr align 1 %DestI, ptr align 1 %SrcI, i64 1, i1 false)1296 %indvar.next = add i64 %indvar, 11297 %exitcond = icmp eq i64 %indvar.next, %Size1298 br i1 %exitcond, label %for.end, label %for.body1299 1300for.end: ; preds = %for.body, %entry1301 ret void1302}1303 1304;; Do not form memmove from next load when stride is negative.1305define void @do_not_form_memmove3(ptr %Src, i64 %Size) {1306; CHECK-LABEL: @do_not_form_memmove3(1307; CHECK-NEXT: bb.nph:1308; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[SIZE:%.*]], 01309; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]1310; CHECK: for.body.preheader:1311; CHECK-NEXT: br label [[FOR_BODY:%.*]]1312; CHECK: for.body:1313; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ], [ [[SIZE]], [[FOR_BODY_PREHEADER]] ]1314; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], 11315; CHECK-NEXT: [[SRCI:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[STEP]]1316; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[SRCI]], align 11317; CHECK-NEXT: [[DESTI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[INDVAR]]1318; CHECK-NEXT: store i8 [[V]], ptr [[DESTI]], align 11319; CHECK-NEXT: [[INDVAR_NEXT]] = add nsw i64 [[INDVAR]], -11320; CHECK-NEXT: [[EXITCOND:%.*]] = icmp sgt i64 [[INDVAR]], 11321; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]1322; CHECK: for.end.loopexit:1323; CHECK-NEXT: br label [[FOR_END]]1324; CHECK: for.end:1325; CHECK-NEXT: ret void1326;1327bb.nph:1328 %cmp1 = icmp sgt i64 %Size, 01329 br i1 %cmp1, label %for.body, label %for.end1330 1331for.body: ; preds = %bb.nph, %.for.body1332 %indvar = phi i64 [ %indvar.next, %for.body ], [ %Size, %bb.nph ]1333 %Step = add nuw nsw i64 %indvar, 11334 %SrcI = getelementptr inbounds i8, ptr %Src, i64 %Step1335 %V = load i8, ptr %SrcI, align 11336 %DestI = getelementptr inbounds i8, ptr %Src, i64 %indvar1337 store i8 %V, ptr %DestI, align 11338 %indvar.next = add nsw i64 %indvar, -11339 %exitcond = icmp sgt i64 %indvar, 11340 br i1 %exitcond, label %for.body, label %for.end1341 1342for.end: ; preds = %.for.body, %bb.nph1343 ret void1344}1345 1346;; Do not form memmove from next load in memcpy when stride is negative.1347define void @do_not_form_memmove4(ptr %Src, i64 %Size) {1348; CHECK-LABEL: @do_not_form_memmove4(1349; CHECK-NEXT: bb.nph:1350; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[SIZE:%.*]], 01351; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]1352; CHECK: for.body.preheader:1353; CHECK-NEXT: br label [[FOR_BODY:%.*]]1354; CHECK: for.body:1355; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ], [ [[SIZE]], [[FOR_BODY_PREHEADER]] ]1356; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], 11357; CHECK-NEXT: [[SRCI:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[STEP]]1358; CHECK-NEXT: [[DESTI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[INDVAR]]1359; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DESTI]], ptr align 1 [[SRCI]], i64 1, i1 false)1360; CHECK-NEXT: [[INDVAR_NEXT]] = add nsw i64 [[INDVAR]], -11361; CHECK-NEXT: [[EXITCOND:%.*]] = icmp sgt i64 [[INDVAR]], 11362; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]1363; CHECK: for.end.loopexit:1364; CHECK-NEXT: br label [[FOR_END]]1365; CHECK: for.end:1366; CHECK-NEXT: ret void1367;1368bb.nph:1369 %cmp1 = icmp sgt i64 %Size, 01370 br i1 %cmp1, label %for.body, label %for.end1371 1372for.body: ; preds = %bb.nph, %.for.body1373 %indvar = phi i64 [ %indvar.next, %for.body ], [ %Size, %bb.nph ]1374 %Step = add nuw nsw i64 %indvar, 11375 %SrcI = getelementptr inbounds i8, ptr %Src, i64 %Step1376 %DestI = getelementptr inbounds i8, ptr %Src, i64 %indvar1377 call void @llvm.memcpy.p0.p0.i64(ptr align 1 %DestI, ptr align 1 %SrcI, i64 1, i1 false)1378 %indvar.next = add nsw i64 %indvar, -11379 %exitcond = icmp sgt i64 %indvar, 11380 br i1 %exitcond, label %for.body, label %for.end1381 1382for.end: ; preds = %.for.body, %bb.nph1383 ret void1384}1385 1386;; Do not form memmove when underaligned load is overlapped with store.1387define void @do_not_form_memmove5(ptr %s, i64 %size) {1388; CHECK-LABEL: @do_not_form_memmove5(1389; CHECK-NEXT: entry:1390; CHECK-NEXT: [[END_IDX:%.*]] = add i64 [[SIZE:%.*]], -11391; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i64 [[END_IDX]]1392; CHECK-NEXT: br label [[WHILE_BODY:%.*]]1393; CHECK: while.body:1394; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[S]], [[ENTRY:%.*]] ], [ [[NEXT_PTR:%.*]], [[WHILE_BODY]] ]1395; CHECK-NEXT: [[SRC_PTR:%.*]] = getelementptr i16, ptr [[PHI_PTR]], i64 11396; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[SRC_PTR]], align 21397; CHECK-NEXT: store i32 [[VAL]], ptr [[PHI_PTR]], align 41398; CHECK-NEXT: [[NEXT_PTR]] = getelementptr i32, ptr [[PHI_PTR]], i64 11399; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[NEXT_PTR]], [[END_PTR]]1400; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[WHILE_BODY]]1401; CHECK: exit:1402; CHECK-NEXT: ret void1403;1404entry:1405 %end.idx = add i64 %size, -11406 %end.ptr = getelementptr inbounds i32, ptr %s, i64 %end.idx1407 br label %while.body1408 1409while.body:1410 %phi.ptr = phi ptr [ %s, %entry ], [ %next.ptr, %while.body ]1411 %src.ptr = getelementptr i16, ptr %phi.ptr, i64 11412 ; below underaligned load is overlapped with store.1413 %val = load i32, ptr %src.ptr, align 21414 store i32 %val, ptr %phi.ptr, align 41415 %next.ptr = getelementptr i32, ptr %phi.ptr, i64 11416 %cmp = icmp eq ptr %next.ptr, %end.ptr1417 br i1 %cmp, label %exit, label %while.body1418 1419exit:1420 ret void1421}1422 1423;; Do not form memmove for memcpy with aliasing store.1424define void @do_not_form_memmove6(ptr %Src, i64 %Size) {1425; CHECK-LABEL: @do_not_form_memmove6(1426; CHECK-NEXT: bb.nph:1427; CHECK-NEXT: [[BASEALIAS:%.*]] = call ptr @external(ptr [[SRC:%.*]])1428; CHECK-NEXT: br label [[FOR_BODY:%.*]]1429; CHECK: for.body:1430; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]1431; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], 11432; CHECK-NEXT: [[SRCI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[STEP]]1433; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[INDVAR]]1434; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DESTI]], ptr align 1 [[SRCI]], i64 1, i1 false)1435; CHECK-NEXT: store i8 4, ptr [[BASEALIAS]], align 11436; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 11437; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]1438; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]1439; CHECK: for.end:1440; CHECK-NEXT: ret void1441;1442bb.nph:1443 %BaseAlias = call ptr @external(ptr %Src)1444 br label %for.body1445 1446for.body: ; preds = %bb.nph, %for.body1447 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]1448 %Step = add nuw nsw i64 %indvar, 11449 %SrcI = getelementptr i8, ptr %Src, i64 %Step1450 %DestI = getelementptr i8, ptr %Src, i64 %indvar1451 call void @llvm.memcpy.p0.p0.i64(ptr align 1 %DestI, ptr align 1 %SrcI, i64 1, i1 false)1452 store i8 4, ptr %BaseAlias1453 %indvar.next = add i64 %indvar, 11454 %exitcond = icmp eq i64 %indvar.next, %Size1455 br i1 %exitcond, label %for.end, label %for.body1456 1457for.end: ; preds = %for.body, %entry1458 ret void1459}1460 1461;; Do not form memmove when load has more than one use.1462define i32 @do_not_form_memmove7(ptr %p) {1463; CHECK-LABEL: @do_not_form_memmove7(1464; CHECK-NEXT: entry:1465; CHECK-NEXT: br label [[FOR_BODY:%.*]]1466; CHECK: for.cond.cleanup:1467; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ]1468; CHECK-NEXT: ret i32 [[ADD_LCSSA]]1469; CHECK: for.body:1470; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 15, [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[FOR_BODY]] ]1471; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD]], [[FOR_BODY]] ]1472; CHECK-NEXT: [[SUB]] = add nsw i32 [[INDEX]], -11473; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[SUB]] to i641474; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[TMP0]]1475; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 41476; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[INDEX]] to i641477; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[IDXPROM]]1478; CHECK-NEXT: store i32 [[TMP1]], ptr [[ARRAYIDX2]], align 41479; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP1]], [[SUM]]1480; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[INDEX]], 11481; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]1482;1483entry:1484 br label %for.body1485 1486for.cond.cleanup: ; preds = %for.body1487 %add.lcssa = phi i32 [ %add, %for.body ]1488 ret i32 %add.lcssa1489 1490for.body: ; preds = %entry, %for.body1491 %index = phi i32 [ 15, %entry ], [ %sub, %for.body ]1492 %sum = phi i32 [ 0, %entry ], [ %add, %for.body ]1493 %sub = add nsw i32 %index, -11494 %0 = zext i32 %sub to i641495 %arrayidx = getelementptr inbounds i32, ptr %p, i64 %01496 %1 = load i32, ptr %arrayidx, align 41497 %idxprom = zext i32 %index to i641498 %arrayidx2 = getelementptr inbounds i32, ptr %p, i64 %idxprom1499 store i32 %1, ptr %arrayidx2, align 41500 %add = add nsw i32 %1, %sum1501 %cmp = icmp sgt i32 %index, 11502 br i1 %cmp, label %for.body, label %for.cond.cleanup1503}1504 1505; Do not form memmove when there's an aliasing operation, even1506; if the memcpy source and destination are in the same object.1507define void @do_not_form_memmove8(ptr %p) {1508; CHECK-LABEL: @do_not_form_memmove8(1509; CHECK-NEXT: entry:1510; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 10001511; CHECK-NEXT: br label [[LOOP:%.*]]1512; CHECK: exit:1513; CHECK-NEXT: ret void1514; CHECK: loop:1515; CHECK-NEXT: [[X4:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X13:%.*]], [[LOOP]] ]1516; CHECK-NEXT: [[X5:%.*]] = zext i32 [[X4]] to i641517; CHECK-NEXT: [[X7:%.*]] = getelementptr inbounds i64, ptr [[P2]], i64 [[X5]]1518; CHECK-NEXT: store i64 1, ptr [[X7]], align 41519; CHECK-NEXT: [[X11:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[X5]]1520; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[X11]], ptr [[X7]], i64 8, i1 false)1521; CHECK-NEXT: [[X13]] = add i32 [[X4]], 11522; CHECK-NEXT: [[X14:%.*]] = icmp eq i32 [[X13]], 441523; CHECK-NEXT: br i1 [[X14]], label [[EXIT:%.*]], label [[LOOP]]1524;1525entry:1526 %p2 = getelementptr inbounds i64, ptr %p, i64 10001527 br label %loop1528 1529exit:1530 ret void1531 1532loop:1533 %x4 = phi i32 [ 0, %entry ], [ %x13, %loop ]1534 %x5 = zext i32 %x4 to i641535 %x7 = getelementptr inbounds i64, ptr %p2, i64 %x51536 store i64 1, ptr %x7, align 41537 %x11 = getelementptr inbounds i64, ptr %p, i64 %x51538 tail call void @llvm.memcpy.p0.p0.i64(ptr %x11, ptr %x7, i64 8, i1 false)1539 %x13 = add i32 %x4, 11540 %x14 = icmp eq i32 %x13, 441541 br i1 %x14, label %exit, label %loop1542}1543 1544;; Memcpy formation is still preferred over memmove.1545define void @prefer_memcpy_over_memmove(ptr noalias %Src, ptr noalias %Dest, i64 %Size) {1546; CHECK-LABEL: @prefer_memcpy_over_memmove(1547; CHECK-NEXT: bb.nph:1548; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 421549; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEST:%.*]], ptr align 1 [[SCEVGEP]], i64 [[SIZE:%.*]], i1 false)1550; CHECK-NEXT: br label [[FOR_BODY:%.*]]1551; CHECK: for.body:1552; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]1553; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], 421554; CHECK-NEXT: [[SRCI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[STEP]]1555; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]1556; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[SRCI]], align 11557; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 11558; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]1559; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]1560; CHECK: for.end:1561; CHECK-NEXT: ret void1562;1563bb.nph:1564 br label %for.body1565 1566for.body: ; preds = %bb.nph, %for.body1567 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]1568 %Step = add nuw nsw i64 %indvar, 421569 %SrcI = getelementptr i8, ptr %Src, i64 %Step1570 %DestI = getelementptr i8, ptr %Dest, i64 %indvar1571 %V = load i8, ptr %SrcI, align 11572 store i8 %V, ptr %DestI, align 11573 %indvar.next = add i64 %indvar, 11574 %exitcond = icmp eq i64 %indvar.next, %Size1575 br i1 %exitcond, label %for.end, label %for.body1576 1577for.end: ; preds = %for.body, %entry1578 ret void1579}1580 1581%class.CMSPULog = type { %struct._opaque_pthread_mutex_t, ptr, i32, i32, i32, i8, i8, i8, [512 x i32] }1582%struct._opaque_pthread_mutex_t = type { i64, [56 x i8] }1583 1584define noalias ptr @_ZN8CMSPULog9beginImplEja(ptr nocapture writeonly %0) local_unnamed_addr #0 {1585; CHECK-LABEL: @_ZN8CMSPULog9beginImplEja(1586; CHECK-NEXT: br label [[TMP2:%.*]]1587; CHECK: 2:1588; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ 0, [[TMP1:%.*]] ], [ [[TMP4:%.*]], [[TMP2]] ]1589; CHECK-NEXT: [[TMP4]] = add nuw nsw i32 [[TMP3]], 11590; CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[TMP3]] to i641591; CHECK-NEXT: [[TMP6:%.*]] = getelementptr [[CLASS_CMSPULOG:%.*]], ptr [[TMP0:%.*]], i64 0, i32 8, i64 [[TMP5]]1592; CHECK-NEXT: [[AND:%.*]] = and i64 ptrtoint (ptr @G to i64), 167772151593; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[AND]] to i321594; CHECK-NEXT: store i32 [[TRUNC]], ptr [[TMP6]], align 41595; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 [[TMP3]], 5111596; CHECK-NEXT: br i1 [[TMP7]], label [[TMP2]], label [[TMP8:%.*]]1597; CHECK: 8:1598; CHECK-NEXT: ret ptr null1599;1600 br label %21601 16022: ; preds = %1, %21603 %3 = phi i32 [ 0, %1 ], [ %4, %2 ]1604 %4 = add nuw nsw i32 %3, 11605 %5 = zext i32 %3 to i641606 %6 = getelementptr %class.CMSPULog, ptr %0, i64 0, i32 8, i64 %51607 %and = and i64 ptrtoint (ptr @G to i64), 167772151608 %trunc = trunc i64 %and to i321609 store i32 %trunc, ptr %6, align 41610 %7 = icmp ult i32 %3, 5111611 br i1 %7, label %2, label %81612 16138: ; preds = %21614 ret ptr null1615}1616 1617; Validate that "memset_pattern" has the proper attributes.1618;.1619; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind ssp }1620; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind }1621; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }1622; CHECK: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }1623; CHECK: attributes #[[ATTR4:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }1624;.1625