760 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; 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"4target triple = "x86_64-unknown-linux-gnu"5 6;; memcpy.atomic formation (atomic load & store)7define void @test1(i64 %Size) nounwind ssp {8; CHECK-LABEL: @test1(9; CHECK-NEXT: bb.nph:10; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 111; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 112; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[BASE]], i64 [[SIZE:%.*]], i32 1)13; CHECK-NEXT: br label [[FOR_BODY:%.*]]14; CHECK: for.body:15; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]16; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]17; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]18; CHECK-NEXT: [[V:%.*]] = load atomic i8, ptr [[I_0_014]] unordered, align 119; 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:26 %Base = alloca i8, i32 1000027 %Dest = alloca i8, i32 1000028 br label %for.body29 30for.body: ; preds = %bb.nph, %for.body31 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]32 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar33 %DestI = getelementptr i8, ptr %Dest, i64 %indvar34 %V = load atomic i8, ptr %I.0.014 unordered, align 135 store atomic i8 %V, ptr %DestI unordered, align 136 %indvar.next = add i64 %indvar, 137 %exitcond = icmp eq i64 %indvar.next, %Size38 br i1 %exitcond, label %for.end, label %for.body39 40for.end: ; preds = %for.body, %entry41 ret void42}43 44;; memcpy.atomic formation (atomic store, normal load)45define void @test2(i64 %Size) nounwind ssp {46; CHECK-LABEL: @test2(47; CHECK-NEXT: bb.nph:48; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 149; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 150; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[BASE]], i64 [[SIZE:%.*]], i32 1)51; CHECK-NEXT: br label [[FOR_BODY:%.*]]52; CHECK: for.body:53; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]54; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]55; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]56; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[I_0_014]], align 157; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 158; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]59; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]60; CHECK: for.end:61; CHECK-NEXT: ret void62;63bb.nph:64 %Base = alloca i8, i32 1000065 %Dest = alloca i8, i32 1000066 br label %for.body67 68for.body: ; preds = %bb.nph, %for.body69 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]70 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar71 %DestI = getelementptr i8, ptr %Dest, i64 %indvar72 %V = load i8, ptr %I.0.014, align 173 store atomic i8 %V, ptr %DestI unordered, align 174 %indvar.next = add i64 %indvar, 175 %exitcond = icmp eq i64 %indvar.next, %Size76 br i1 %exitcond, label %for.end, label %for.body77 78for.end: ; preds = %for.body, %entry79 ret void80}81 82;; memcpy.atomic formation (atomic store, normal load w/ no align)83define void @test2b(i64 %Size) nounwind ssp {84; CHECK-LABEL: @test2b(85; CHECK-NEXT: bb.nph:86; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 187; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 188; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[BASE]], i64 [[SIZE:%.*]], i32 1)89; CHECK-NEXT: br label [[FOR_BODY:%.*]]90; CHECK: for.body:91; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]92; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]93; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]94; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[I_0_014]], align 195; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 196; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]97; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]98; CHECK: for.end:99; CHECK-NEXT: ret void100;101bb.nph:102 %Base = alloca i8, i32 10000103 %Dest = alloca i8, i32 10000104 br label %for.body105 106for.body: ; preds = %bb.nph, %for.body107 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]108 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar109 %DestI = getelementptr i8, ptr %Dest, i64 %indvar110 %V = load i8, ptr %I.0.014111 store atomic i8 %V, ptr %DestI unordered, align 1112 %indvar.next = add i64 %indvar, 1113 %exitcond = icmp eq i64 %indvar.next, %Size114 br i1 %exitcond, label %for.end, label %for.body115 116for.end: ; preds = %for.body, %entry117 ret void118}119 120;; memcpy.atomic formation rejection (atomic store, normal load w/ bad align)121define void @test2c(i64 %Size) nounwind ssp {122; CHECK-LABEL: @test2c(123; CHECK-NEXT: bb.nph:124; CHECK-NEXT: [[BASE:%.*]] = alloca i32, i32 10000, align 4125; CHECK-NEXT: [[DEST:%.*]] = alloca i32, i32 10000, align 4126; CHECK-NEXT: br label [[FOR_BODY:%.*]]127; CHECK: for.body:128; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]129; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[INDVAR]]130; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, ptr [[DEST]], i64 [[INDVAR]]131; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[I_0_014]], align 2132; CHECK-NEXT: store atomic i32 [[V]], ptr [[DESTI]] unordered, align 4133; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1134; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]135; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]136; CHECK: for.end:137; CHECK-NEXT: ret void138;139bb.nph:140 %Base = alloca i32, i32 10000141 %Dest = alloca i32, i32 10000142 br label %for.body143 144for.body: ; preds = %bb.nph, %for.body145 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]146 %I.0.014 = getelementptr i32, ptr %Base, i64 %indvar147 %DestI = getelementptr i32, ptr %Dest, i64 %indvar148 %V = load i32, ptr %I.0.014, align 2149 store atomic i32 %V, ptr %DestI unordered, align 4150 %indvar.next = add i64 %indvar, 1151 %exitcond = icmp eq i64 %indvar.next, %Size152 br i1 %exitcond, label %for.end, label %for.body153 154for.end: ; preds = %for.body, %entry155 ret void156}157 158;; memcpy.atomic formation rejection (atomic store w/ bad align, normal load)159define void @test2d(i64 %Size) nounwind ssp {160; CHECK-LABEL: @test2d(161; CHECK-NEXT: bb.nph:162; CHECK-NEXT: [[BASE:%.*]] = alloca i32, i32 10000, align 4163; CHECK-NEXT: [[DEST:%.*]] = alloca i32, i32 10000, align 4164; CHECK-NEXT: br label [[FOR_BODY:%.*]]165; CHECK: for.body:166; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]167; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[INDVAR]]168; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, ptr [[DEST]], i64 [[INDVAR]]169; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[I_0_014]], align 4170; CHECK-NEXT: store atomic i32 [[V]], ptr [[DESTI]] unordered, align 2171; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1172; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]173; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]174; CHECK: for.end:175; CHECK-NEXT: ret void176;177bb.nph:178 %Base = alloca i32, i32 10000179 %Dest = alloca i32, i32 10000180 br label %for.body181 182for.body: ; preds = %bb.nph, %for.body183 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]184 %I.0.014 = getelementptr i32, ptr %Base, i64 %indvar185 %DestI = getelementptr i32, ptr %Dest, i64 %indvar186 %V = load i32, ptr %I.0.014, align 4187 store atomic i32 %V, ptr %DestI unordered, align 2188 %indvar.next = add i64 %indvar, 1189 %exitcond = icmp eq i64 %indvar.next, %Size190 br i1 %exitcond, label %for.end, label %for.body191 192for.end: ; preds = %for.body, %entry193 ret void194}195 196 197;; memcpy.atomic formation (normal store, atomic load)198define void @test3(i64 %Size) nounwind ssp {199; CHECK-LABEL: @test3(200; CHECK-NEXT: bb.nph:201; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 1202; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 1203; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[BASE]], i64 [[SIZE:%.*]], i32 1)204; CHECK-NEXT: br label [[FOR_BODY:%.*]]205; CHECK: for.body:206; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]207; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]208; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]209; CHECK-NEXT: [[V:%.*]] = load atomic i8, ptr [[I_0_014]] unordered, align 1210; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1211; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]212; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]213; CHECK: for.end:214; CHECK-NEXT: ret void215;216bb.nph:217 %Base = alloca i8, i32 10000218 %Dest = alloca i8, i32 10000219 br label %for.body220 221for.body: ; preds = %bb.nph, %for.body222 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]223 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar224 %DestI = getelementptr i8, ptr %Dest, i64 %indvar225 %V = load atomic i8, ptr %I.0.014 unordered, align 1226 store i8 %V, ptr %DestI, align 1227 %indvar.next = add i64 %indvar, 1228 %exitcond = icmp eq i64 %indvar.next, %Size229 br i1 %exitcond, label %for.end, label %for.body230 231for.end: ; preds = %for.body, %entry232 ret void233}234 235;; memcpy.atomic formation rejection (normal store w/ no align, atomic load)236define void @test3b(i64 %Size) nounwind ssp {237; CHECK-LABEL: @test3b(238; CHECK-NEXT: bb.nph:239; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 1240; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 1241; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[BASE]], i64 [[SIZE:%.*]], i32 1)242; CHECK-NEXT: br label [[FOR_BODY:%.*]]243; CHECK: for.body:244; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]245; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]246; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]247; CHECK-NEXT: [[V:%.*]] = load atomic i8, ptr [[I_0_014]] unordered, align 1248; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1249; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]250; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]251; CHECK: for.end:252; CHECK-NEXT: ret void253;254bb.nph:255 %Base = alloca i8, i32 10000256 %Dest = alloca i8, i32 10000257 br label %for.body258 259for.body: ; preds = %bb.nph, %for.body260 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]261 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar262 %DestI = getelementptr i8, ptr %Dest, i64 %indvar263 %V = load atomic i8, ptr %I.0.014 unordered, align 1264 store i8 %V, ptr %DestI265 %indvar.next = add i64 %indvar, 1266 %exitcond = icmp eq i64 %indvar.next, %Size267 br i1 %exitcond, label %for.end, label %for.body268 269for.end: ; preds = %for.body, %entry270 ret void271}272 273;; memcpy.atomic formation rejection (normal store, atomic load w/ bad align)274define void @test3c(i64 %Size) nounwind ssp {275; CHECK-LABEL: @test3c(276; CHECK-NEXT: bb.nph:277; CHECK-NEXT: [[BASE:%.*]] = alloca i32, i32 10000, align 4278; CHECK-NEXT: [[DEST:%.*]] = alloca i32, i32 10000, align 4279; CHECK-NEXT: br label [[FOR_BODY:%.*]]280; CHECK: for.body:281; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]282; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[INDVAR]]283; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, ptr [[DEST]], i64 [[INDVAR]]284; CHECK-NEXT: [[V:%.*]] = load atomic i32, ptr [[I_0_014]] unordered, align 2285; CHECK-NEXT: store i32 [[V]], ptr [[DESTI]], align 4286; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1287; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]288; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]289; CHECK: for.end:290; CHECK-NEXT: ret void291;292bb.nph:293 %Base = alloca i32, i32 10000294 %Dest = alloca i32, i32 10000295 br label %for.body296 297for.body: ; preds = %bb.nph, %for.body298 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]299 %I.0.014 = getelementptr i32, ptr %Base, i64 %indvar300 %DestI = getelementptr i32, ptr %Dest, i64 %indvar301 %V = load atomic i32, ptr %I.0.014 unordered, align 2302 store i32 %V, ptr %DestI, align 4303 %indvar.next = add i64 %indvar, 1304 %exitcond = icmp eq i64 %indvar.next, %Size305 br i1 %exitcond, label %for.end, label %for.body306 307for.end: ; preds = %for.body, %entry308 ret void309}310 311;; memcpy.atomic formation rejection (normal store w/ bad align, atomic load)312define void @test3d(i64 %Size) nounwind ssp {313; CHECK-LABEL: @test3d(314; CHECK-NEXT: bb.nph:315; CHECK-NEXT: [[BASE:%.*]] = alloca i32, i32 10000, align 4316; CHECK-NEXT: [[DEST:%.*]] = alloca i32, i32 10000, align 4317; CHECK-NEXT: br label [[FOR_BODY:%.*]]318; CHECK: for.body:319; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]320; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[INDVAR]]321; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, ptr [[DEST]], i64 [[INDVAR]]322; CHECK-NEXT: [[V:%.*]] = load atomic i32, ptr [[I_0_014]] unordered, align 4323; CHECK-NEXT: store i32 [[V]], ptr [[DESTI]], align 2324; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1325; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]326; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]327; CHECK: for.end:328; CHECK-NEXT: ret void329;330bb.nph:331 %Base = alloca i32, i32 10000332 %Dest = alloca i32, i32 10000333 br label %for.body334 335for.body: ; preds = %bb.nph, %for.body336 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]337 %I.0.014 = getelementptr i32, ptr %Base, i64 %indvar338 %DestI = getelementptr i32, ptr %Dest, i64 %indvar339 %V = load atomic i32, ptr %I.0.014 unordered, align 4340 store i32 %V, ptr %DestI, align 2341 %indvar.next = add i64 %indvar, 1342 %exitcond = icmp eq i64 %indvar.next, %Size343 br i1 %exitcond, label %for.end, label %for.body344 345for.end: ; preds = %for.body, %entry346 ret void347}348 349 350;; memcpy.atomic formation rejection (atomic load, ordered-atomic store)351define void @test4(i64 %Size) nounwind ssp {352; CHECK-LABEL: @test4(353; CHECK-NEXT: bb.nph:354; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 1355; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 1356; CHECK-NEXT: br label [[FOR_BODY:%.*]]357; CHECK: for.body:358; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]359; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]360; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]361; CHECK-NEXT: [[V:%.*]] = load atomic i8, ptr [[I_0_014]] unordered, align 1362; CHECK-NEXT: store atomic i8 [[V]], ptr [[DESTI]] monotonic, align 1363; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1364; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]365; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]366; CHECK: for.end:367; CHECK-NEXT: ret void368;369bb.nph:370 %Base = alloca i8, i32 10000371 %Dest = alloca i8, i32 10000372 br label %for.body373 374for.body: ; preds = %bb.nph, %for.body375 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]376 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar377 %DestI = getelementptr i8, ptr %Dest, i64 %indvar378 %V = load atomic i8, ptr %I.0.014 unordered, align 1379 store atomic i8 %V, ptr %DestI monotonic, align 1380 %indvar.next = add i64 %indvar, 1381 %exitcond = icmp eq i64 %indvar.next, %Size382 br i1 %exitcond, label %for.end, label %for.body383 384for.end: ; preds = %for.body, %entry385 ret void386}387 388;; memcpy.atomic formation rejection (ordered-atomic load, unordered-atomic store)389define void @test5(i64 %Size) nounwind ssp {390; CHECK-LABEL: @test5(391; CHECK-NEXT: bb.nph:392; CHECK-NEXT: [[BASE:%.*]] = alloca i8, i32 10000, align 1393; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i32 10000, align 1394; CHECK-NEXT: br label [[FOR_BODY:%.*]]395; CHECK: for.body:396; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]397; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[INDVAR]]398; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[INDVAR]]399; CHECK-NEXT: [[V:%.*]] = load atomic i8, ptr [[I_0_014]] monotonic, align 1400; CHECK-NEXT: store atomic i8 [[V]], ptr [[DESTI]] unordered, align 1401; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1402; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]403; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]404; CHECK: for.end:405; CHECK-NEXT: ret void406;407bb.nph:408 %Base = alloca i8, i32 10000409 %Dest = alloca i8, i32 10000410 br label %for.body411 412for.body: ; preds = %bb.nph, %for.body413 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]414 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar415 %DestI = getelementptr i8, ptr %Dest, i64 %indvar416 %V = load atomic i8, ptr %I.0.014 monotonic, align 1417 store atomic i8 %V, ptr %DestI unordered, align 1418 %indvar.next = add i64 %indvar, 1419 %exitcond = icmp eq i64 %indvar.next, %Size420 br i1 %exitcond, label %for.end, label %for.body421 422for.end: ; preds = %for.body, %entry423 ret void424}425 426;; memcpy.atomic formation (atomic load & store) -- element size 2427define void @test6(i64 %Size) nounwind ssp {428; CHECK-LABEL: @test6(429; CHECK-NEXT: bb.nph:430; CHECK-NEXT: [[BASE:%.*]] = alloca i16, i32 10000, align 2431; CHECK-NEXT: [[DEST:%.*]] = alloca i16, i32 10000, align 2432; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 1433; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 2 [[DEST]], ptr align 2 [[BASE]], i64 [[TMP0]], i32 2)434; CHECK-NEXT: br label [[FOR_BODY:%.*]]435; CHECK: for.body:436; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]437; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i16, ptr [[BASE]], i64 [[INDVAR]]438; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i16, ptr [[DEST]], i64 [[INDVAR]]439; CHECK-NEXT: [[V:%.*]] = load atomic i16, ptr [[I_0_014]] unordered, align 2440; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1441; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]442; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]443; CHECK: for.end:444; CHECK-NEXT: ret void445;446bb.nph:447 %Base = alloca i16, i32 10000448 %Dest = alloca i16, i32 10000449 br label %for.body450 451for.body: ; preds = %bb.nph, %for.body452 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]453 %I.0.014 = getelementptr i16, ptr %Base, i64 %indvar454 %DestI = getelementptr i16, ptr %Dest, i64 %indvar455 %V = load atomic i16, ptr %I.0.014 unordered, align 2456 store atomic i16 %V, ptr %DestI unordered, align 2457 %indvar.next = add i64 %indvar, 1458 %exitcond = icmp eq i64 %indvar.next, %Size459 br i1 %exitcond, label %for.end, label %for.body460 461for.end: ; preds = %for.body, %entry462 ret void463}464 465;; memcpy.atomic formation (atomic load & store) -- element size 4466define void @test7(i64 %Size) nounwind ssp {467; CHECK-LABEL: @test7(468; CHECK-NEXT: bb.nph:469; CHECK-NEXT: [[BASE:%.*]] = alloca i32, i32 10000, align 4470; CHECK-NEXT: [[DEST:%.*]] = alloca i32, i32 10000, align 4471; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 2472; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[BASE]], i64 [[TMP0]], i32 4)473; CHECK-NEXT: br label [[FOR_BODY:%.*]]474; CHECK: for.body:475; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]476; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[INDVAR]]477; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i32, ptr [[DEST]], i64 [[INDVAR]]478; CHECK-NEXT: [[V:%.*]] = load atomic i32, ptr [[I_0_014]] unordered, align 4479; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1480; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]481; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]482; CHECK: for.end:483; CHECK-NEXT: ret void484;485bb.nph:486 %Base = alloca i32, i32 10000487 %Dest = alloca i32, i32 10000488 br label %for.body489 490for.body: ; preds = %bb.nph, %for.body491 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]492 %I.0.014 = getelementptr i32, ptr %Base, i64 %indvar493 %DestI = getelementptr i32, ptr %Dest, i64 %indvar494 %V = load atomic i32, ptr %I.0.014 unordered, align 4495 store atomic i32 %V, ptr %DestI unordered, align 4496 %indvar.next = add i64 %indvar, 1497 %exitcond = icmp eq i64 %indvar.next, %Size498 br i1 %exitcond, label %for.end, label %for.body499 500for.end: ; preds = %for.body, %entry501 ret void502}503 504;; memcpy.atomic formation (atomic load & store) -- element size 8505define void @test8(i64 %Size) nounwind ssp {506; CHECK-LABEL: @test8(507; CHECK-NEXT: bb.nph:508; CHECK-NEXT: [[BASE:%.*]] = alloca i64, i32 10000, align 8509; CHECK-NEXT: [[DEST:%.*]] = alloca i64, i32 10000, align 8510; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 3511; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 8 [[DEST]], ptr align 8 [[BASE]], i64 [[TMP0]], i32 8)512; CHECK-NEXT: br label [[FOR_BODY:%.*]]513; CHECK: for.body:514; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]515; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i64, ptr [[BASE]], i64 [[INDVAR]]516; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i64, ptr [[DEST]], i64 [[INDVAR]]517; CHECK-NEXT: [[V:%.*]] = load atomic i64, ptr [[I_0_014]] unordered, align 8518; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1519; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]520; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]521; CHECK: for.end:522; CHECK-NEXT: ret void523;524bb.nph:525 %Base = alloca i64, i32 10000526 %Dest = alloca i64, i32 10000527 br label %for.body528 529for.body: ; preds = %bb.nph, %for.body530 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]531 %I.0.014 = getelementptr i64, ptr %Base, i64 %indvar532 %DestI = getelementptr i64, ptr %Dest, i64 %indvar533 %V = load atomic i64, ptr %I.0.014 unordered, align 8534 store atomic i64 %V, ptr %DestI unordered, align 8535 %indvar.next = add i64 %indvar, 1536 %exitcond = icmp eq i64 %indvar.next, %Size537 br i1 %exitcond, label %for.end, label %for.body538 539for.end: ; preds = %for.body, %entry540 ret void541}542 543;; memcpy.atomic formation rejection (atomic load & store) -- element size 16544define void @test9(i64 %Size) nounwind ssp {545; CHECK-LABEL: @test9(546; CHECK-NEXT: bb.nph:547; CHECK-NEXT: [[BASE:%.*]] = alloca i128, i32 10000, align 8548; CHECK-NEXT: [[DEST:%.*]] = alloca i128, i32 10000, align 8549; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[SIZE:%.*]], 4550; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 16 [[DEST]], ptr align 16 [[BASE]], i64 [[TMP0]], i32 16)551; CHECK-NEXT: br label [[FOR_BODY:%.*]]552; CHECK: for.body:553; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]554; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i128, ptr [[BASE]], i64 [[INDVAR]]555; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i128, ptr [[DEST]], i64 [[INDVAR]]556; CHECK-NEXT: [[V:%.*]] = load atomic i128, ptr [[I_0_014]] unordered, align 16557; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1558; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE]]559; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]560; CHECK: for.end:561; CHECK-NEXT: ret void562;563bb.nph:564 %Base = alloca i128, i32 10000565 %Dest = alloca i128, i32 10000566 br label %for.body567 568for.body: ; preds = %bb.nph, %for.body569 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]570 %I.0.014 = getelementptr i128, ptr %Base, i64 %indvar571 %DestI = getelementptr i128, ptr %Dest, i64 %indvar572 %V = load atomic i128, ptr %I.0.014 unordered, align 16573 store atomic i128 %V, ptr %DestI unordered, align 16574 %indvar.next = add i64 %indvar, 1575 %exitcond = icmp eq i64 %indvar.next, %Size576 br i1 %exitcond, label %for.end, label %for.body577 578for.end: ; preds = %for.body, %entry579 ret void580}581 582;; memcpy.atomic formation rejection (atomic load & store) -- element size 32583define void @test10(i64 %Size) nounwind ssp {584; CHECK-LABEL: @test10(585; CHECK-NEXT: bb.nph:586; CHECK-NEXT: [[BASE:%.*]] = alloca i256, i32 10000, align 8587; CHECK-NEXT: [[DEST:%.*]] = alloca i256, i32 10000, align 8588; CHECK-NEXT: br label [[FOR_BODY:%.*]]589; CHECK: for.body:590; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]591; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i256, ptr [[BASE]], i64 [[INDVAR]]592; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i256, ptr [[DEST]], i64 [[INDVAR]]593; CHECK-NEXT: [[V:%.*]] = load atomic i256, ptr [[I_0_014]] unordered, align 32594; CHECK-NEXT: store atomic i256 [[V]], ptr [[DESTI]] unordered, align 32595; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1596; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]597; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]598; CHECK: for.end:599; CHECK-NEXT: ret void600;601bb.nph:602 %Base = alloca i256, i32 10000603 %Dest = alloca i256, i32 10000604 br label %for.body605 606for.body: ; preds = %bb.nph, %for.body607 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]608 %I.0.014 = getelementptr i256, ptr %Base, i64 %indvar609 %DestI = getelementptr i256, ptr %Dest, i64 %indvar610 %V = load atomic i256, ptr %I.0.014 unordered, align 32611 store atomic i256 %V, ptr %DestI unordered, align 32612 %indvar.next = add i64 %indvar, 1613 %exitcond = icmp eq i64 %indvar.next, %Size614 br i1 %exitcond, label %for.end, label %for.body615 616for.end: ; preds = %for.body, %entry617 ret void618}619 620 621 622; Make sure that atomic memset doesn't get recognized by mistake623define void @test_nomemset(ptr %Base, i64 %Size) nounwind ssp {624; CHECK-LABEL: @test_nomemset(625; CHECK-NEXT: bb.nph:626; CHECK-NEXT: br label [[FOR_BODY:%.*]]627; CHECK: for.body:628; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]629; CHECK-NEXT: [[I_0_014:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 [[INDVAR]]630; CHECK-NEXT: store atomic i8 0, ptr [[I_0_014]] unordered, align 1631; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1632; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]633; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]634; CHECK: for.end:635; CHECK-NEXT: ret void636;637bb.nph: ; preds = %entry638 br label %for.body639 640for.body: ; preds = %bb.nph, %for.body641 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]642 %I.0.014 = getelementptr i8, ptr %Base, i64 %indvar643 store atomic i8 0, ptr %I.0.014 unordered, align 1644 %indvar.next = add i64 %indvar, 1645 %exitcond = icmp eq i64 %indvar.next, %Size646 br i1 %exitcond, label %for.end, label %for.body647 648for.end: ; preds = %for.body, %entry649 ret void650}651 652; Verify that unordered memset_pattern isn't recognized.653; This is a replica of test11_pattern from basic.ll654define void @test_nomemset_pattern(ptr nocapture %P) nounwind ssp {655; CHECK-LABEL: @test_nomemset_pattern(656; CHECK-NEXT: entry:657; CHECK-NEXT: br label [[FOR_BODY:%.*]]658; CHECK: for.body:659; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]660; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDVAR]]661; CHECK-NEXT: store atomic i32 1, ptr [[ARRAYIDX]] unordered, align 4662; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1663; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 10000664; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]665; CHECK: for.end:666; CHECK-NEXT: ret void667;668entry:669 br label %for.body670 671for.body: ; preds = %entry, %for.body672 %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ]673 %arrayidx = getelementptr i32, ptr %P, i64 %indvar674 store atomic i32 1, ptr %arrayidx unordered, align 4675 %indvar.next = add i64 %indvar, 1676 %exitcond = icmp eq i64 %indvar.next, 10000677 br i1 %exitcond, label %for.end, label %for.body678 679for.end: ; preds = %for.body680 ret void681}682 683; Make sure that atomic memcpy or memmove don't get recognized by mistake684; when looping with positive stride685define void @test_no_memcpy_memmove1(ptr %Src, i64 %Size) {686; CHECK-LABEL: @test_no_memcpy_memmove1(687; CHECK-NEXT: bb.nph:688; CHECK-NEXT: br label [[FOR_BODY:%.*]]689; CHECK: for.body:690; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_BODY]] ]691; CHECK-NEXT: [[STEP:%.*]] = add nuw nsw i64 [[INDVAR]], 1692; CHECK-NEXT: [[SRCI:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[STEP]]693; CHECK-NEXT: [[DESTI:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[INDVAR]]694; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[SRCI]], align 1695; CHECK-NEXT: store atomic i8 [[V]], ptr [[DESTI]] unordered, align 1696; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1697; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[SIZE:%.*]]698; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]699; CHECK: for.end:700; CHECK-NEXT: ret void701;702bb.nph:703 br label %for.body704 705for.body: ; preds = %bb.nph, %for.body706 %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]707 %Step = add nuw nsw i64 %indvar, 1708 %SrcI = getelementptr i8, ptr %Src, i64 %Step709 %DestI = getelementptr i8, ptr %Src, i64 %indvar710 %V = load i8, ptr %SrcI, align 1711 store atomic i8 %V, ptr %DestI unordered, align 1712 %indvar.next = add i64 %indvar, 1713 %exitcond = icmp eq i64 %indvar.next, %Size714 br i1 %exitcond, label %for.end, label %for.body715 716for.end: ; preds = %for.body, %entry717 ret void718}719 720; Make sure that atomic memcpy or memmove don't get recognized by mistake721; when looping with negative stride722define void @test_no_memcpy_memmove2(ptr %Src, i64 %Size) {723; CHECK-LABEL: @test_no_memcpy_memmove2(724; CHECK-NEXT: bb.nph:725; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[SIZE:%.*]], 0726; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]727; CHECK: for.body.preheader:728; CHECK-NEXT: br label [[FOR_BODY:%.*]]729; CHECK: for.body:730; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[STEP:%.*]], [[FOR_BODY]] ], [ [[SIZE]], [[FOR_BODY_PREHEADER]] ]731; CHECK-NEXT: [[STEP]] = add nsw i64 [[INDVAR]], -1732; CHECK-NEXT: [[SRCI:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[STEP]]733; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[SRCI]], align 1734; CHECK-NEXT: [[DESTI:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[INDVAR]]735; CHECK-NEXT: store atomic i8 [[V]], ptr [[DESTI]] unordered, align 1736; CHECK-NEXT: [[EXITCOND:%.*]] = icmp sgt i64 [[INDVAR]], 1737; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]738; CHECK: for.end.loopexit:739; CHECK-NEXT: br label [[FOR_END]]740; CHECK: for.end:741; CHECK-NEXT: ret void742;743bb.nph:744 %cmp1 = icmp sgt i64 %Size, 0745 br i1 %cmp1, label %for.body, label %for.end746 747for.body: ; preds = %bb.nph, %.for.body748 %indvar = phi i64 [ %Step, %for.body ], [ %Size, %bb.nph ]749 %Step = add nsw i64 %indvar, -1750 %SrcI = getelementptr inbounds i8, ptr %Src, i64 %Step751 %V = load i8, ptr %SrcI, align 1752 %DestI = getelementptr inbounds i8, ptr %Src, i64 %indvar753 store atomic i8 %V, ptr %DestI unordered, align 1754 %exitcond = icmp sgt i64 %indvar, 1755 br i1 %exitcond, label %for.body, label %for.end756 757for.end: ; preds = %for.body, %entry758 ret void759}760