brintos

brintos / llvm-project-archived public Read only

0
0
Text · 70.1 KiB · 9deccf5 Raw
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