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