1554 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=gvn -enable-load-pre -S | FileCheck %s --check-prefixes=CHECK,MDEP3; RUN: opt < %s -passes='gvn<memoryssa>' -enable-load-pre -S | FileCheck %s --check-prefixes=CHECK,MSSA4; RUN: opt < %s -aa-pipeline=basic-aa -passes="gvn<load-pre>" -enable-load-pre=false -S | FileCheck %s5target 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"6 7define i32 @test1(ptr %p, i1 %C) {8; MDEP-LABEL: @test1(9; MDEP-NEXT: block1:10; MDEP-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]11; MDEP: block2:12; MDEP-NEXT: [[PRE_PRE:%.*]] = load i32, ptr [[P:%.*]], align 413; MDEP-NEXT: br label [[BLOCK4:%.*]]14; MDEP: block3:15; MDEP-NEXT: store i32 0, ptr [[P]], align 416; MDEP-NEXT: br label [[BLOCK4]]17; MDEP: block4:18; MDEP-NEXT: [[PRE:%.*]] = phi i32 [ 0, [[BLOCK3]] ], [ [[PRE_PRE]], [[BLOCK2]] ]19; MDEP-NEXT: ret i32 [[PRE]]20;21; MSSA-LABEL: @test1(22; MSSA-NEXT: block1:23; MSSA-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]24; MSSA: block2:25; MSSA-NEXT: br label [[BLOCK4:%.*]]26; MSSA: block3:27; MSSA-NEXT: store i32 0, ptr [[P:%.*]], align 428; MSSA-NEXT: br label [[BLOCK4]]29; MSSA: block4:30; MSSA-NEXT: [[PRE:%.*]] = load i32, ptr [[P]], align 431; MSSA-NEXT: ret i32 [[PRE]]32;33block1:34 br i1 %C, label %block2, label %block335 36block2:37 br label %block438 39block3:40 store i32 0, ptr %p41 br label %block442 43block4:44 %PRE = load i32, ptr %p45 ret i32 %PRE46}47 48; This is a simple phi translation case.49define i32 @test2(ptr %p, ptr %q, i1 %C) {50; MDEP-LABEL: @test2(51; MDEP-NEXT: block1:52; MDEP-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]53; MDEP: block2:54; MDEP-NEXT: [[PRE_PRE:%.*]] = load i32, ptr [[Q:%.*]], align 455; MDEP-NEXT: br label [[BLOCK4:%.*]]56; MDEP: block3:57; MDEP-NEXT: store i32 0, ptr [[P:%.*]], align 458; MDEP-NEXT: br label [[BLOCK4]]59; MDEP: block4:60; MDEP-NEXT: [[PRE:%.*]] = phi i32 [ 0, [[BLOCK3]] ], [ [[PRE_PRE]], [[BLOCK2]] ]61; MDEP-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q]], [[BLOCK2]] ]62; MDEP-NEXT: ret i32 [[PRE]]63;64; MSSA-LABEL: @test2(65; MSSA-NEXT: block1:66; MSSA-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]67; MSSA: block2:68; MSSA-NEXT: br label [[BLOCK4:%.*]]69; MSSA: block3:70; MSSA-NEXT: store i32 0, ptr [[P:%.*]], align 471; MSSA-NEXT: br label [[BLOCK4]]72; MSSA: block4:73; MSSA-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q:%.*]], [[BLOCK2]] ]74; MSSA-NEXT: [[PRE:%.*]] = load i32, ptr [[P2]], align 475; MSSA-NEXT: ret i32 [[PRE]]76;77block1:78 br i1 %C, label %block2, label %block379 80block2:81 br label %block482 83block3:84 store i32 0, ptr %p85 br label %block486 87block4:88 %P2 = phi ptr [%p, %block3], [%q, %block2]89 %PRE = load i32, ptr %P290 ret i32 %PRE91}92 93; This is a PRE case that requires phi translation through a GEP.94define i32 @test3(ptr %p, ptr %q, ptr %Hack, i1 %C) {95; MDEP-LABEL: @test3(96; MDEP-NEXT: block1:97; MDEP-NEXT: [[B:%.*]] = getelementptr i32, ptr [[Q:%.*]], i32 198; MDEP-NEXT: store ptr [[B]], ptr [[HACK:%.*]], align 899; MDEP-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]100; MDEP: block2:101; MDEP-NEXT: [[PRE_PRE:%.*]] = load i32, ptr [[B]], align 4102; MDEP-NEXT: br label [[BLOCK4:%.*]]103; MDEP: block3:104; MDEP-NEXT: [[A:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1105; MDEP-NEXT: store i32 0, ptr [[A]], align 4106; MDEP-NEXT: br label [[BLOCK4]]107; MDEP: block4:108; MDEP-NEXT: [[PRE:%.*]] = phi i32 [ 0, [[BLOCK3]] ], [ [[PRE_PRE]], [[BLOCK2]] ]109; MDEP-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q]], [[BLOCK2]] ]110; MDEP-NEXT: [[P3:%.*]] = getelementptr i32, ptr [[P2]], i32 1111; MDEP-NEXT: ret i32 [[PRE]]112;113; MSSA-LABEL: @test3(114; MSSA-NEXT: block1:115; MSSA-NEXT: [[B:%.*]] = getelementptr i32, ptr [[Q:%.*]], i32 1116; MSSA-NEXT: store ptr [[B]], ptr [[HACK:%.*]], align 8117; MSSA-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]118; MSSA: block2:119; MSSA-NEXT: br label [[BLOCK4:%.*]]120; MSSA: block3:121; MSSA-NEXT: [[A:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1122; MSSA-NEXT: store i32 0, ptr [[A]], align 4123; MSSA-NEXT: br label [[BLOCK4]]124; MSSA: block4:125; MSSA-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q]], [[BLOCK2]] ]126; MSSA-NEXT: [[P3:%.*]] = getelementptr i32, ptr [[P2]], i32 1127; MSSA-NEXT: [[PRE:%.*]] = load i32, ptr [[P3]], align 4128; MSSA-NEXT: ret i32 [[PRE]]129;130block1:131 %B = getelementptr i32, ptr %q, i32 1132 store ptr %B, ptr %Hack133 br i1 %C, label %block2, label %block3134 135block2:136 br label %block4137 138block3:139 %A = getelementptr i32, ptr %p, i32 1140 store i32 0, ptr %A141 br label %block4142 143block4:144 %P2 = phi ptr [%p, %block3], [%q, %block2]145 %P3 = getelementptr i32, ptr %P2, i32 1146 %PRE = load i32, ptr %P3147 ret i32 %PRE148}149 150;; Here the loaded address is available, but the computation is in 'block3'151;; which does not dominate 'block2'.152define i32 @test4(ptr %p, ptr %q, ptr %Hack, i1 %C) {153; MDEP-LABEL: @test4(154; MDEP-NEXT: block1:155; MDEP-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]156; MDEP: block2:157; MDEP-NEXT: [[P3_PHI_TRANS_INSERT:%.*]] = getelementptr i32, ptr [[Q:%.*]], i32 1158; MDEP-NEXT: [[PRE_PRE:%.*]] = load i32, ptr [[P3_PHI_TRANS_INSERT]], align 4159; MDEP-NEXT: br label [[BLOCK4:%.*]]160; MDEP: block3:161; MDEP-NEXT: [[B:%.*]] = getelementptr i32, ptr [[Q]], i32 1162; MDEP-NEXT: store ptr [[B]], ptr [[HACK:%.*]], align 8163; MDEP-NEXT: [[A:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1164; MDEP-NEXT: store i32 0, ptr [[A]], align 4165; MDEP-NEXT: br label [[BLOCK4]]166; MDEP: block4:167; MDEP-NEXT: [[PRE:%.*]] = phi i32 [ 0, [[BLOCK3]] ], [ [[PRE_PRE]], [[BLOCK2]] ]168; MDEP-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q]], [[BLOCK2]] ]169; MDEP-NEXT: [[P3:%.*]] = getelementptr i32, ptr [[P2]], i32 1170; MDEP-NEXT: ret i32 [[PRE]]171;172; MSSA-LABEL: @test4(173; MSSA-NEXT: block1:174; MSSA-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]175; MSSA: block2:176; MSSA-NEXT: br label [[BLOCK4:%.*]]177; MSSA: block3:178; MSSA-NEXT: [[B:%.*]] = getelementptr i32, ptr [[Q:%.*]], i32 1179; MSSA-NEXT: store ptr [[B]], ptr [[HACK:%.*]], align 8180; MSSA-NEXT: [[A:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1181; MSSA-NEXT: store i32 0, ptr [[A]], align 4182; MSSA-NEXT: br label [[BLOCK4]]183; MSSA: block4:184; MSSA-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q]], [[BLOCK2]] ]185; MSSA-NEXT: [[P3:%.*]] = getelementptr i32, ptr [[P2]], i32 1186; MSSA-NEXT: [[PRE:%.*]] = load i32, ptr [[P3]], align 4187; MSSA-NEXT: ret i32 [[PRE]]188;189block1:190 br i1 %C, label %block2, label %block3191 192block2:193 br label %block4194 195block3:196 %B = getelementptr i32, ptr %q, i32 1197 store ptr %B, ptr %Hack198 199 %A = getelementptr i32, ptr %p, i32 1200 store i32 0, ptr %A201 br label %block4202 203block4:204 %P2 = phi ptr [%p, %block3], [%q, %block2]205 %P3 = getelementptr i32, ptr %P2, i32 1206 %PRE = load i32, ptr %P3207 ret i32 %PRE208}209 210; Same as test4, with a nuw flag on the GEP.211define i32 @test4_nuw(ptr %p, ptr %q, ptr %Hack, i1 %C) {212; MDEP-LABEL: @test4_nuw(213; MDEP-NEXT: block1:214; MDEP-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]215; MDEP: block2:216; MDEP-NEXT: [[P3_PHI_TRANS_INSERT:%.*]] = getelementptr nuw i32, ptr [[Q:%.*]], i32 1217; MDEP-NEXT: [[PRE_PRE:%.*]] = load i32, ptr [[P3_PHI_TRANS_INSERT]], align 4218; MDEP-NEXT: br label [[BLOCK4:%.*]]219; MDEP: block3:220; MDEP-NEXT: [[B:%.*]] = getelementptr i32, ptr [[Q]], i32 1221; MDEP-NEXT: store ptr [[B]], ptr [[HACK:%.*]], align 8222; MDEP-NEXT: [[A:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1223; MDEP-NEXT: store i32 0, ptr [[A]], align 4224; MDEP-NEXT: br label [[BLOCK4]]225; MDEP: block4:226; MDEP-NEXT: [[PRE:%.*]] = phi i32 [ 0, [[BLOCK3]] ], [ [[PRE_PRE]], [[BLOCK2]] ]227; MDEP-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q]], [[BLOCK2]] ]228; MDEP-NEXT: [[P3:%.*]] = getelementptr nuw i32, ptr [[P2]], i32 1229; MDEP-NEXT: ret i32 [[PRE]]230;231; MSSA-LABEL: @test4_nuw(232; MSSA-NEXT: block1:233; MSSA-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]234; MSSA: block2:235; MSSA-NEXT: br label [[BLOCK4:%.*]]236; MSSA: block3:237; MSSA-NEXT: [[B:%.*]] = getelementptr i32, ptr [[Q:%.*]], i32 1238; MSSA-NEXT: store ptr [[B]], ptr [[HACK:%.*]], align 8239; MSSA-NEXT: [[A:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1240; MSSA-NEXT: store i32 0, ptr [[A]], align 4241; MSSA-NEXT: br label [[BLOCK4]]242; MSSA: block4:243; MSSA-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q]], [[BLOCK2]] ]244; MSSA-NEXT: [[P3:%.*]] = getelementptr nuw i32, ptr [[P2]], i32 1245; MSSA-NEXT: [[PRE:%.*]] = load i32, ptr [[P3]], align 4246; MSSA-NEXT: ret i32 [[PRE]]247;248block1:249 br i1 %C, label %block2, label %block3250 251block2:252 br label %block4253 254block3:255 %B = getelementptr i32, ptr %q, i32 1256 store ptr %B, ptr %Hack257 258 %A = getelementptr i32, ptr %p, i32 1259 store i32 0, ptr %A260 br label %block4261 262block4:263 %P2 = phi ptr [%p, %block3], [%q, %block2]264 %P3 = getelementptr nuw i32, ptr %P2, i32 1265 %PRE = load i32, ptr %P3266 ret i32 %PRE267}268 269;void test5(int N, ptr G) {270; int j;271; for (j = 0; j < N - 1; j++)272; G[j] = G[j] + G[j+1];273;}274 275define void @test5(i32 %N, ptr nocapture %G) nounwind ssp {276; MDEP-LABEL: @test5(277; MDEP-NEXT: entry:278; MDEP-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1279; MDEP-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0280; MDEP-NEXT: br i1 [[TMP1]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]281; MDEP: bb.nph:282; MDEP-NEXT: [[TMP:%.*]] = zext i32 [[TMP0]] to i64283; MDEP-NEXT: [[DOTPRE:%.*]] = load double, ptr [[G:%.*]], align 8284; MDEP-NEXT: br label [[BB:%.*]]285; MDEP: bb:286; MDEP-NEXT: [[TMP2:%.*]] = phi double [ [[DOTPRE]], [[BB_NPH]] ], [ [[TMP3:%.*]], [[BB]] ]287; MDEP-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP6:%.*]], [[BB]] ]288; MDEP-NEXT: [[TMP6]] = add i64 [[INDVAR]], 1289; MDEP-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP6]]290; MDEP-NEXT: [[SCEVGEP7:%.*]] = getelementptr double, ptr [[G]], i64 [[INDVAR]]291; MDEP-NEXT: [[TMP3]] = load double, ptr [[SCEVGEP]], align 8292; MDEP-NEXT: [[TMP4:%.*]] = fadd double [[TMP2]], [[TMP3]]293; MDEP-NEXT: store double [[TMP4]], ptr [[SCEVGEP7]], align 8294; MDEP-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP6]], [[TMP]]295; MDEP-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]296; MDEP: return:297; MDEP-NEXT: ret void298;299; MSSA-LABEL: @test5(300; MSSA-NEXT: entry:301; MSSA-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1302; MSSA-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0303; MSSA-NEXT: br i1 [[TMP1]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]304; MSSA: bb.nph:305; MSSA-NEXT: [[TMP:%.*]] = zext i32 [[TMP0]] to i64306; MSSA-NEXT: br label [[BB:%.*]]307; MSSA: bb:308; MSSA-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP6:%.*]], [[BB]] ]309; MSSA-NEXT: [[TMP6]] = add i64 [[INDVAR]], 1310; MSSA-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G:%.*]], i64 [[TMP6]]311; MSSA-NEXT: [[SCEVGEP7:%.*]] = getelementptr double, ptr [[G]], i64 [[INDVAR]]312; MSSA-NEXT: [[TMP2:%.*]] = load double, ptr [[SCEVGEP7]], align 8313; MSSA-NEXT: [[TMP3:%.*]] = load double, ptr [[SCEVGEP]], align 8314; MSSA-NEXT: [[TMP4:%.*]] = fadd double [[TMP2]], [[TMP3]]315; MSSA-NEXT: store double [[TMP4]], ptr [[SCEVGEP7]], align 8316; MSSA-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP6]], [[TMP]]317; MSSA-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]318; MSSA: return:319; MSSA-NEXT: ret void320;321entry:322 %0 = add i32 %N, -1323 %1 = icmp sgt i32 %0, 0324 br i1 %1, label %bb.nph, label %return325 326bb.nph:327 %tmp = zext i32 %0 to i64328 br label %bb329 330 331bb:332 %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ]333 %tmp6 = add i64 %indvar, 1334 %scevgep = getelementptr double, ptr %G, i64 %tmp6335 %scevgep7 = getelementptr double, ptr %G, i64 %indvar336 %2 = load double, ptr %scevgep7, align 8337 %3 = load double, ptr %scevgep, align 8338 %4 = fadd double %2, %3339 store double %4, ptr %scevgep7, align 8340 %exitcond = icmp eq i64 %tmp6, %tmp341 br i1 %exitcond, label %return, label %bb342 343; Should only be one load in the loop.344 345return:346 ret void347}348 349;void test6(int N, ptr G) {350; int j;351; for (j = 0; j < N - 1; j++)352; G[j+1] = G[j] + G[j+1];353;}354 355define void @test6(i32 %N, ptr nocapture %G) nounwind ssp {356; MDEP-LABEL: @test6(357; MDEP-NEXT: entry:358; MDEP-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1359; MDEP-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0360; MDEP-NEXT: br i1 [[TMP1]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]361; MDEP: bb.nph:362; MDEP-NEXT: [[TMP:%.*]] = zext i32 [[TMP0]] to i64363; MDEP-NEXT: [[DOTPRE:%.*]] = load double, ptr [[G:%.*]], align 8364; MDEP-NEXT: br label [[BB:%.*]]365; MDEP: bb:366; MDEP-NEXT: [[TMP2:%.*]] = phi double [ [[DOTPRE]], [[BB_NPH]] ], [ [[TMP4:%.*]], [[BB]] ]367; MDEP-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP6:%.*]], [[BB]] ]368; MDEP-NEXT: [[TMP6]] = add i64 [[INDVAR]], 1369; MDEP-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP6]]370; MDEP-NEXT: [[SCEVGEP7:%.*]] = getelementptr double, ptr [[G]], i64 [[INDVAR]]371; MDEP-NEXT: [[TMP3:%.*]] = load double, ptr [[SCEVGEP]], align 8372; MDEP-NEXT: [[TMP4]] = fadd double [[TMP2]], [[TMP3]]373; MDEP-NEXT: store double [[TMP4]], ptr [[SCEVGEP]], align 8374; MDEP-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP6]], [[TMP]]375; MDEP-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]376; MDEP: return:377; MDEP-NEXT: ret void378;379; MSSA-LABEL: @test6(380; MSSA-NEXT: entry:381; MSSA-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1382; MSSA-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0383; MSSA-NEXT: br i1 [[TMP1]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]384; MSSA: bb.nph:385; MSSA-NEXT: [[TMP:%.*]] = zext i32 [[TMP0]] to i64386; MSSA-NEXT: br label [[BB:%.*]]387; MSSA: bb:388; MSSA-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP6:%.*]], [[BB]] ]389; MSSA-NEXT: [[TMP6]] = add i64 [[INDVAR]], 1390; MSSA-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G:%.*]], i64 [[TMP6]]391; MSSA-NEXT: [[SCEVGEP7:%.*]] = getelementptr double, ptr [[G]], i64 [[INDVAR]]392; MSSA-NEXT: [[TMP2:%.*]] = load double, ptr [[SCEVGEP7]], align 8393; MSSA-NEXT: [[TMP3:%.*]] = load double, ptr [[SCEVGEP]], align 8394; MSSA-NEXT: [[TMP4:%.*]] = fadd double [[TMP2]], [[TMP3]]395; MSSA-NEXT: store double [[TMP4]], ptr [[SCEVGEP]], align 8396; MSSA-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP6]], [[TMP]]397; MSSA-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]398; MSSA: return:399; MSSA-NEXT: ret void400;401entry:402 %0 = add i32 %N, -1403 %1 = icmp sgt i32 %0, 0404 br i1 %1, label %bb.nph, label %return405 406bb.nph:407 %tmp = zext i32 %0 to i64408 br label %bb409 410 411bb:412 %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ]413 %tmp6 = add i64 %indvar, 1414 %scevgep = getelementptr double, ptr %G, i64 %tmp6415 %scevgep7 = getelementptr double, ptr %G, i64 %indvar416 %2 = load double, ptr %scevgep7, align 8417 %3 = load double, ptr %scevgep, align 8418 %4 = fadd double %2, %3419 store double %4, ptr %scevgep, align 8420 %exitcond = icmp eq i64 %tmp6, %tmp421 br i1 %exitcond, label %return, label %bb422 423; Should only be one load in the loop.424 425return:426 ret void427}428 429;void test7(int N, ptr G) {430; long j;431; G[1] = 1;432; for (j = 1; j < N - 1; j++)433; G[j+1] = G[j] + G[j+1];434;}435 436; This requires phi translation of the adds.437define void @test7(i32 %N, ptr nocapture %G) nounwind ssp {438; MDEP-LABEL: @test7(439; MDEP-NEXT: entry:440; MDEP-NEXT: [[TMP0:%.*]] = getelementptr inbounds double, ptr [[G:%.*]], i64 1441; MDEP-NEXT: store double 1.000000e+00, ptr [[TMP0]], align 8442; MDEP-NEXT: [[TMP1:%.*]] = add i32 [[N:%.*]], -1443; MDEP-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], 1444; MDEP-NEXT: br i1 [[TMP2]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]445; MDEP: bb.nph:446; MDEP-NEXT: [[TMP:%.*]] = sext i32 [[TMP1]] to i64447; MDEP-NEXT: [[TMP7:%.*]] = add i64 [[TMP]], -1448; MDEP-NEXT: br label [[BB:%.*]]449; MDEP: bb:450; MDEP-NEXT: [[TMP3:%.*]] = phi double [ 1.000000e+00, [[BB_NPH]] ], [ [[TMP5:%.*]], [[BB]] ]451; MDEP-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP9:%.*]], [[BB]] ]452; MDEP-NEXT: [[TMP8:%.*]] = add i64 [[INDVAR]], 2453; MDEP-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP8]]454; MDEP-NEXT: [[TMP9]] = add i64 [[INDVAR]], 1455; MDEP-NEXT: [[SCEVGEP10:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP9]]456; MDEP-NEXT: [[TMP4:%.*]] = load double, ptr [[SCEVGEP]], align 8457; MDEP-NEXT: [[TMP5]] = fadd double [[TMP3]], [[TMP4]]458; MDEP-NEXT: store double [[TMP5]], ptr [[SCEVGEP]], align 8459; MDEP-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP9]], [[TMP7]]460; MDEP-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]461; MDEP: return:462; MDEP-NEXT: ret void463;464; MSSA-LABEL: @test7(465; MSSA-NEXT: entry:466; MSSA-NEXT: [[TMP0:%.*]] = getelementptr inbounds double, ptr [[G:%.*]], i64 1467; MSSA-NEXT: store double 1.000000e+00, ptr [[TMP0]], align 8468; MSSA-NEXT: [[TMP1:%.*]] = add i32 [[N:%.*]], -1469; MSSA-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], 1470; MSSA-NEXT: br i1 [[TMP2]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]471; MSSA: bb.nph:472; MSSA-NEXT: [[TMP:%.*]] = sext i32 [[TMP1]] to i64473; MSSA-NEXT: [[TMP7:%.*]] = add i64 [[TMP]], -1474; MSSA-NEXT: br label [[BB:%.*]]475; MSSA: bb:476; MSSA-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP9:%.*]], [[BB]] ]477; MSSA-NEXT: [[TMP8:%.*]] = add i64 [[INDVAR]], 2478; MSSA-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP8]]479; MSSA-NEXT: [[TMP9]] = add i64 [[INDVAR]], 1480; MSSA-NEXT: [[SCEVGEP10:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP9]]481; MSSA-NEXT: [[TMP3:%.*]] = load double, ptr [[SCEVGEP10]], align 8482; MSSA-NEXT: [[TMP4:%.*]] = load double, ptr [[SCEVGEP]], align 8483; MSSA-NEXT: [[TMP5:%.*]] = fadd double [[TMP3]], [[TMP4]]484; MSSA-NEXT: store double [[TMP5]], ptr [[SCEVGEP]], align 8485; MSSA-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP9]], [[TMP7]]486; MSSA-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]487; MSSA: return:488; MSSA-NEXT: ret void489;490entry:491 %0 = getelementptr inbounds double, ptr %G, i64 1492 store double 1.000000e+00, ptr %0, align 8493 %1 = add i32 %N, -1494 %2 = icmp sgt i32 %1, 1495 br i1 %2, label %bb.nph, label %return496 497bb.nph:498 %tmp = sext i32 %1 to i64499 %tmp7 = add i64 %tmp, -1500 br label %bb501 502bb:503 %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ]504 %tmp8 = add i64 %indvar, 2505 %scevgep = getelementptr double, ptr %G, i64 %tmp8506 %tmp9 = add i64 %indvar, 1507 %scevgep10 = getelementptr double, ptr %G, i64 %tmp9508 %3 = load double, ptr %scevgep10, align 8509 %4 = load double, ptr %scevgep, align 8510 %5 = fadd double %3, %4511 store double %5, ptr %scevgep, align 8512 %exitcond = icmp eq i64 %tmp9, %tmp7513 br i1 %exitcond, label %return, label %bb514 515; Should only be one load in the loop.516 517return:518 ret void519}520 521;; Here the loaded address isn't available in 'block2' at all, requiring a new522;; GEP to be inserted into it.523define i32 @test8(ptr %p, ptr %q, ptr %Hack, i1 %C) {524; MDEP-LABEL: @test8(525; MDEP-NEXT: block1:526; MDEP-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]527; MDEP: block2:528; MDEP-NEXT: [[P3_PHI_TRANS_INSERT:%.*]] = getelementptr i32, ptr [[Q:%.*]], i32 1529; MDEP-NEXT: [[PRE_PRE:%.*]] = load i32, ptr [[P3_PHI_TRANS_INSERT]], align 4530; MDEP-NEXT: br label [[BLOCK4:%.*]]531; MDEP: block3:532; MDEP-NEXT: [[A:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1533; MDEP-NEXT: store i32 0, ptr [[A]], align 4534; MDEP-NEXT: br label [[BLOCK4]]535; MDEP: block4:536; MDEP-NEXT: [[PRE:%.*]] = phi i32 [ 0, [[BLOCK3]] ], [ [[PRE_PRE]], [[BLOCK2]] ]537; MDEP-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q]], [[BLOCK2]] ]538; MDEP-NEXT: [[P3:%.*]] = getelementptr i32, ptr [[P2]], i32 1539; MDEP-NEXT: ret i32 [[PRE]]540;541; MSSA-LABEL: @test8(542; MSSA-NEXT: block1:543; MSSA-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]544; MSSA: block2:545; MSSA-NEXT: br label [[BLOCK4:%.*]]546; MSSA: block3:547; MSSA-NEXT: [[A:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1548; MSSA-NEXT: store i32 0, ptr [[A]], align 4549; MSSA-NEXT: br label [[BLOCK4]]550; MSSA: block4:551; MSSA-NEXT: [[P2:%.*]] = phi ptr [ [[P]], [[BLOCK3]] ], [ [[Q:%.*]], [[BLOCK2]] ]552; MSSA-NEXT: [[P3:%.*]] = getelementptr i32, ptr [[P2]], i32 1553; MSSA-NEXT: [[PRE:%.*]] = load i32, ptr [[P3]], align 4554; MSSA-NEXT: ret i32 [[PRE]]555;556block1:557 br i1 %C, label %block2, label %block3558 559block2:560 br label %block4561 562block3:563 %A = getelementptr i32, ptr %p, i32 1564 store i32 0, ptr %A565 br label %block4566 567block4:568 %P2 = phi ptr [%p, %block3], [%q, %block2]569 %P3 = getelementptr i32, ptr %P2, i32 1570 %PRE = load i32, ptr %P3571 ret i32 %PRE572}573 574;void test9(int N, ptr G) {575; long j;576; for (j = 1; j < N - 1; j++)577; G[j+1] = G[j] + G[j+1];578;}579 580; This requires phi translation of the adds.581define void @test9(i32 %N, ptr nocapture %G) nounwind ssp {582; MDEP-LABEL: @test9(583; MDEP-NEXT: entry:584; MDEP-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1585; MDEP-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 1586; MDEP-NEXT: br i1 [[TMP1]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]587; MDEP: bb.nph:588; MDEP-NEXT: [[TMP:%.*]] = sext i32 [[TMP0]] to i64589; MDEP-NEXT: [[TMP7:%.*]] = add i64 [[TMP]], -1590; MDEP-NEXT: [[SCEVGEP10_PHI_TRANS_INSERT:%.*]] = getelementptr double, ptr [[G:%.*]], i64 1591; MDEP-NEXT: [[DOTPRE:%.*]] = load double, ptr [[SCEVGEP10_PHI_TRANS_INSERT]], align 8592; MDEP-NEXT: br label [[BB:%.*]]593; MDEP: bb:594; MDEP-NEXT: [[TMP2:%.*]] = phi double [ [[DOTPRE]], [[BB_NPH]] ], [ [[TMP4:%.*]], [[BB]] ]595; MDEP-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP9:%.*]], [[BB]] ]596; MDEP-NEXT: [[TMP8:%.*]] = add i64 [[INDVAR]], 2597; MDEP-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP8]]598; MDEP-NEXT: [[TMP9]] = add i64 [[INDVAR]], 1599; MDEP-NEXT: [[SCEVGEP10:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP9]]600; MDEP-NEXT: [[TMP3:%.*]] = load double, ptr [[SCEVGEP]], align 8601; MDEP-NEXT: [[TMP4]] = fadd double [[TMP2]], [[TMP3]]602; MDEP-NEXT: store double [[TMP4]], ptr [[SCEVGEP]], align 8603; MDEP-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP9]], [[TMP7]]604; MDEP-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]605; MDEP: return:606; MDEP-NEXT: ret void607;608; MSSA-LABEL: @test9(609; MSSA-NEXT: entry:610; MSSA-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1611; MSSA-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 1612; MSSA-NEXT: br i1 [[TMP1]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]613; MSSA: bb.nph:614; MSSA-NEXT: [[TMP:%.*]] = sext i32 [[TMP0]] to i64615; MSSA-NEXT: [[TMP7:%.*]] = add i64 [[TMP]], -1616; MSSA-NEXT: br label [[BB:%.*]]617; MSSA: bb:618; MSSA-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP9:%.*]], [[BB]] ]619; MSSA-NEXT: [[TMP8:%.*]] = add i64 [[INDVAR]], 2620; MSSA-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G:%.*]], i64 [[TMP8]]621; MSSA-NEXT: [[TMP9]] = add i64 [[INDVAR]], 1622; MSSA-NEXT: [[SCEVGEP10:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP9]]623; MSSA-NEXT: [[TMP2:%.*]] = load double, ptr [[SCEVGEP10]], align 8624; MSSA-NEXT: [[TMP3:%.*]] = load double, ptr [[SCEVGEP]], align 8625; MSSA-NEXT: [[TMP4:%.*]] = fadd double [[TMP2]], [[TMP3]]626; MSSA-NEXT: store double [[TMP4]], ptr [[SCEVGEP]], align 8627; MSSA-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP9]], [[TMP7]]628; MSSA-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]629; MSSA: return:630; MSSA-NEXT: ret void631;632entry:633 add i32 0, 0634 %1 = add i32 %N, -1635 %2 = icmp sgt i32 %1, 1636 br i1 %2, label %bb.nph, label %return637 638bb.nph:639 %tmp = sext i32 %1 to i64640 %tmp7 = add i64 %tmp, -1641 br label %bb642 643 644bb:645 %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ]646 %tmp8 = add i64 %indvar, 2647 %scevgep = getelementptr double, ptr %G, i64 %tmp8648 %tmp9 = add i64 %indvar, 1649 %scevgep10 = getelementptr double, ptr %G, i64 %tmp9650 %3 = load double, ptr %scevgep10, align 8651 %4 = load double, ptr %scevgep, align 8652 %5 = fadd double %3, %4653 store double %5, ptr %scevgep, align 8654 %exitcond = icmp eq i64 %tmp9, %tmp7655 br i1 %exitcond, label %return, label %bb656 657; Should only be one load in the loop.658 659return:660 ret void661}662 663;void test10(int N, ptr G) {664; long j;665; for (j = 1; j < N - 1; j++)666; G[j] = G[j] + G[j+1] + G[j-1];667;}668 669; PR5501670define void @test10(i32 %N, ptr nocapture %G) nounwind ssp {671; MDEP-LABEL: @test10(672; MDEP-NEXT: entry:673; MDEP-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1674; MDEP-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 1675; MDEP-NEXT: br i1 [[TMP1]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]676; MDEP: bb.nph:677; MDEP-NEXT: [[TMP:%.*]] = sext i32 [[TMP0]] to i64678; MDEP-NEXT: [[TMP8:%.*]] = add i64 [[TMP]], -1679; MDEP-NEXT: [[SCEVGEP12_PHI_TRANS_INSERT:%.*]] = getelementptr double, ptr [[G:%.*]], i64 1680; MDEP-NEXT: [[DOTPRE:%.*]] = load double, ptr [[SCEVGEP12_PHI_TRANS_INSERT]], align 8681; MDEP-NEXT: [[DOTPRE1:%.*]] = load double, ptr [[G]], align 8682; MDEP-NEXT: br label [[BB:%.*]]683; MDEP: bb:684; MDEP-NEXT: [[TMP2:%.*]] = phi double [ [[DOTPRE1]], [[BB_NPH]] ], [ [[TMP6:%.*]], [[BB]] ]685; MDEP-NEXT: [[TMP3:%.*]] = phi double [ [[DOTPRE]], [[BB_NPH]] ], [ [[TMP4:%.*]], [[BB]] ]686; MDEP-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP11:%.*]], [[BB]] ]687; MDEP-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G]], i64 [[INDVAR]]688; MDEP-NEXT: [[TMP9:%.*]] = add i64 [[INDVAR]], 2689; MDEP-NEXT: [[SCEVGEP10:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP9]]690; MDEP-NEXT: [[TMP11]] = add i64 [[INDVAR]], 1691; MDEP-NEXT: [[SCEVGEP12:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP11]]692; MDEP-NEXT: [[TMP4]] = load double, ptr [[SCEVGEP10]], align 8693; MDEP-NEXT: [[TMP5:%.*]] = fadd double [[TMP3]], [[TMP4]]694; MDEP-NEXT: [[TMP6]] = fadd double [[TMP5]], [[TMP2]]695; MDEP-NEXT: store double [[TMP6]], ptr [[SCEVGEP12]], align 8696; MDEP-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP11]], [[TMP8]]697; MDEP-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]698; MDEP: return:699; MDEP-NEXT: ret void700;701; MSSA-LABEL: @test10(702; MSSA-NEXT: entry:703; MSSA-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], -1704; MSSA-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 1705; MSSA-NEXT: br i1 [[TMP1]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]706; MSSA: bb.nph:707; MSSA-NEXT: [[TMP:%.*]] = sext i32 [[TMP0]] to i64708; MSSA-NEXT: [[TMP8:%.*]] = add i64 [[TMP]], -1709; MSSA-NEXT: br label [[BB:%.*]]710; MSSA: bb:711; MSSA-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[TMP11:%.*]], [[BB]] ]712; MSSA-NEXT: [[SCEVGEP:%.*]] = getelementptr double, ptr [[G:%.*]], i64 [[INDVAR]]713; MSSA-NEXT: [[TMP9:%.*]] = add i64 [[INDVAR]], 2714; MSSA-NEXT: [[SCEVGEP10:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP9]]715; MSSA-NEXT: [[TMP11]] = add i64 [[INDVAR]], 1716; MSSA-NEXT: [[SCEVGEP12:%.*]] = getelementptr double, ptr [[G]], i64 [[TMP11]]717; MSSA-NEXT: [[TMP2:%.*]] = load double, ptr [[SCEVGEP12]], align 8718; MSSA-NEXT: [[TMP3:%.*]] = load double, ptr [[SCEVGEP10]], align 8719; MSSA-NEXT: [[TMP4:%.*]] = fadd double [[TMP2]], [[TMP3]]720; MSSA-NEXT: [[TMP5:%.*]] = load double, ptr [[SCEVGEP]], align 8721; MSSA-NEXT: [[TMP6:%.*]] = fadd double [[TMP4]], [[TMP5]]722; MSSA-NEXT: store double [[TMP6]], ptr [[SCEVGEP12]], align 8723; MSSA-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[TMP11]], [[TMP8]]724; MSSA-NEXT: br i1 [[EXITCOND]], label [[RETURN]], label [[BB]]725; MSSA: return:726; MSSA-NEXT: ret void727;728entry:729 %0 = add i32 %N, -1730 %1 = icmp sgt i32 %0, 1731 br i1 %1, label %bb.nph, label %return732 733bb.nph:734 %tmp = sext i32 %0 to i64735 %tmp8 = add i64 %tmp, -1736 br label %bb737 738 739bb:740 %indvar = phi i64 [ 0, %bb.nph ], [ %tmp11, %bb ]741 %scevgep = getelementptr double, ptr %G, i64 %indvar742 %tmp9 = add i64 %indvar, 2743 %scevgep10 = getelementptr double, ptr %G, i64 %tmp9744 %tmp11 = add i64 %indvar, 1745 %scevgep12 = getelementptr double, ptr %G, i64 %tmp11746 %2 = load double, ptr %scevgep12, align 8747 %3 = load double, ptr %scevgep10, align 8748 %4 = fadd double %2, %3749 %5 = load double, ptr %scevgep, align 8750 %6 = fadd double %4, %5751 store double %6, ptr %scevgep12, align 8752 %exitcond = icmp eq i64 %tmp11, %tmp8753 br i1 %exitcond, label %return, label %bb754 755; Should only be one load in the loop.756 757return:758 ret void759}760 761; Test critical edge splitting.762define i32 @test11(ptr %p, i1 %C, i32 %N) {763; MDEP-LABEL: @test11(764; MDEP-NEXT: block1:765; MDEP-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]766; MDEP: block2:767; MDEP-NEXT: [[COND:%.*]] = icmp sgt i32 [[N:%.*]], 1768; MDEP-NEXT: br i1 [[COND]], label [[BLOCK2_BLOCK4_CRIT_EDGE:%.*]], label [[BLOCK5:%.*]]769; MDEP: block2.block4_crit_edge:770; MDEP-NEXT: [[PRE_PRE:%.*]] = load i32, ptr [[P:%.*]], align 4771; MDEP-NEXT: br label [[BLOCK4:%.*]]772; MDEP: block3:773; MDEP-NEXT: store i32 0, ptr [[P]], align 4774; MDEP-NEXT: br label [[BLOCK4]]775; MDEP: block4:776; MDEP-NEXT: [[PRE:%.*]] = phi i32 [ [[PRE_PRE]], [[BLOCK2_BLOCK4_CRIT_EDGE]] ], [ 0, [[BLOCK3]] ]777; MDEP-NEXT: br label [[BLOCK5]]778; MDEP: block5:779; MDEP-NEXT: [[RET:%.*]] = phi i32 [ 0, [[BLOCK2]] ], [ [[PRE]], [[BLOCK4]] ]780; MDEP-NEXT: ret i32 [[RET]]781;782; MSSA-LABEL: @test11(783; MSSA-NEXT: block1:784; MSSA-NEXT: br i1 [[C:%.*]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]785; MSSA: block2:786; MSSA-NEXT: [[COND:%.*]] = icmp sgt i32 [[N:%.*]], 1787; MSSA-NEXT: br i1 [[COND]], label [[BLOCK4:%.*]], label [[BLOCK5:%.*]]788; MSSA: block3:789; MSSA-NEXT: store i32 0, ptr [[P:%.*]], align 4790; MSSA-NEXT: br label [[BLOCK4]]791; MSSA: block4:792; MSSA-NEXT: [[PRE:%.*]] = load i32, ptr [[P]], align 4793; MSSA-NEXT: br label [[BLOCK5]]794; MSSA: block5:795; MSSA-NEXT: [[RET:%.*]] = phi i32 [ 0, [[BLOCK2]] ], [ [[PRE]], [[BLOCK4]] ]796; MSSA-NEXT: ret i32 [[RET]]797;798block1:799 br i1 %C, label %block2, label %block3800 801block2:802 %cond = icmp sgt i32 %N, 1803 br i1 %cond, label %block4, label %block5804 805block3:806 store i32 0, ptr %p807 br label %block4808 809block4:810 %PRE = load i32, ptr %p811 br label %block5812 813block5:814 %ret = phi i32 [ 0, %block2 ], [ %PRE, %block4 ]815 ret i32 %ret816}817 818declare void @f()819declare void @g(i32)820declare i32 @__CxxFrameHandler3(...)821 822; Test that loads aren't PRE'd into EH pads.823define void @test12(ptr %p) personality ptr @__CxxFrameHandler3 {824; CHECK-LABEL: @test12(825; CHECK-NEXT: block1:826; CHECK-NEXT: invoke void @f()827; CHECK-NEXT: to label [[BLOCK2:%.*]] unwind label [[CATCH_DISPATCH:%.*]]828; CHECK: block2:829; CHECK-NEXT: invoke void @f()830; CHECK-NEXT: to label [[BLOCK3:%.*]] unwind label [[CLEANUP:%.*]]831; CHECK: block3:832; CHECK-NEXT: ret void833; CHECK: catch.dispatch:834; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind label [[CLEANUP2:%.*]]835; CHECK: catch:836; CHECK-NEXT: [[C:%.*]] = catchpad within [[CS1]] []837; CHECK-NEXT: catchret from [[C]] to label [[BLOCK2]]838; CHECK: cleanup:839; CHECK-NEXT: [[C1:%.*]] = cleanuppad within none []840; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4841; CHECK-NEXT: cleanupret from [[C1]] unwind label [[CLEANUP2]]842; CHECK: cleanup2:843; CHECK-NEXT: [[C2:%.*]] = cleanuppad within none []844; CHECK-NEXT: [[NOTPRE:%.*]] = load i32, ptr [[P]], align 4845; CHECK-NEXT: call void @g(i32 [[NOTPRE]])846; CHECK-NEXT: cleanupret from [[C2]] unwind to caller847;848block1:849 invoke void @f()850 to label %block2 unwind label %catch.dispatch851 852block2:853 invoke void @f()854 to label %block3 unwind label %cleanup855 856block3:857 ret void858 859catch.dispatch:860 %cs1 = catchswitch within none [label %catch] unwind label %cleanup2861 862catch:863 %c = catchpad within %cs1 []864 catchret from %c to label %block2865 866cleanup:867 %c1 = cleanuppad within none []868 store i32 0, ptr %p869 cleanupret from %c1 unwind label %cleanup2870 871cleanup2:872 %c2 = cleanuppad within none []873 %NOTPRE = load i32, ptr %p874 call void @g(i32 %NOTPRE)875 cleanupret from %c2 unwind to caller876}877 878; Don't PRE load across potentially throwing calls.879 880define i32 @test13(ptr noalias nocapture readonly %x, ptr noalias nocapture %r, i32 %a) {881; CHECK-LABEL: @test13(882; CHECK-NEXT: entry:883; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0884; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]885; CHECK: if.then:886; CHECK-NEXT: [[UU:%.*]] = load i32, ptr [[X:%.*]], align 4887; CHECK-NEXT: store i32 [[UU]], ptr [[R:%.*]], align 4888; CHECK-NEXT: br label [[IF_END]]889; CHECK: if.end:890; CHECK-NEXT: call void @f()891; CHECK-NEXT: [[VV:%.*]] = load i32, ptr [[X]], align 4892; CHECK-NEXT: ret i32 [[VV]]893;894 895entry:896 %tobool = icmp eq i32 %a, 0897 br i1 %tobool, label %if.end, label %if.then898 899 900if.then:901 %uu = load i32, ptr %x, align 4902 store i32 %uu, ptr %r, align 4903 br label %if.end904 905 906if.end:907 call void @f()908 %vv = load i32, ptr %x, align 4909 ret i32 %vv910}911 912; Same as test13, but now the blocking function is not immediately in load's913; block.914 915define i32 @test14(ptr noalias nocapture readonly %x, ptr noalias nocapture %r, i32 %a) {916; CHECK-LABEL: @test14(917; CHECK-NEXT: entry:918; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0919; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]920; CHECK: if.then:921; CHECK-NEXT: [[UU:%.*]] = load i32, ptr [[X:%.*]], align 4922; CHECK-NEXT: store i32 [[UU]], ptr [[R:%.*]], align 4923; CHECK-NEXT: br label [[IF_END]]924; CHECK: if.end:925; CHECK-NEXT: call void @f()926; CHECK-NEXT: [[VV:%.*]] = load i32, ptr [[X]], align 4927; CHECK-NEXT: ret i32 [[VV]]928;929 930entry:931 %tobool = icmp eq i32 %a, 0932 br i1 %tobool, label %if.end, label %if.then933 934 935if.then:936 %uu = load i32, ptr %x, align 4937 store i32 %uu, ptr %r, align 4938 br label %if.end939 940 941if.end:942 call void @f()943 br label %follow_1944 945follow_1:946 br label %follow_2947 948follow_2:949 %vv = load i32, ptr %x, align 4950 ret i32 %vv951}952 953; Same as test13, but %x here is dereferenceable. A pointer that is954; dereferenceable can be loaded from speculatively without a risk of trapping.955; Since it is OK to speculate, PRE is allowed.956 957define i32 @test15(ptr noalias nocapture readonly dereferenceable(8) align 4 %x, ptr noalias nocapture %r, i32 %a) nofree nosync {958; MDEP-LABEL: @test15(959; MDEP-NEXT: entry:960; MDEP-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0961; MDEP-NEXT: [[VV_PRE:%.*]] = load i32, ptr [[X:%.*]], align 4962; MDEP-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]963; MDEP: if.then:964; MDEP-NEXT: store i32 [[VV_PRE]], ptr [[R:%.*]], align 4965; MDEP-NEXT: br label [[IF_END]]966; MDEP: if.end:967; MDEP-NEXT: call void @f()968; MDEP-NEXT: ret i32 [[VV_PRE]]969;970; MSSA-LABEL: @test15(971; MSSA-NEXT: entry:972; MSSA-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 0973; MSSA-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]974; MSSA: if.then:975; MSSA-NEXT: [[UU:%.*]] = load i32, ptr [[X:%.*]], align 4976; MSSA-NEXT: store i32 [[UU]], ptr [[R:%.*]], align 4977; MSSA-NEXT: br label [[IF_END]]978; MSSA: if.end:979; MSSA-NEXT: call void @f()980; MSSA-NEXT: [[VV:%.*]] = load i32, ptr [[X]], align 4981; MSSA-NEXT: ret i32 [[VV]]982;983 984entry:985 %tobool = icmp eq i32 %a, 0986 br i1 %tobool, label %if.end, label %if.then987 988 989if.then:990 %uu = load i32, ptr %x, align 4991 store i32 %uu, ptr %r, align 4992 br label %if.end993 994 995if.end:996 call void @f()997 %vv = load i32, ptr %x, align 4998 ret i32 %vv999 1000 1001}1002 1003; Same as test14, but %x here is dereferenceable. A pointer that is1004; dereferenceable can be loaded from speculatively without a risk of trapping.1005; Since it is OK to speculate, PRE is allowed.1006 1007define i32 @test16(ptr noalias nocapture readonly dereferenceable(8) align 4 %x, ptr noalias nocapture %r, i32 %a) nofree nosync {1008; MDEP-LABEL: @test16(1009; MDEP-NEXT: entry:1010; MDEP-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 01011; MDEP-NEXT: [[VV_PRE:%.*]] = load i32, ptr [[X:%.*]], align 41012; MDEP-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]1013; MDEP: if.then:1014; MDEP-NEXT: store i32 [[VV_PRE]], ptr [[R:%.*]], align 41015; MDEP-NEXT: br label [[IF_END]]1016; MDEP: if.end:1017; MDEP-NEXT: call void @f()1018; MDEP-NEXT: ret i32 [[VV_PRE]]1019;1020; MSSA-LABEL: @test16(1021; MSSA-NEXT: entry:1022; MSSA-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A:%.*]], 01023; MSSA-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]1024; MSSA: if.then:1025; MSSA-NEXT: [[UU:%.*]] = load i32, ptr [[X:%.*]], align 41026; MSSA-NEXT: store i32 [[UU]], ptr [[R:%.*]], align 41027; MSSA-NEXT: br label [[IF_END]]1028; MSSA: if.end:1029; MSSA-NEXT: call void @f()1030; MSSA-NEXT: [[VV:%.*]] = load i32, ptr [[X]], align 41031; MSSA-NEXT: ret i32 [[VV]]1032;1033 1034entry:1035 %tobool = icmp eq i32 %a, 01036 br i1 %tobool, label %if.end, label %if.then1037 1038 1039if.then:1040 %uu = load i32, ptr %x, align 41041 store i32 %uu, ptr %r, align 41042 br label %if.end1043 1044 1045if.end:1046 call void @f()1047 br label %follow_11048 1049 1050follow_1:1051 br label %follow_21052 1053follow_2:1054 %vv = load i32, ptr %x, align 41055 ret i32 %vv1056}1057 1058declare i1 @foo()1059declare i1 @bar()1060 1061; %v3 is partially redundant, bb3 has multiple predecessors coming through1062; critical edges. The other successors of those predecessors have same loads.1063; We can move all loads into predecessors.1064 1065define void @test17(ptr %p1, ptr %p2, ptr %p3, ptr %p4)1066; MDEP-LABEL: @test17(1067; MDEP-NEXT: entry:1068; MDEP-NEXT: [[V1:%.*]] = load i64, ptr [[P1:%.*]], align 81069; MDEP-NEXT: [[COND1:%.*]] = icmp sgt i64 [[V1]], 2001070; MDEP-NEXT: br i1 [[COND1]], label [[BB200:%.*]], label [[BB1:%.*]]1071; MDEP: bb1:1072; MDEP-NEXT: [[COND2:%.*]] = icmp sgt i64 [[V1]], 1001073; MDEP-NEXT: br i1 [[COND2]], label [[BB100:%.*]], label [[BB2:%.*]]1074; MDEP: bb2:1075; MDEP-NEXT: [[V2:%.*]] = add nsw i64 [[V1]], 11076; MDEP-NEXT: store i64 [[V2]], ptr [[P1]], align 81077; MDEP-NEXT: br label [[BB3:%.*]]1078; MDEP: bb3:1079; MDEP-NEXT: [[V3:%.*]] = phi i64 [ [[V3_PRE:%.*]], [[BB200]] ], [ [[V3_PRE1:%.*]], [[BB100]] ], [ [[V2]], [[BB2]] ]1080; MDEP-NEXT: store i64 [[V3]], ptr [[P2:%.*]], align 81081; MDEP-NEXT: ret void1082; MDEP: bb100:1083; MDEP-NEXT: [[COND3:%.*]] = call i1 @foo()1084; MDEP-NEXT: [[V3_PRE1]] = load i64, ptr [[P1]], align 81085; MDEP-NEXT: br i1 [[COND3]], label [[BB3]], label [[BB101:%.*]]1086; MDEP: bb101:1087; MDEP-NEXT: store i64 [[V3_PRE1]], ptr [[P3:%.*]], align 81088; MDEP-NEXT: ret void1089; MDEP: bb200:1090; MDEP-NEXT: [[COND4:%.*]] = call i1 @bar()1091; MDEP-NEXT: [[V3_PRE]] = load i64, ptr [[P1]], align 81092; MDEP-NEXT: br i1 [[COND4]], label [[BB3]], label [[BB201:%.*]]1093; MDEP: bb201:1094; MDEP-NEXT: store i64 [[V3_PRE]], ptr [[P4:%.*]], align 81095; MDEP-NEXT: ret void1096;1097; MSSA-LABEL: @test17(1098; MSSA-NEXT: entry:1099; MSSA-NEXT: [[V1:%.*]] = load i64, ptr [[P1:%.*]], align 81100; MSSA-NEXT: [[COND1:%.*]] = icmp sgt i64 [[V1]], 2001101; MSSA-NEXT: br i1 [[COND1]], label [[BB200:%.*]], label [[BB1:%.*]]1102; MSSA: bb1:1103; MSSA-NEXT: [[COND2:%.*]] = icmp sgt i64 [[V1]], 1001104; MSSA-NEXT: br i1 [[COND2]], label [[BB100:%.*]], label [[BB2:%.*]]1105; MSSA: bb2:1106; MSSA-NEXT: [[V2:%.*]] = add nsw i64 [[V1]], 11107; MSSA-NEXT: store i64 [[V2]], ptr [[P1]], align 81108; MSSA-NEXT: br label [[BB3:%.*]]1109; MSSA: bb3:1110; MSSA-NEXT: [[V3:%.*]] = load i64, ptr [[P1]], align 81111; MSSA-NEXT: store i64 [[V3]], ptr [[P2:%.*]], align 81112; MSSA-NEXT: ret void1113; MSSA: bb100:1114; MSSA-NEXT: [[COND3:%.*]] = call i1 @foo()1115; MSSA-NEXT: br i1 [[COND3]], label [[BB3]], label [[BB101:%.*]]1116; MSSA: bb101:1117; MSSA-NEXT: [[V4:%.*]] = load i64, ptr [[P1]], align 81118; MSSA-NEXT: store i64 [[V4]], ptr [[P3:%.*]], align 81119; MSSA-NEXT: ret void1120; MSSA: bb200:1121; MSSA-NEXT: [[COND4:%.*]] = call i1 @bar()1122; MSSA-NEXT: br i1 [[COND4]], label [[BB3]], label [[BB201:%.*]]1123; MSSA: bb201:1124; MSSA-NEXT: [[V5:%.*]] = load i64, ptr [[P1]], align 81125; MSSA-NEXT: store i64 [[V5]], ptr [[P4:%.*]], align 81126; MSSA-NEXT: ret void1127;1128{1129entry:1130 %v1 = load i64, ptr %p1, align 81131 %cond1 = icmp sgt i64 %v1, 2001132 br i1 %cond1, label %bb200, label %bb11133 1134bb1:1135 %cond2 = icmp sgt i64 %v1, 1001136 br i1 %cond2, label %bb100, label %bb21137 1138bb2:1139 %v2 = add nsw i64 %v1, 11140 store i64 %v2, ptr %p1, align 81141 br label %bb31142 1143bb3:1144 %v3 = load i64, ptr %p1, align 81145 store i64 %v3, ptr %p2, align 81146 ret void1147 1148bb100:1149 %cond3 = call i1 @foo()1150 br i1 %cond3, label %bb3, label %bb1011151 1152bb101:1153 %v4 = load i64, ptr %p1, align 81154 store i64 %v4, ptr %p3, align 81155 ret void1156 1157bb200:1158 %cond4 = call i1 @bar()1159 br i1 %cond4, label %bb3, label %bb2011160 1161bb201:1162 %v5 = load i64, ptr %p1, align 81163 store i64 %v5, ptr %p4, align 81164 ret void1165}1166 1167; The output value from %if.then block is %dec, not loaded %v1.1168; So ValuesPerBlock[%if.then] should not be replaced when the load instruction1169; is moved to %entry.1170define void @test18(i1 %cond, ptr %p1, ptr %p2) {1171; MDEP-LABEL: @test18(1172; MDEP-NEXT: entry:1173; MDEP-NEXT: [[V2_PRE:%.*]] = load i16, ptr [[P1:%.*]], align 21174; MDEP-NEXT: br i1 [[COND:%.*]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]1175; MDEP: if.then:1176; MDEP-NEXT: [[DEC:%.*]] = add i16 [[V2_PRE]], -11177; MDEP-NEXT: store i16 [[DEC]], ptr [[P1]], align 21178; MDEP-NEXT: br label [[IF_END]]1179; MDEP: if.end:1180; MDEP-NEXT: [[V2:%.*]] = phi i16 [ [[DEC]], [[IF_THEN]] ], [ [[V2_PRE]], [[ENTRY:%.*]] ]1181; MDEP-NEXT: store i16 [[V2]], ptr [[P2:%.*]], align 21182; MDEP-NEXT: ret void1183;1184; MSSA-LABEL: @test18(1185; MSSA-NEXT: entry:1186; MSSA-NEXT: br i1 [[COND:%.*]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]1187; MSSA: if.then:1188; MSSA-NEXT: [[V1:%.*]] = load i16, ptr [[P1:%.*]], align 21189; MSSA-NEXT: [[DEC:%.*]] = add i16 [[V1]], -11190; MSSA-NEXT: store i16 [[DEC]], ptr [[P1]], align 21191; MSSA-NEXT: br label [[IF_END]]1192; MSSA: if.end:1193; MSSA-NEXT: [[V2:%.*]] = load i16, ptr [[P1]], align 21194; MSSA-NEXT: store i16 [[V2]], ptr [[P2:%.*]], align 21195; MSSA-NEXT: ret void1196;1197entry:1198 br i1 %cond, label %if.end, label %if.then1199 1200if.then:1201 %v1 = load i16, ptr %p11202 %dec = add i16 %v1, -11203 store i16 %dec, ptr %p11204 br label %if.end1205 1206if.end:1207 %v2 = load i16, ptr %p11208 store i16 %v2, ptr %p21209 ret void1210}1211 1212; PRE of load instructions should not cross exception handling instructions.1213define void @test19(i1 %cond, ptr %p1, ptr %p2)1214; MDEP-LABEL: @test19(1215; MDEP-NEXT: entry:1216; MDEP-NEXT: br i1 [[COND:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]1217; MDEP: then:1218; MDEP-NEXT: [[V2:%.*]] = load i64, ptr [[P2:%.*]], align 81219; MDEP-NEXT: [[ADD:%.*]] = add i64 [[V2]], 11220; MDEP-NEXT: store i64 [[ADD]], ptr [[P1:%.*]], align 81221; MDEP-NEXT: br label [[END:%.*]]1222; MDEP: else:1223; MDEP-NEXT: invoke void @f()1224; MDEP-NEXT: to label [[ELSE_END_CRIT_EDGE:%.*]] unwind label [[LPAD:%.*]]1225; MDEP: else.end_crit_edge:1226; MDEP-NEXT: [[V1_PRE:%.*]] = load i64, ptr [[P1]], align 81227; MDEP-NEXT: br label [[END]]1228; MDEP: end:1229; MDEP-NEXT: [[V1:%.*]] = phi i64 [ [[V1_PRE]], [[ELSE_END_CRIT_EDGE]] ], [ [[ADD]], [[THEN]] ]1230; MDEP-NEXT: [[AND:%.*]] = and i64 [[V1]], 1001231; MDEP-NEXT: store i64 [[AND]], ptr [[P2]], align 81232; MDEP-NEXT: ret void1233; MDEP: lpad:1234; MDEP-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }1235; MDEP-NEXT: cleanup1236; MDEP-NEXT: [[V3:%.*]] = load i64, ptr [[P1]], align 81237; MDEP-NEXT: [[OR:%.*]] = or i64 [[V3]], 2001238; MDEP-NEXT: store i64 [[OR]], ptr [[P1]], align 81239; MDEP-NEXT: resume { ptr, i32 } [[LP]]1240;1241; MSSA-LABEL: @test19(1242; MSSA-NEXT: entry:1243; MSSA-NEXT: br i1 [[COND:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]1244; MSSA: then:1245; MSSA-NEXT: [[V2:%.*]] = load i64, ptr [[P2:%.*]], align 81246; MSSA-NEXT: [[ADD:%.*]] = add i64 [[V2]], 11247; MSSA-NEXT: store i64 [[ADD]], ptr [[P1:%.*]], align 81248; MSSA-NEXT: br label [[END:%.*]]1249; MSSA: else:1250; MSSA-NEXT: invoke void @f()1251; MSSA-NEXT: to label [[END]] unwind label [[LPAD:%.*]]1252; MSSA: end:1253; MSSA-NEXT: [[V1:%.*]] = load i64, ptr [[P1]], align 81254; MSSA-NEXT: [[AND:%.*]] = and i64 [[V1]], 1001255; MSSA-NEXT: store i64 [[AND]], ptr [[P2]], align 81256; MSSA-NEXT: ret void1257; MSSA: lpad:1258; MSSA-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }1259; MSSA-NEXT: cleanup1260; MSSA-NEXT: [[V3:%.*]] = load i64, ptr [[P1]], align 81261; MSSA-NEXT: [[OR:%.*]] = or i64 [[V3]], 2001262; MSSA-NEXT: store i64 [[OR]], ptr [[P1]], align 81263; MSSA-NEXT: resume { ptr, i32 } [[LP]]1264;1265 personality ptr @__CxxFrameHandler3 {1266entry:1267 br i1 %cond, label %then, label %else1268 1269then:1270 %v2 = load i64, ptr %p21271 %add = add i64 %v2, 11272 store i64 %add, ptr %p11273 br label %end1274 1275else:1276 invoke void @f()1277 to label %end unwind label %lpad1278 1279end:1280 %v1 = load i64, ptr %p11281 %and = and i64 %v1, 1001282 store i64 %and, ptr %p21283 ret void1284 1285lpad:1286 %lp = landingpad { ptr, i32 }1287 cleanup1288 %v3 = load i64, ptr %p11289 %or = or i64 %v3, 2001290 store i64 %or, ptr %p11291 resume { ptr, i32 } %lp1292}1293 1294; A predecessor BB has both successors to the same BB, for simplicity we don't1295; handle it, nothing should be changed.1296define void @test20(i1 %cond, i1 %cond2, ptr %p1, ptr %p2) {1297; CHECK-LABEL: @test20(1298; CHECK-NEXT: entry:1299; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]1300; CHECK: if.then:1301; CHECK-NEXT: [[V1:%.*]] = load i16, ptr [[P1:%.*]], align 21302; CHECK-NEXT: [[DEC:%.*]] = add i16 [[V1]], -11303; CHECK-NEXT: store i16 [[DEC]], ptr [[P1]], align 21304; CHECK-NEXT: br label [[IF_END:%.*]]1305; CHECK: if.else:1306; CHECK-NEXT: br i1 [[COND2:%.*]], label [[IF_END]], label [[IF_END]]1307; CHECK: if.end:1308; CHECK-NEXT: [[V2:%.*]] = load i16, ptr [[P1]], align 21309; CHECK-NEXT: store i16 [[V2]], ptr [[P2:%.*]], align 21310; CHECK-NEXT: ret void1311;1312entry:1313 br i1 %cond, label %if.then, label %if.else1314 1315if.then:1316 %v1 = load i16, ptr %p11317 %dec = add i16 %v1, -11318 store i16 %dec, ptr %p11319 br label %if.end1320 1321if.else:1322 br i1 %cond2, label %if.end, label %if.end1323 1324if.end:1325 %v2 = load i16, ptr %p11326 store i16 %v2, ptr %p21327 ret void1328}1329 1330; More edges from the same BB to LoadBB. Don't change anything.1331define void @test21(i1 %cond, i32 %code, ptr %p1, ptr %p2) {1332; CHECK-LABEL: @test21(1333; CHECK-NEXT: entry:1334; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]1335; CHECK: if.then:1336; CHECK-NEXT: [[V1:%.*]] = load i16, ptr [[P1:%.*]], align 21337; CHECK-NEXT: [[DEC:%.*]] = add i16 [[V1]], -11338; CHECK-NEXT: store i16 [[DEC]], ptr [[P1]], align 21339; CHECK-NEXT: br label [[IF_END:%.*]]1340; CHECK: if.else:1341; CHECK-NEXT: switch i32 [[CODE:%.*]], label [[IF_END]] [1342; CHECK-NEXT: i32 1, label [[IF_END]]1343; CHECK-NEXT: i32 2, label [[IF_END]]1344; CHECK-NEXT: i32 3, label [[IF_END]]1345; CHECK-NEXT: ]1346; CHECK: if.end:1347; CHECK-NEXT: [[V2:%.*]] = load i16, ptr [[P1]], align 21348; CHECK-NEXT: store i16 [[V2]], ptr [[P2:%.*]], align 21349; CHECK-NEXT: ret void1350;1351entry:1352 br i1 %cond, label %if.then, label %if.else1353 1354if.then:1355 %v1 = load i16, ptr %p11356 %dec = add i16 %v1, -11357 store i16 %dec, ptr %p11358 br label %if.end1359 1360if.else:1361 switch i32 %code, label %if.end [1362 i32 1, label %if.end1363 i32 2, label %if.end1364 i32 3, label %if.end1365 ]1366 1367if.end:1368 %v2 = load i16, ptr %p11369 store i16 %v2, ptr %p21370 ret void1371}1372 1373; Call to function @maybethrow may cause exception, so the load of %v3 can't1374; be hoisted to block %if.else.1375define void @test22(i1 %cond, ptr %p1, ptr %p2) {1376; MDEP-LABEL: @test22(1377; MDEP-NEXT: entry:1378; MDEP-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]1379; MDEP: if.then:1380; MDEP-NEXT: [[V1:%.*]] = load i64, ptr [[P1:%.*]], align 81381; MDEP-NEXT: [[DEC:%.*]] = add i64 [[V1]], -11382; MDEP-NEXT: store i64 [[DEC]], ptr [[P1]], align 81383; MDEP-NEXT: br label [[IF_END:%.*]]1384; MDEP: if.end:1385; MDEP-NEXT: [[V2:%.*]] = phi i64 [ [[V2_PRE:%.*]], [[IF_ELSE_IF_END_CRIT_EDGE:%.*]] ], [ [[DEC]], [[IF_THEN]] ]1386; MDEP-NEXT: store i64 [[V2]], ptr [[P2:%.*]], align 81387; MDEP-NEXT: ret void1388; MDEP: if.else:1389; MDEP-NEXT: [[COND2:%.*]] = call i1 @foo()1390; MDEP-NEXT: br i1 [[COND2]], label [[IF_ELSE_IF_END_CRIT_EDGE]], label [[EXIT:%.*]]1391; MDEP: if.else.if.end_crit_edge:1392; MDEP-NEXT: [[V2_PRE]] = load i64, ptr [[P1]], align 81393; MDEP-NEXT: br label [[IF_END]]1394; MDEP: exit:1395; MDEP-NEXT: [[_:%.*]] = call i1 @maybethrow()1396; MDEP-NEXT: [[V3:%.*]] = load i64, ptr [[P1]], align 81397; MDEP-NEXT: store i64 [[V3]], ptr [[P2]], align 81398; MDEP-NEXT: ret void1399;1400; MSSA-LABEL: @test22(1401; MSSA-NEXT: entry:1402; MSSA-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]1403; MSSA: if.then:1404; MSSA-NEXT: [[V1:%.*]] = load i64, ptr [[P1:%.*]], align 81405; MSSA-NEXT: [[DEC:%.*]] = add i64 [[V1]], -11406; MSSA-NEXT: store i64 [[DEC]], ptr [[P1]], align 81407; MSSA-NEXT: br label [[IF_END:%.*]]1408; MSSA: if.end:1409; MSSA-NEXT: [[V2:%.*]] = load i64, ptr [[P1]], align 81410; MSSA-NEXT: store i64 [[V2]], ptr [[P2:%.*]], align 81411; MSSA-NEXT: ret void1412; MSSA: if.else:1413; MSSA-NEXT: [[COND2:%.*]] = call i1 @foo()1414; MSSA-NEXT: br i1 [[COND2]], label [[IF_END]], label [[EXIT:%.*]]1415; MSSA: exit:1416; MSSA-NEXT: [[_:%.*]] = call i1 @maybethrow()1417; MSSA-NEXT: [[V3:%.*]] = load i64, ptr [[P1]], align 81418; MSSA-NEXT: store i64 [[V3]], ptr [[P2]], align 81419; MSSA-NEXT: ret void1420;1421entry:1422 br i1 %cond, label %if.then, label %if.else1423 1424if.then:1425 %v1 = load i64, ptr %p11426 %dec = add i64 %v1, -11427 store i64 %dec, ptr %p11428 br label %if.end1429 1430if.end:1431 %v2 = load i64, ptr %p11432 store i64 %v2, ptr %p21433 ret void1434 1435if.else:1436 %cond2 = call i1 @foo()1437 br i1 %cond2, label %if.end, label %exit1438 1439exit:1440 %_ = call i1 @maybethrow()1441 %v3 = load i64, ptr %p11442 store i64 %v3, ptr %p21443 ret void1444}1445 1446declare void @maybethrow() readnone1447@B = external global i64, align 81448 1449; When BB in ValuesPerBlock(BB, OldLoad) is not OldLoad->getParent(), it should1450; also be replaced by ValuesPerBlock(BB, NewLoad). So we'll not use the deleted1451; OldLoad in later PHI instruction.1452define void @test23(i1 %cond1, i1 %cond2) {1453; MDEP-LABEL: @test23(1454; MDEP-NEXT: entry:1455; MDEP-NEXT: [[G:%.*]] = alloca i64, align 81456; MDEP-NEXT: [[VAL1_PRE:%.*]] = load i64, ptr @B, align 81457; MDEP-NEXT: br i1 [[COND2:%.*]], label [[THEN:%.*]], label [[WRONG:%.*]]1458; MDEP: then:1459; MDEP-NEXT: br i1 [[COND1:%.*]], label [[STORE:%.*]], label [[EXIT:%.*]]1460; MDEP: store:1461; MDEP-NEXT: store i64 [[VAL1_PRE]], ptr @B, align 81462; MDEP-NEXT: br label [[WRONG]]1463; MDEP: wrong:1464; MDEP-NEXT: store i64 [[VAL1_PRE]], ptr [[G]], align 81465; MDEP-NEXT: ret void1466; MDEP: exit:1467; MDEP-NEXT: ret void1468;1469; MSSA-LABEL: @test23(1470; MSSA-NEXT: entry:1471; MSSA-NEXT: [[G:%.*]] = alloca i64, align 81472; MSSA-NEXT: br i1 [[COND2:%.*]], label [[THEN:%.*]], label [[WRONG:%.*]]1473; MSSA: then:1474; MSSA-NEXT: [[VAL2:%.*]] = load i64, ptr @B, align 81475; MSSA-NEXT: br i1 [[COND1:%.*]], label [[STORE:%.*]], label [[EXIT:%.*]]1476; MSSA: store:1477; MSSA-NEXT: store i64 [[VAL2]], ptr @B, align 81478; MSSA-NEXT: br label [[WRONG]]1479; MSSA: wrong:1480; MSSA-NEXT: [[VAL1:%.*]] = load i64, ptr @B, align 81481; MSSA-NEXT: store i64 [[VAL1]], ptr [[G]], align 81482; MSSA-NEXT: ret void1483; MSSA: exit:1484; MSSA-NEXT: ret void1485;1486entry:1487 %G = alloca i64, align 81488 br i1 %cond2, label %then, label %wrong1489 1490then:1491 %val2 = load i64, ptr @B, align 81492 br i1 %cond1, label %store, label %exit1493 1494store:1495 store i64 %val2, ptr @B, align 81496 br label %wrong1497 1498wrong:1499 %val1 = load i64, ptr @B, align 81500 store i64 %val1, ptr %G, align 81501 ret void1502 1503exit:1504 ret void1505}1506 1507; Allow the load to be made available on the edge (%entry, %if.end) as part of PRE,1508; but ensure `%identical.l` is not hoisted to its predecessor due to the local1509; dependency with the call.1510 1511define i32 @test24(ptr noalias %p, ptr noalias %q, i1 %c) {1512; MDEP-LABEL: @test24(1513; MDEP-NEXT: entry:1514; MDEP-NEXT: br i1 [[C:%.*]], label [[ENTRY_IF_END_CRIT_EDGE:%.*]], label [[IF_THEN:%.*]]1515; MDEP: entry.if.end_crit_edge:1516; MDEP-NEXT: [[VV_PRE:%.*]] = load i32, ptr [[X:%.*]], align 41517; MDEP-NEXT: br label [[IF_END:%.*]]1518; MDEP: if.then:1519; MDEP-NEXT: call void @opaque(ptr [[X]])1520; MDEP-NEXT: [[UU:%.*]] = load i32, ptr [[X]], align 41521; MDEP-NEXT: store i32 [[UU]], ptr [[R:%.*]], align 41522; MDEP-NEXT: br label [[IF_END]]1523; MDEP: if.end:1524; MDEP-NEXT: [[VV:%.*]] = phi i32 [ [[VV_PRE]], [[ENTRY_IF_END_CRIT_EDGE]] ], [ [[UU]], [[IF_THEN]] ]1525; MDEP-NEXT: ret i32 [[VV]]1526;1527; MSSA-LABEL: @test24(1528; MSSA-NEXT: entry:1529; MSSA-NEXT: br i1 [[C:%.*]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]1530; MSSA: if.then:1531; MSSA-NEXT: call void @opaque(ptr [[X:%.*]])1532; MSSA-NEXT: [[UU:%.*]] = load i32, ptr [[X]], align 41533; MSSA-NEXT: store i32 [[UU]], ptr [[R:%.*]], align 41534; MSSA-NEXT: br label [[IF_END]]1535; MSSA: if.end:1536; MSSA-NEXT: [[VV:%.*]] = load i32, ptr [[X]], align 41537; MSSA-NEXT: ret i32 [[VV]]1538;1539entry:1540 br i1 %c, label %if.end, label %if.then1541 1542if.then:1543 call void @opaque(ptr %p)1544 %identical.l = load i32, ptr %p, align 41545 store i32 %identical.l, ptr %q, align 41546 br label %if.end1547 1548if.end:1549 %l = load i32, ptr %p, align 41550 ret i32 %l1551}1552 1553declare void @opaque(ptr) nounwind willreturn1554