1; RUN: opt -licm -basic-aa -licm-n2-threshold=0 < %s -S | FileCheck %s 2; RUN: opt -licm -basic-aa -licm-n2-threshold=200 < %s -S | FileCheck %s --check-prefix=ALIAS-N2 3; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s 4; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=200 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2 5 6define void @test1(i1 %cond, i32* %ptr) { 7; CHECK-LABEL: @test1( 8; CHECK-LABEL: entry: 9; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 10; CHECK: %val = load i32, i32* %ptr 11; CHECK-LABEL: loop: 12 13; ALIAS-N2-LABEL: @test1( 14; ALIAS-N2-LABEL: entry: 15; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 16; ALIAS-N2: %val = load i32, i32* %ptr 17; ALIAS-N2-LABEL: loop: 18 19entry: 20 br label %loop 21 22loop: 23 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 24 call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 25 %val = load i32, i32* %ptr 26 %x.inc = add i32 %x, %val 27 br label %loop 28} 29 30;; despite the loop varying invariant.start, we should be 31;; able to hoist the load 32define void @test2(i1 %cond, i32* %ptr) { 33; CHECK-LABEL: @test2( 34; CHECK-LABEL: entry: 35; CHECK: %val = load i32, i32* %ptr 36; CHECK-LABEL: loop: 37; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %piv) 38 39; ALIAS-N2-LABEL: @test2( 40; ALIAS-N2-LABEL: entry: 41; ALIAS-N2: %val = load i32, i32* %ptr 42; ALIAS-N2-LABEL: loop: 43; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %piv) 44entry: 45 br label %loop 46 47loop: 48 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 49 %piv = getelementptr i32, i32* %ptr, i32 %x 50 call {}* @llvm.invariant.start.p0i32(i64 4, i32* %piv) 51 %val = load i32, i32* %ptr 52 %x.inc = add i32 %x, %val 53 br label %loop 54} 55 56define void @test3(i1 %cond, i32* %ptr) { 57; CHECK-LABEL: @test3( 58; CHECK-LABEL: entry: 59; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 60; CHECK: %val = load i32, i32* %ptr 61; CHECK-LABEL: loop: 62 63; ALIAS-N2-LABEL: @test3( 64; ALIAS-N2-LABEL: entry: 65; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 66; ALIAS-N2: %val = load i32, i32* %ptr 67; ALIAS-N2-LABEL: loop: 68entry: 69 br label %loop 70 71loop: 72 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 73 call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 74 %val = load i32, i32* %ptr 75 %p2 = getelementptr i32, i32* %ptr, i32 1 76 store volatile i32 0, i32* %p2 77 %x.inc = add i32 %x, %val 78 br label %loop 79} 80 81; can't hoist due to init in loop, only well defined if loop exits 82; on first iteration, but we don't bother checking for that currently 83define void @test4(i1 %cond, i32* %ptr) { 84; CHECK-LABEL: @test4( 85; CHECK-LABEL: entry: 86; CHECK-LABEL: loop: 87; CHECK: store i32 0, i32* %ptr 88; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 89; CHECK: %val = load i32, i32* %ptr 90 91; ALIAS-N2-LABEL: @test4( 92; ALIAS-N2-LABEL: entry: 93; ALIAS-N2-LABEL: loop: 94; ALIAS-N2: store i32 0, i32* %ptr 95; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 96; ALIAS-N2: %val = load i32, i32* %ptr 97entry: 98 br label %loop 99 100loop: 101 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 102 store i32 0, i32* %ptr 103 call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 104 %val = load i32, i32* %ptr 105 %x.inc = add i32 %x, %val 106 br label %loop 107} 108 109; don't try to reason about scopes 110define void @test5(i1 %cond, i32* %ptr) { 111; CHECK-LABEL: @test5( 112; CHECK-LABEL: entry: 113; CHECK-LABEL: loop: 114; CHECK: store i32 0, i32* %ptr 115; CHECK: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 116; CHECK: %val = load i32, i32* %ptr 117 118; ALIAS-N2-LABEL: @test5( 119; ALIAS-N2-LABEL: entry: 120; ALIAS-N2-LABEL: loop: 121; ALIAS-N2: store i32 0, i32* %ptr 122; ALIAS-N2: call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 123; ALIAS-N2: %val = load i32, i32* %ptr 124entry: 125 br label %loop 126 127loop: 128 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 129 store i32 0, i32* %ptr 130 %scope = call {}* @llvm.invariant.start.p0i32(i64 4, i32* %ptr) 131 %val = load i32, i32* %ptr 132 call void @llvm.invariant.end.p0i32({}* %scope, i64 4, i32* %ptr) 133 %x.inc = add i32 %x, %val 134 br label %loop 135} 136 137declare {}* @llvm.invariant.start.p0i32(i64, i32*) 138declare void @llvm.invariant.end.p0i32({}*, i64, i32*) 139