brintos

brintos / llvm-project-archived public Read only

0
0
Text · 53.0 KiB · afa1354 Raw
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