1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -gvn -gvn-max-block-speculations=1 -S | FileCheck -check-prefix=PRE %s 3; RUN: opt < %s -gvn -gvn-max-block-speculations=0 -S | FileCheck -check-prefix=CHECK %s 4 5define i32 @loadpre_opportunity(i32** %arg, i1 %arg1, i1 %arg2, i1 %arg3) { 6; PRE-LABEL: @loadpre_opportunity( 7; PRE-NEXT: bb: 8; PRE-NEXT: [[I:%.*]] = load i32*, i32** [[ARG:%.*]], align 8 9; PRE-NEXT: [[I6:%.*]] = call i32 @use(i32* [[I]]) 10; PRE-NEXT: br label [[BB11:%.*]] 11; PRE: bb7: 12; PRE-NEXT: [[I8:%.*]] = phi i32* [ [[I8_PRE:%.*]], [[BB17_BB7_CRIT_EDGE:%.*]] ], [ [[I81:%.*]], [[BB11]] ] 13; PRE-NEXT: [[I10:%.*]] = call i32 @use(i32* [[I8]]) 14; PRE-NEXT: br label [[BB11]] 15; PRE: bb11: 16; PRE-NEXT: [[I81]] = phi i32* [ [[I]], [[BB:%.*]] ], [ [[I8]], [[BB7:%.*]] ] 17; PRE-NEXT: [[I12:%.*]] = phi i32 [ [[I6]], [[BB]] ], [ [[I10]], [[BB7]] ] 18; PRE-NEXT: br i1 [[ARG1:%.*]], label [[BB7]], label [[BB13:%.*]] 19; PRE: bb13: 20; PRE-NEXT: call void @somecall() 21; PRE-NEXT: br i1 [[ARG2:%.*]], label [[BB14:%.*]], label [[BB17:%.*]] 22; PRE: bb14: 23; PRE-NEXT: br label [[BB15:%.*]] 24; PRE: bb15: 25; PRE-NEXT: br i1 [[ARG3:%.*]], label [[BB16:%.*]], label [[BB15]] 26; PRE: bb16: 27; PRE-NEXT: br label [[BB17]] 28; PRE: bb17: 29; PRE-NEXT: [[I18:%.*]] = call i1 @cond() 30; PRE-NEXT: br i1 [[I18]], label [[BB17_BB7_CRIT_EDGE]], label [[BB19:%.*]] 31; PRE: bb17.bb7_crit_edge: 32; PRE-NEXT: [[I8_PRE]] = load i32*, i32** [[ARG]], align 8 33; PRE-NEXT: br label [[BB7]] 34; PRE: bb19: 35; PRE-NEXT: ret i32 [[I12]] 36; 37; CHECK-LABEL: @loadpre_opportunity( 38; CHECK-NEXT: bb: 39; CHECK-NEXT: [[I:%.*]] = load i32*, i32** [[ARG:%.*]], align 8 40; CHECK-NEXT: [[I6:%.*]] = call i32 @use(i32* [[I]]) 41; CHECK-NEXT: br label [[BB11:%.*]] 42; CHECK: bb7: 43; CHECK-NEXT: [[I8:%.*]] = load i32*, i32** [[ARG]], align 8 44; CHECK-NEXT: [[I10:%.*]] = call i32 @use(i32* [[I8]]) 45; CHECK-NEXT: br label [[BB11]] 46; CHECK: bb11: 47; CHECK-NEXT: [[I12:%.*]] = phi i32 [ [[I6]], [[BB:%.*]] ], [ [[I10]], [[BB7:%.*]] ] 48; CHECK-NEXT: br i1 [[ARG1:%.*]], label [[BB7]], label [[BB13:%.*]] 49; CHECK: bb13: 50; CHECK-NEXT: call void @somecall() 51; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB14:%.*]], label [[BB17:%.*]] 52; CHECK: bb14: 53; CHECK-NEXT: br label [[BB15:%.*]] 54; CHECK: bb15: 55; CHECK-NEXT: br i1 [[ARG3:%.*]], label [[BB16:%.*]], label [[BB15]] 56; CHECK: bb16: 57; CHECK-NEXT: br label [[BB17]] 58; CHECK: bb17: 59; CHECK-NEXT: [[I18:%.*]] = call i1 @cond() 60; CHECK-NEXT: br i1 [[I18]], label [[BB7]], label [[BB19:%.*]] 61; CHECK: bb19: 62; CHECK-NEXT: ret i32 [[I12]] 63; 64bb: 65 %i = load i32*, i32** %arg, align 8 66 %i4 = getelementptr inbounds i32, i32* %i, i64 0 67 br label %bb5 68 69bb5: 70 %i6 = call i32 @use(i32* %i4) 71 br label %bb11 72 73bb7: 74 %i8 = load i32*, i32** %arg, align 8 75 %i9 = getelementptr inbounds i32, i32* %i8, i64 0 76 %i10 = call i32 @use(i32* %i9) 77 br label %bb11 78 79bb11: 80 %i12 = phi i32 [ %i6, %bb5 ], [ %i10, %bb7 ] 81 br i1 %arg1, label %bb7, label %bb13 82 83bb13: 84 call void @somecall() 85 br i1 %arg2, label %bb14, label %bb17 86 87bb14: 88 br label %bb15 89 90bb15: 91 br i1 %arg3, label %bb16, label %bb15 92 93bb16: 94 br label %bb17 95 96bb17: 97 %i18 = call i1 @cond() 98 br i1 %i18, label %bb7, label %bb19 99 100bb19: 101 ret i32 %i12 102} 103 104declare void @somecall() 105declare i32 @use(i32*) readnone 106declare i1 @cond() readnone 107