1; RUN: opt -S -basic-aa -licm -licm-n2-threshold=0 -enable-mssa-loop-dependency=false %s -enable-new-pm=0 | FileCheck %s 2; RUN: opt -S -basic-aa -licm -licm-n2-threshold=0 -enable-mssa-loop-dependency=true -verify-memoryssa %s -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2 3; RUN: opt -licm -basic-aa -licm-n2-threshold=200 < %s -S -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2 4 5; 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 6; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2 7; 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 8 9declare i32 @foo() readonly argmemonly nounwind 10declare i32 @foo2() readonly nounwind 11declare i32 @bar(i32* %loc2) readonly argmemonly nounwind 12 13define void @test(i32* %loc) { 14; CHECK-LABEL: @test 15; CHECK: @foo 16; CHECK-LABEL: loop: 17; ALIAS-N2-LABEL: @test 18; ALIAS-N2: @foo 19; ALIAS-N2-LABEL: loop: 20 br label %loop 21 22loop: 23 %res = call i32 @foo() 24 store i32 %res, i32* %loc 25 br label %loop 26} 27 28; Negative test: show argmemonly is required 29define void @test_neg(i32* %loc) { 30; CHECK-LABEL: @test_neg 31; CHECK-LABEL: loop: 32; CHECK: @foo 33; ALIAS-N2-LABEL: @test_neg 34; ALIAS-N2-LABEL: loop: 35; ALIAS-N2: @foo 36 br label %loop 37 38loop: 39 %res = call i32 @foo2() 40 store i32 %res, i32* %loc 41 br label %loop 42} 43 44define void @test2(i32* noalias %loc, i32* noalias %loc2) { 45; CHECK-LABEL: @test2 46; CHECK: @bar 47; CHECK-LABEL: loop: 48; ALIAS-N2-LABEL: @test2 49; ALIAS-N2: @bar 50; ALIAS-N2-LABEL: loop: 51 br label %loop 52 53loop: 54 %res = call i32 @bar(i32* %loc2) 55 store i32 %res, i32* %loc 56 br label %loop 57} 58 59; Negative test: %might clobber gep 60define void @test3(i32* %loc) { 61; CHECK-LABEL: @test3 62; CHECK-LABEL: loop: 63; CHECK: @bar 64; ALIAS-N2-LABEL: @test3 65; ALIAS-N2-LABEL: loop: 66; ALIAS-N2: @bar 67 br label %loop 68 69loop: 70 %res = call i32 @bar(i32* %loc) 71 %gep = getelementptr i32, i32 *%loc, i64 1000000 72 store i32 %res, i32* %gep 73 br label %loop 74} 75 76 77; Negative test: %loc might alias %loc2 78define void @test4(i32* %loc, i32* %loc2) { 79; CHECK-LABEL: @test4 80; CHECK-LABEL: loop: 81; CHECK: @bar 82; ALIAS-N2-LABEL: @test4 83; ALIAS-N2-LABEL: loop: 84; ALIAS-N2: @bar 85 br label %loop 86 87loop: 88 %res = call i32 @bar(i32* %loc2) 89 store i32 %res, i32* %loc 90 br label %loop 91} 92 93declare i32 @foo_new(i32*) readonly 94; With the default AST mechanism used by LICM for alias analysis, 95; we clump foo_new with bar. 96; With the N2 Alias analysis diagnostic tool, we are able to hoist the 97; argmemonly bar call out of the loop. 98; Using MemorySSA we can also hoist bar. 99 100define void @test5(i32* %loc2, i32* noalias %loc) { 101; ALIAS-N2-LABEL: @test5 102; ALIAS-N2: @bar 103; ALIAS-N2-LABEL: loop: 104 105; CHECK-LABEL: @test5 106; CHECK-LABEL: loop: 107; CHECK: @bar 108 br label %loop 109 110loop: 111 %res1 = call i32 @bar(i32* %loc2) 112 %res = call i32 @foo_new(i32* %loc2) 113 store volatile i32 %res1, i32* %loc 114 br label %loop 115} 116 117 118; memcpy doesn't write to it's source argument, so loads to that location 119; can still be hoisted 120define void @test6(i32* noalias %loc, i32* noalias %loc2) { 121; CHECK-LABEL: @test6 122; CHECK: %val = load i32, i32* %loc2 123; CHECK-LABEL: loop: 124; CHECK: @llvm.memcpy 125; ALIAS-N2-LABEL: @test6 126; ALIAS-N2: %val = load i32, i32* %loc2 127; ALIAS-N2-LABEL: loop: 128; ALIAS-N2: @llvm.memcpy 129 br label %loop 130 131loop: 132 %val = load i32, i32* %loc2 133 store i32 %val, i32* %loc 134 %dest = bitcast i32* %loc to i8* 135 %src = bitcast i32* %loc2 to i8* 136 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest, i8* %src, i64 8, i1 false) 137 br label %loop 138} 139 140define void @test7(i32* noalias %loc, i32* noalias %loc2) { 141; CHECK-LABEL: @test7 142; CHECK: %val = load i32, i32* %loc2 143; CHECK-LABEL: loop: 144; CHECK: @custom_memcpy 145; ALIAS-N2-LABEL: @test7 146; ALIAS-N2: %val = load i32, i32* %loc2 147; ALIAS-N2-LABEL: loop: 148; ALIAS-N2: @custom_memcpy 149 br label %loop 150 151loop: 152 %val = load i32, i32* %loc2 153 store i32 %val, i32* %loc 154 %dest = bitcast i32* %loc to i8* 155 %src = bitcast i32* %loc2 to i8* 156 call void @custom_memcpy(i8* %dest, i8* %src) 157 br label %loop 158} 159 160declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) 161declare void @custom_memcpy(i8* nocapture writeonly, i8* nocapture readonly) argmemonly nounwind 162