Home | History | Annotate | Download | only in GVN
      1 ; Test if the !invariant.load metadata is maintained by GVN.
      2 ; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
      3 
      4 define i32 @test1(i32* nocapture %p, i8* nocapture %q) {
      5 ; CHECK-LABEL: test1
      6 ; CHECK: %x = load i32, i32* %p, align 4, !invariant.load !0
      7 ; CHECK-NOT: %y = load
      8 entry:
      9   %x = load i32, i32* %p, align 4, !invariant.load !0
     10   %conv = trunc i32 %x to i8
     11   store i8 %conv, i8* %q, align 1
     12   %y = load i32, i32* %p, align 4, !invariant.load !0
     13   %add = add i32 %y, 1
     14   ret i32 %add
     15 }
     16 
     17 define i32 @test2(i32* nocapture %p, i8* nocapture %q) {
     18 ; CHECK-LABEL: test2
     19 ; CHECK-NOT: !invariant.load
     20 ; CHECK-NOT: %y = load
     21 entry:
     22   %x = load i32, i32* %p, align 4
     23   %conv = trunc i32 %x to i8
     24   store i8 %conv, i8* %q, align 1
     25   %y = load i32, i32* %p, align 4, !invariant.load !0
     26   %add = add i32 %y, 1
     27   ret i32 %add
     28 }
     29 
     30 ; With the invariant.load metadata, what would otherwise
     31 ; be a case for PRE becomes a full redundancy.
     32 define i32 @test3(i1 %cnd, i32* %p, i32* %q) {
     33 ; CHECK-LABEL: test3
     34 ; CHECK-NOT: load
     35 entry:
     36   %v1 = load i32, i32* %p
     37   br i1 %cnd, label %bb1, label %bb2
     38 
     39 bb1:
     40   store i32 5, i32* %q
     41   br label %bb2
     42 
     43 bb2:
     44   %v2 = load i32, i32* %p, !invariant.load !0
     45   %res = sub i32 %v1, %v2
     46   ret i32 %res
     47 }
     48 
     49 ; This test is here to document a case which doesn't optimize
     50 ; as well as it could.  
     51 define i32 @test4(i1 %cnd, i32* %p, i32* %q) {
     52 ; CHECK-LABEL: test4
     53 ; %v2 is redundant, but GVN currently doesn't catch that
     54 entry:
     55   %v1 = load i32, i32* %p, !invariant.load !0
     56   br i1 %cnd, label %bb1, label %bb2
     57 
     58 bb1:
     59   store i32 5, i32* %q
     60   br label %bb2
     61 
     62 bb2:
     63   %v2 = load i32, i32* %p
     64   %res = sub i32 %v1, %v2
     65   ret i32 %res
     66 }
     67 
     68 ; Checks that we return the mustalias store as a def
     69 ; so that it contributes to value forwarding.  Note
     70 ; that we could and should remove the store too.
     71 define i32 @test5(i1 %cnd, i32* %p) {
     72 ; CHECK-LABEL: test5
     73 ; CHECK-LABEL: entry:
     74 ; CHECK-NEXT: store i32 5, i32* %p
     75 ; CHECK-NEXT: ret i32 5
     76 entry:
     77   %v1 = load i32, i32* %p, !invariant.load !0
     78   store i32 5, i32* %p ;; must alias store, want to exploit
     79   %v2 = load i32, i32* %p, !invariant.load !0
     80   ret i32 %v2
     81 }
     82 
     83 
     84 declare void @foo()
     85 
     86 ; Clobbering (mayalias) stores, even in function calls, can be ignored
     87 define i32 @test6(i1 %cnd, i32* %p) {
     88 ; CHECK-LABEL: test6
     89 ; CHECK-LABEL: entry:
     90 ; CHECK-NEXT: @foo
     91 ; CHECK-NEXT: ret i32 0
     92 entry:
     93   %v1 = load i32, i32* %p, !invariant.load !0
     94   call void @foo()
     95   %v2 = load i32, i32* %p, !invariant.load !0
     96   %res = sub i32 %v1, %v2
     97   ret i32 %res
     98 }
     99 
    100 declare noalias i32* @bar(...) 
    101 
    102 ; Same as previous, but a function with a noalias result (since they're handled
    103 ; differently in MDA)
    104 define i32 @test7(i1 %cnd, i32* %p) {
    105 ; CHECK-LABEL: test7
    106 ; CHECK-LABEL: entry:
    107 ; CHECK-NEXT: @bar
    108 ; CHECK-NEXT: ret i32 0
    109 entry:
    110   %v1 = load i32, i32* %p, !invariant.load !0
    111   call i32* (...) @bar(i32* %p)
    112   %v2 = load i32, i32* %p, !invariant.load !0
    113   %res = sub i32 %v1, %v2
    114   ret i32 %res
    115 }
    116 
    117 define i32 @test8(i1 %cnd, i32* %p) {
    118 ; CHECK-LABEL: test8
    119 ; CHECK: @bar
    120 ; CHECK: load i32, i32* %p2, !invariant.load
    121 ; CHECK: br label %merge
    122 entry:
    123   %v1 = load i32, i32* %p, !invariant.load !0
    124   br i1 %cnd, label %taken, label %merge
    125 taken:
    126   %p2 = call i32* (...) @bar(i32* %p)
    127   br label %merge
    128 merge:
    129   %p3 = phi i32* [%p, %entry], [%p2, %taken]
    130   %v2 = load i32, i32* %p3, !invariant.load !0
    131   %res = sub i32 %v1, %v2
    132   ret i32 %res
    133 }
    134 
    135 !0 = !{ }
    136 
    137