Home | History | Annotate | Download | only in Sink
      1 ; RUN: opt < %s -basicaa -sink -S | FileCheck %s
      2 
      3 declare i32 @f_load_global() nounwind readonly
      4 declare i32 @f_load_arg(i32*) nounwind readonly argmemonly
      5 declare void @f_store_global(i32) nounwind
      6 declare void @f_store_arg(i32*) nounwind argmemonly
      7 declare void @f_readonly_arg(i32* readonly, i32*) nounwind argmemonly
      8 declare i32 @f_readnone(i32) nounwind readnone
      9 
     10 @A = external global i32
     11 @B = external global i32
     12 
     13 ; Sink readonly call if no stores are in the way.
     14 ;
     15 ; CHECK-LABEL: @test_sink_no_stores(
     16 ; CHECK: true:
     17 ; CHECK-NEXT: %l = call i32 @f_load_global
     18 ; CHECK-NEXT: ret i32 %l
     19 define i32 @test_sink_no_stores(i1 %z) {
     20   %l = call i32 @f_load_global()
     21   br i1 %z, label %true, label %false
     22 true:
     23   ret i32 %l
     24 false:
     25   ret i32 0
     26 }
     27 
     28 ; CHECK-LABEL: @test_sink_argmem_store(
     29 ; CHECK: true:
     30 ; CHECK-NEXT: %l = call i32 @f_load_arg
     31 ; CHECK-NEXT: ret i32 %l
     32 define i32 @test_sink_argmem_store(i1 %z) {
     33   %l = call i32 @f_load_arg(i32* @A)
     34   store i32 0, i32* @B
     35   br i1 %z, label %true, label %false
     36 true:
     37   ret i32 %l
     38 false:
     39   ret i32 0
     40 }
     41 
     42 ; CHECK-LABEL: @test_sink_argmem_call(
     43 ; CHECK: true:
     44 ; CHECK-NEXT: %l = call i32 @f_load_arg
     45 ; CHECK-NEXT: ret i32 %l
     46 define i32 @test_sink_argmem_call(i1 %z) {
     47   %l = call i32 @f_load_arg(i32* @A)
     48   call void @f_store_arg(i32* @B)
     49   br i1 %z, label %true, label %false
     50 true:
     51   ret i32 %l
     52 false:
     53   ret i32 0
     54 }
     55 
     56 ; CHECK-LABEL: @test_sink_argmem_multiple(
     57 ; CHECK: true:
     58 ; CHECK-NEXT: %l = call i32 @f_load_arg
     59 ; CHECK-NEXT: ret i32 %l
     60 define i32 @test_sink_argmem_multiple(i1 %z) {
     61   %l = call i32 @f_load_arg(i32* @A)
     62   call void @f_readonly_arg(i32* @A, i32* @B)
     63   br i1 %z, label %true, label %false
     64 true:
     65   ret i32 %l
     66 false:
     67   ret i32 0
     68 }
     69 
     70 ; But don't sink if there is a store.
     71 ;
     72 ; CHECK-LABEL: @test_nosink_store(
     73 ; CHECK: call i32 @f_load_global
     74 ; CHECK-NEXT: store i32
     75 define i32 @test_nosink_store(i1 %z) {
     76   %l = call i32 @f_load_global()
     77   store i32 0, i32* @A
     78   br i1 %z, label %true, label %false
     79 true:
     80   ret i32 %l
     81 false:
     82   ret i32 0
     83 }
     84 
     85 ; CHECK-LABEL: @test_nosink_call(
     86 ; CHECK: call i32 @f_load_global
     87 ; CHECK-NEXT: call void @f_store_global
     88 define i32 @test_nosink_call(i1 %z) {
     89   %l = call i32 @f_load_global()
     90   call void @f_store_global(i32 0)
     91   br i1 %z, label %true, label %false
     92 true:
     93   ret i32 %l
     94 false:
     95   ret i32 0
     96 }
     97 
     98 ; readnone calls are sunk across stores.
     99 ;
    100 ; CHECK-LABEL: @test_sink_readnone(
    101 ; CHECK: true:
    102 ; CHECK-NEXT: %l = call i32 @f_readnone(
    103 ; CHECK-NEXT: ret i32 %l
    104 define i32 @test_sink_readnone(i1 %z) {
    105   %l = call i32 @f_readnone(i32 0)
    106   store i32 0, i32* @A
    107   br i1 %z, label %true, label %false
    108 true:
    109   ret i32 %l
    110 false:
    111   ret i32 0
    112 }
    113