Home | History | Annotate | Download | only in ARM
      1 ; RUN: llc < %s -mtriple=arm-apple-darwin -relocation-model=dynamic-no-pic -mcpu=cortex-a8 -asm-verbose=false | FileCheck %s
      2 
      3 declare void @bar(i32)
      4 declare void @car(i32)
      5 declare void @dar(i32)
      6 declare void @ear(i32)
      7 declare void @far(i32)
      8 declare i1 @qux()
      9 
     10 @GHJK = global i32 0
     11 
     12 declare i8* @choose(i8*, i8*)
     13 
     14 ; BranchFolding should tail-duplicate the indirect jump to avoid
     15 ; redundant branching.
     16 
     17 ; CHECK-LABEL: tail_duplicate_me:
     18 ; CHECK:      qux
     19 ; CHECK:      movw r{{[0-9]+}}, :lower16:_GHJK
     20 ; CHECK:      movt r{{[0-9]+}}, :upper16:_GHJK
     21 ; CHECK:      str r
     22 ; CHECK-NEXT: bx r
     23 ; CHECK:      qux
     24 ; CHECK:      movw r{{[0-9]+}}, :lower16:_GHJK
     25 ; CHECK:      movt r{{[0-9]+}}, :upper16:_GHJK
     26 ; CHECK:      str r
     27 ; CHECK-NEXT: bx r
     28 ; CHECK:      movw r{{[0-9]+}}, :lower16:_GHJK
     29 ; CHECK:      movt r{{[0-9]+}}, :upper16:_GHJK
     30 ; CHECK:      str r
     31 ; CHECK-NEXT: bx r
     32 
     33 define void @tail_duplicate_me() nounwind {
     34 entry:
     35   %a = call i1 @qux()
     36   %c = call i8* @choose(i8* blockaddress(@tail_duplicate_me, %return),
     37                         i8* blockaddress(@tail_duplicate_me, %altret))
     38   br i1 %a, label %A, label %next
     39 next:
     40   %b = call i1 @qux()
     41   br i1 %b, label %B, label %C
     42 
     43 A:
     44   call void @bar(i32 0)
     45   store i32 0, i32* @GHJK
     46   br label %M
     47 
     48 B:
     49   call void @car(i32 1)
     50   store i32 0, i32* @GHJK
     51   br label %M
     52 
     53 C:
     54   call void @dar(i32 2)
     55   store i32 0, i32* @GHJK
     56   br label %M
     57 
     58 M:
     59   indirectbr i8* %c, [label %return, label %altret]
     60 
     61 return:
     62   call void @ear(i32 1000)
     63   ret void
     64 altret:
     65   call void @far(i32 1001)
     66   ret void
     67 }
     68 
     69 ; Use alternating abort functions so that the blocks we wish to merge are not
     70 ; layout successors during branch folding.
     71 
     72 ; CHECK-LABEL: merge_alternating_aborts:
     73 ; CHECK-NOT: _abort
     74 ; CHECK-NOT: _alt_abort
     75 ; CHECK: bxne lr
     76 ; CHECK-NOT: _abort
     77 ; CHECK-NOT: _alt_abort
     78 ; CHECK: LBB{{.*}}:
     79 ; CHECK: mov lr, pc
     80 ; CHECK: b _alt_abort
     81 ; CHECK-NOT: _abort
     82 ; CHECK-NOT: _alt_abort
     83 ; CHECK: LBB{{.*}}:
     84 ; CHECK: mov lr, pc
     85 ; CHECK: b _abort
     86 ; CHECK-NOT: _abort
     87 ; CHECK-NOT: _alt_abort
     88 
     89 declare void @abort()
     90 declare void @alt_abort()
     91 
     92 define void @merge_alternating_aborts() {
     93 entry:
     94   %c1 = call i1 @qux()
     95   br i1 %c1, label %cont1, label %abort1
     96 abort1:
     97   call void @abort()
     98   unreachable
     99 cont1:
    100   %c2 = call i1 @qux()
    101   br i1 %c2, label %cont2, label %abort2
    102 abort2:
    103   call void @alt_abort()
    104   unreachable
    105 cont2:
    106   %c3 = call i1 @qux()
    107   br i1 %c3, label %cont3, label %abort3
    108 abort3:
    109   call void @abort()
    110   unreachable
    111 cont3:
    112   %c4 = call i1 @qux()
    113   br i1 %c4, label %cont4, label %abort4
    114 abort4:
    115   call void @alt_abort()
    116   unreachable
    117 cont4:
    118   ret void
    119 }
    120