1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -enable-load-pre -enable-pre -passes=gvn -S < %s | FileCheck %s 3 4declare void @side_effect_0() nofree 5 6declare void @side_effect_1(i32 %x) nofree 7 8declare void @no_side_effect() readonly 9 10; TODO: We can PRE the load into the cold path, removing it from the hot path. 11define i32 @test_01(ptr %p) { 12; CHECK-LABEL: @test_01( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: br label [[LOOP:%.*]] 15; CHECK: loop: 16; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 17; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4 18; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], 100 19; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 20; CHECK: hot_path: 21; CHECK-NEXT: br label [[BACKEDGE]] 22; CHECK: cold_path: 23; CHECK-NEXT: call void @side_effect_0() #[[ATTR0:[0-9]+]] 24; CHECK-NEXT: br label [[BACKEDGE]] 25; CHECK: backedge: 26; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 27; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 28; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 29; CHECK: exit: 30; CHECK-NEXT: ret i32 [[X]] 31; 32entry: 33 br label %loop 34 35loop: 36 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 37 %x = load i32, ptr %p 38 %cond = icmp ult i32 %x, 100 39 br i1 %cond, label %hot_path, label %cold_path 40 41hot_path: 42 br label %backedge 43 44cold_path: 45 call void @side_effect_0() nofree 46 br label %backedge 47 48backedge: 49 %iv.next = add i32 %iv, %x 50 %loop.cond = icmp ult i32 %iv.next, 1000 51 br i1 %loop.cond, label %loop, label %exit 52 53exit: 54 ret i32 %x 55} 56 57; TODO: We can PRE the load into the cold path, removing it from the hot path. 58define i32 @test_02(ptr %p) { 59; CHECK-LABEL: @test_02( 60; CHECK-NEXT: entry: 61; CHECK-NEXT: br label [[LOOP:%.*]] 62; CHECK: loop: 63; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 64; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4 65; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], 100 66; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 67; CHECK: hot_path: 68; CHECK-NEXT: br label [[BACKEDGE]] 69; CHECK: cold_path: 70; CHECK-NEXT: call void @side_effect_1(i32 [[X]]) #[[ATTR0]] 71; CHECK-NEXT: br label [[BACKEDGE]] 72; CHECK: backedge: 73; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 74; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 75; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 76; CHECK: exit: 77; CHECK-NEXT: ret i32 [[X]] 78; 79entry: 80 br label %loop 81 82loop: 83 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 84 %x = load i32, ptr %p 85 %cond = icmp ult i32 %x, 100 86 br i1 %cond, label %hot_path, label %cold_path 87 88hot_path: 89 br label %backedge 90 91cold_path: 92 call void @side_effect_1(i32 %x) nofree 93 br label %backedge 94 95backedge: 96 %iv.next = add i32 %iv, %x 97 %loop.cond = icmp ult i32 %iv.next, 1000 98 br i1 %loop.cond, label %loop, label %exit 99 100exit: 101 ret i32 %x 102} 103 104define i32 @test_03(ptr %p) { 105; CHECK-LABEL: @test_03( 106; CHECK-NEXT: entry: 107; CHECK-NEXT: [[X_PRE:%.*]] = load i32, ptr [[P:%.*]], align 4 108; CHECK-NEXT: br label [[LOOP:%.*]] 109; CHECK: loop: 110; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 111; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X_PRE]], 100 112; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 113; CHECK: hot_path: 114; CHECK-NEXT: br label [[BACKEDGE]] 115; CHECK: cold_path: 116; CHECK-NEXT: call void @no_side_effect() 117; CHECK-NEXT: br label [[BACKEDGE]] 118; CHECK: backedge: 119; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X_PRE]] 120; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 121; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 122; CHECK: exit: 123; CHECK-NEXT: ret i32 [[X_PRE]] 124; 125entry: 126 br label %loop 127 128loop: 129 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 130 %x = load i32, ptr %p 131 %cond = icmp ult i32 %x, 100 132 br i1 %cond, label %hot_path, label %cold_path 133 134hot_path: 135 br label %backedge 136 137cold_path: 138 call void @no_side_effect() 139 br label %backedge 140 141backedge: 142 %iv.next = add i32 %iv, %x 143 %loop.cond = icmp ult i32 %iv.next, 1000 144 br i1 %loop.cond, label %loop, label %exit 145 146exit: 147 ret i32 %x 148} 149