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 10define internal i32 @testPhi1(i32 %arg) { 11entry: 12 %cmp1 = icmp sgt i32 %arg, 0 13 br i1 %cmp1, label %next, label %target 14next: 15 br label %target 16target: 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 32define internal i32 @testPhi2(i32 %arg) { 33entry: 34 %cmp1 = icmp sgt i32 %arg, 0 35 br i1 %cmp1, label %next, label %target 36next: 37 br label %target 38target: 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. 52define internal i32 @testPhi3(i32 %arg) { 53entry: 54 br label %body 55body: 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 65exit: 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). 107define internal <4 x i32> @test_split_undef_int_vec(<4 x i32> %arg, i32 %cond) { 108entry: 109 %cmp = icmp eq i32 %cond, 0 110 br i1 %cmp, label %eq, label %exit 111eq: 112 br label %exit 113exit: 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). 121define internal <4 x float> @test_split_undef_float_vec(<4 x float> %arg, i32 %cond) { 122entry: 123 %cmp = icmp eq i32 %cond, 0 124 br i1 %cmp, label %eq, label %exit 125eq: 126 br label %exit 127exit: 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). 135define internal i32 @test_split_undef_int_scalar(i32 %arg, i32 %cond) { 136entry: 137 %cmp = icmp eq i32 %cond, 0 138 br i1 %cmp, label %eq, label %exit 139eq: 140 br label %exit 141exit: 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). 149define internal float @test_split_undef_float_scalar(float %arg, i32 %cond) { 150entry: 151 %cmp = icmp eq i32 %cond, 0 152 br i1 %cmp, label %eq, label %exit 153eq: 154 br label %exit 155exit: 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