Home | History | Annotate | Download | only in llvm2ice_tests
      1 ; This tests some of the subtleties of Phi lowering.  In particular,
      2 ; it tests that it does the right thing when it tries to enable
      3 ; compare/branch fusing.
      4 
      5 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 --phi-edge-split=0 \
      6 ; RUN:   | FileCheck %s
      7 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 --phi-edge-split=1 \
      8 ; RUN:   | FileCheck --check-prefix=SPLIT %s
      9 
     10 define internal i32 @testPhi1(i32 %arg) {
     11 entry:
     12   %cmp1 = icmp sgt i32 %arg, 0
     13   br i1 %cmp1, label %next, label %target
     14 next:
     15   br label %target
     16 target:
     17   %merge = phi i1 [ %cmp1, %entry ], [ false, %next ]
     18   %result = zext i1 %merge to i32
     19   ret i32 %result
     20 }
     21 ; Test that compare/branch fusing does not happen, and Phi lowering is
     22 ; put in the right place.
     23 ; CHECK-LABEL: testPhi1
     24 ; CHECK: cmp {{.*}},0x0
     25 ; CHECK: setg
     26 ; CHECK: mov [[PHI:.*]],
     27 ; CHECK: cmp {{.*}},0x0
     28 ; CHECK: je
     29 ; CHECK: mov [[PHI]],0x0
     30 ; CHECK: movzx {{.*}},[[PHI]]
     31 
     32 define internal i32 @testPhi2(i32 %arg) {
     33 entry:
     34   %cmp1 = icmp sgt i32 %arg, 0
     35   br i1 %cmp1, label %next, label %target
     36 next:
     37   br label %target
     38 target:
     39   %merge = phi i32 [ 12345, %entry ], [ 54321, %next ]
     40   ret i32 %merge
     41 }
     42 ; Test that compare/branch fusing and Phi lowering happens as expected.
     43 ; CHECK-LABEL: testPhi2
     44 ; CHECK: mov {{.*}},0x3039
     45 ; CHECK: cmp {{.*}},0x0
     46 ; CHECK-NEXT: jle
     47 ; CHECK: mov [[PHI:.*]],0xd431
     48 ; CHECK: mov {{.*}},[[PHI]]
     49 
     50 ; Test that address mode inference doesn't extend past
     51 ; multi-definition, non-SSA Phi temporaries.
     52 define internal i32 @testPhi3(i32 %arg) {
     53 entry:
     54   br label %body
     55 body:
     56   %merge = phi i32 [ %arg, %entry ], [ %elt, %body ]
     57   %interior = add i32 %merge, 1000
     58   ; Trick to make a basic block local copy of interior for
     59   ; addressing mode optimization.
     60   %interior__4 = add i32 %interior, 0
     61   %__4 = inttoptr i32 %interior__4 to i32*
     62   %elt = load i32, i32* %__4, align 1
     63   %cmp = icmp eq i32 %elt, 0
     64   br i1 %cmp, label %exit, label %body
     65 exit:
     66   ; Same trick (making a basic block local copy).
     67   %interior__6 = add i32 %interior, 0
     68   %__6 = inttoptr i32 %interior__6 to i32*
     69   store i32 %arg, i32* %__6, align 1
     70   ret i32 %arg
     71 }
     72 ; I can't figure out how to reliably test this for correctness, so I
     73 ; will just include patterns for the entire current O2 sequence.  This
     74 ; may need to be changed when meaningful optimizations are added.
     75 ; The key is to avoid the "bad" pattern like this:
     76 ;
     77 ; testPhi3:
     78 ; .LtestPhi3$entry:
     79 ;         mov     eax, DWORD PTR [esp+4]
     80 ;         mov     ecx, eax
     81 ; .LtestPhi3$body:
     82 ;         mov     ecx, DWORD PTR [ecx+1000]
     83 ;         cmp     ecx, 0
     84 ;         jne     .LtestPhi3$body
     85 ; .LtestPhi3$exit:
     86 ;         mov     DWORD PTR [ecx+1000], eax
     87 ;         ret
     88 ;
     89 ; This is bad because the final store address is supposed to be the
     90 ; same as the load address in the loop, but it has clearly been
     91 ; over-optimized into a null pointer dereference.
     92 
     93 ; CHECK-LABEL: testPhi3
     94 ; CHECK: push [[EBX:.*]]
     95 ; CHECK: mov [[EAX:.*]],DWORD PTR [esp
     96 ; CHECK: mov [[ECX:.*]],[[EAX]]
     97 ;;; start of loop body
     98 ; CHECK: mov [[EDX:.*]],[[ECX]]
     99 ; CHECK: mov {{.*}},DWORD PTR [{{.*}}+0x3e8]
    100 ; CHECK: cmp {{.*}},0x0
    101 ; CHECK: jne
    102 ;;; start of epilog
    103 ; CHECK: mov DWORD PTR {{.}}[[EDX]]+0x3e8],
    104 ; CHECK: pop [[EBX]]
    105 
    106 ; Test of "advanced phi lowering" with undef phi arg (integer vector).
    107 define internal <4 x i32> @test_split_undef_int_vec(<4 x i32> %arg, i32 %cond) {
    108 entry:
    109   %cmp = icmp eq i32 %cond, 0
    110   br i1 %cmp, label %eq, label %exit
    111 eq:
    112   br label %exit
    113 exit:
    114   %merge = phi <4 x i32> [ %arg, %entry ], [ undef, %eq ]
    115   ret <4 x i32> %merge
    116 }
    117 ; SPLIT-LABEL: test_split_undef_int_vec
    118 ; SPLIT: pxor
    119 
    120 ; Test of "advanced phi lowering" with undef phi arg (float vector).
    121 define internal <4 x float> @test_split_undef_float_vec(<4 x float> %arg, i32 %cond) {
    122 entry:
    123   %cmp = icmp eq i32 %cond, 0
    124   br i1 %cmp, label %eq, label %exit
    125 eq:
    126   br label %exit
    127 exit:
    128   %merge = phi <4 x float> [ %arg, %entry ], [ undef, %eq ]
    129   ret <4 x float> %merge
    130 }
    131 ; SPLIT-LABEL: test_split_undef_float_vec
    132 ; SPLIT: pxor
    133 
    134 ; Test of "advanced phi lowering" with undef phi arg (integer scalar).
    135 define internal i32 @test_split_undef_int_scalar(i32 %arg, i32 %cond) {
    136 entry:
    137   %cmp = icmp eq i32 %cond, 0
    138   br i1 %cmp, label %eq, label %exit
    139 eq:
    140   br label %exit
    141 exit:
    142   %merge = phi i32 [ %arg, %entry ], [ undef, %eq ]
    143   ret i32 %merge
    144 }
    145 ; SPLIT-LABEL: test_split_undef_int_scalar
    146 ; SPLIT: mov {{.*}},0x0
    147 
    148 ; Test of "advanced phi lowering" with undef phi arg (float scalar).
    149 define internal float @test_split_undef_float_scalar(float %arg, i32 %cond) {
    150 entry:
    151   %cmp = icmp eq i32 %cond, 0
    152   br i1 %cmp, label %eq, label %exit
    153 eq:
    154   br label %exit
    155 exit:
    156   %merge = phi float [ %arg, %entry ], [ undef, %eq ]
    157   ret float %merge
    158 }
    159 ; SPLIT-LABEL: test_split_undef_float_scalar
    160 ; SPLIT: movss {{.*}},DWORD PTR
    161