|  | ; Tests the branch optimizations under O2 (against a lack of | 
|  | ; optimizations under Om1). | 
|  |  | 
|  | ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ | 
|  | ; RUN:   --target x8632 -i %s --args -O2 -allow-externally-defined-symbols \ | 
|  | ; RUN:   | %if --need=target_X8632 --command FileCheck --check-prefix=O2 %s | 
|  |  | 
|  | ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ | 
|  | ; RUN:   --target x8632 -i %s --args -Om1 -allow-externally-defined-symbols \ | 
|  | ; RUN:   | %if --need=target_X8632 --command FileCheck --check-prefix=OM1 %s | 
|  |  | 
|  | ; RUN: %if --need=target_ARM32_dump \ | 
|  | ; RUN:   --command %p2i --filetype=obj \ | 
|  | ; RUN:   --disassemble --target arm32 -i %s --args -O2 \ | 
|  | ; RUN:   -allow-externally-defined-symbols \ | 
|  | ; RUN:   | %if --need=target_ARM32_dump \ | 
|  | ; RUN:   --command FileCheck --check-prefix ARM32O2 %s | 
|  |  | 
|  | ; RUN: %if --need=target_ARM32 \ | 
|  | ; RUN:   --command %p2i --filetype=obj \ | 
|  | ; RUN:   --disassemble --target arm32 -i %s --args -Om1 \ | 
|  | ; RUN:   -allow-externally-defined-symbols \ | 
|  | ; RUN:   | %if --need=target_ARM32 \ | 
|  | ; RUN:   --command FileCheck \ | 
|  | ; RUN:   --check-prefix ARM32OM1 %s | 
|  |  | 
|  | ; RUN: %if --need=target_MIPS32 --need=allow_dump \ | 
|  | ; RUN:   --command %p2i --filetype=asm --assemble \ | 
|  | ; RUN:   --disassemble --target mips32 -i %s --args -O2 \ | 
|  | ; RUN:   -allow-externally-defined-symbols \ | 
|  | ; RUN:   | %if --need=target_MIPS32 --need=allow_dump \ | 
|  | ; RUN:   --command FileCheck --check-prefix MIPS32O2 %s | 
|  |  | 
|  | ; RUN: %if --need=target_MIPS32 --need=allow_dump \ | 
|  | ; RUN:   --command %p2i --filetype=asm --assemble \ | 
|  | ; RUN:   --disassemble --target mips32 -i %s --args -Om1 \ | 
|  | ; RUN:   -allow-externally-defined-symbols \ | 
|  | ; RUN:   | %if --need=target_MIPS32 --need=allow_dump \ | 
|  | ; RUN:   --command FileCheck \ | 
|  | ; RUN:   --check-prefix MIPS32OM1 %s | 
|  |  | 
|  | declare void @dummy() | 
|  |  | 
|  | ; An unconditional branch to the next block should be removed. | 
|  | define internal void @testUncondToNextBlock() { | 
|  | entry: | 
|  | call void @dummy() | 
|  | br label %next | 
|  | next: | 
|  | call void @dummy() | 
|  | ret void | 
|  | } | 
|  | ; O2-LABEL: testUncondToNextBlock | 
|  | ; O2: call | 
|  | ; There will be nops for bundle align to end (for NaCl), but there should | 
|  | ; not be a branch. | 
|  | ; O2-NOT: j | 
|  | ; O2: call | 
|  |  | 
|  | ; OM1-LABEL: testUncondToNextBlock | 
|  | ; OM1: call | 
|  | ; OM1-NEXT: jmp | 
|  | ; OM1: call | 
|  |  | 
|  | ; ARM32O2-LABEL: testUncondToNextBlock | 
|  | ; ARM32O2: bl {{.*}} dummy | 
|  | ; ARM32O2-NEXT: bl {{.*}} dummy | 
|  |  | 
|  | ; ARM32OM1-LABEL: testUncondToNextBlock | 
|  | ; ARM32OM1: bl {{.*}} dummy | 
|  | ; ARM32OM1-NEXT: b | 
|  | ; ARM32OM1-NEXT: bl {{.*}} dummy | 
|  |  | 
|  | ; MIPS32O2-LABEL: testUncondToNextBlock | 
|  | ; MIPS32O2: jal {{.*}} dummy | 
|  | ; MIPS32O2-NEXT: nop | 
|  | ; MIPS32O2-LABEL: <.LtestUncondToNextBlock$next>: | 
|  | ; MIPS32O2-NEXT: jal {{.*}} dummy | 
|  | ; MIPS32O2-NEXT: nop | 
|  |  | 
|  | ; MIPS32OM1-LABEL: testUncondToNextBlock | 
|  | ; MIPS32OM1: jal {{.*}} dummy | 
|  | ; MIPS32OM1-NEXT: nop | 
|  | ; MIPS32OM1-NEXT: b {{.*}} <.LtestUncondToNextBlock$next> | 
|  | ; MIPS32OM1-NEXT: nop | 
|  | ; MIPS32OM1-LABEL: <.LtestUncondToNextBlock$next>: | 
|  | ; MIPS32OM1-NEXT: jal {{.*}} dummy | 
|  | ; MIPS32OM1-NEXT: nop | 
|  |  | 
|  | ; For a conditional branch with a fallthrough to the next block, the | 
|  | ; fallthrough branch should be removed. | 
|  | define internal void @testCondFallthroughToNextBlock(i32 %arg) { | 
|  | entry: | 
|  | %cmp = icmp sge i32 %arg, 123 | 
|  | br i1 %cmp, label %target, label %fallthrough | 
|  | fallthrough: | 
|  | call void @dummy() | 
|  | ret void | 
|  | target: | 
|  | call void @dummy() | 
|  | ret void | 
|  | } | 
|  | ; O2-LABEL: testCondFallthroughToNextBlock | 
|  | ; O2: cmp {{.*}},0x7b | 
|  | ; O2-NEXT: jge | 
|  | ; O2-NOT: j | 
|  | ; O2: call | 
|  | ; O2: ret | 
|  | ; O2: call | 
|  | ; O2: ret | 
|  |  | 
|  | ; OM1-LABEL: testCondFallthroughToNextBlock | 
|  | ; OM1: cmp {{.*}},0x7b | 
|  | ; OM1: setge | 
|  | ; OM1: cmp | 
|  | ; OM1: jne | 
|  | ; OM1: jmp | 
|  | ; OM1: call | 
|  | ; OM1: ret | 
|  | ; OM1: call | 
|  | ; OM1: ret | 
|  |  | 
|  | ; ARM32O2-LABEL: testCondFallthroughToNextBlock | 
|  | ; ARM32O2: cmp {{.*}}, #123 | 
|  | ; ARM32O2-NEXT: bge | 
|  | ; ARM32O2-NEXT: bl | 
|  | ; ARM32O2: bx lr | 
|  | ; ARM32O2: bl | 
|  | ; ARM32O2: bx lr | 
|  |  | 
|  | ; ARM32OM1-LABEL: testCondFallthroughToNextBlock | 
|  | ; ARM32OM1: mov {{.*}}, #0 | 
|  | ; ARM32OM1: cmp {{.*}}, #123 | 
|  | ; ARM32OM1: movge {{.*}}, #1 | 
|  | ; ARM32OM1: tst {{.*}}, #1 | 
|  | ; ARM32OM1: bne | 
|  | ; ARM32OM1: b | 
|  | ; ARM32OM1: bl | 
|  | ; ARM32OM1: bx lr | 
|  | ; ARM32OM1: bl | 
|  | ; ARM32OM1: bx lr | 
|  |  | 
|  | ; MIPS32O2-LABEL: testCondFallthroughToNextBlock | 
|  | ; MIPS32O2: li {{.*}},123 | 
|  | ; MIPS32O2: slt {{.*}},{{.*}},{{.*}} | 
|  | ; MIPS32O2: beqz | 
|  | ; MIPS32O2: nop | 
|  | ; MIPS32O2: .LtestCondFallthroughToNextBlock$fallthrough | 
|  | ; MIPS32O2: jal {{.*}} dummy | 
|  | ; MIPS32O2: nop | 
|  | ; MIPS32O2: jr | 
|  | ; MIPS32O2: nop | 
|  | ; MIPS32O2: .LtestCondFallthroughToNextBlock$target | 
|  | ; MIPS32O2: jal {{.*}} dummy | 
|  | ; MIPS32O2: nop | 
|  | ; MIPS32O2: jr | 
|  | ; MIPS32O2: nop | 
|  |  | 
|  | ; MIPS32OM1-LABEL: testCondFallthroughToNextBlock | 
|  | ; MIPS32OM1: li {{.*}},123 | 
|  | ; MIPS32OM1: slt {{.*}},{{.*}},{{.*}} | 
|  | ; MIPS32OM1: xori {{.*}},{{.*}},{{.*}} | 
|  | ; MIPS32OM1: beqz | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: b | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: .LtestCondFallthroughToNextBlock$fallthrough | 
|  | ; MIPS32OM1: jal {{.*}} dummy | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: jr | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: .LtestCondFallthroughToNextBlock$target | 
|  | ; MIPS32OM1: jal {{.*}} dummy | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: jr | 
|  | ; MIPS32OM1: nop | 
|  |  | 
|  | ; For a conditional branch with the next block as the target and a | 
|  | ; different block as the fallthrough, the branch condition should be | 
|  | ; inverted, the fallthrough block changed to the target, and the | 
|  | ; branch to the next block removed. | 
|  | define internal void @testCondTargetNextBlock(i32 %arg) { | 
|  | entry: | 
|  | %cmp = icmp sge i32 %arg, 123 | 
|  | br i1 %cmp, label %fallthrough, label %target | 
|  | fallthrough: | 
|  | call void @dummy() | 
|  | ret void | 
|  | target: | 
|  | call void @dummy() | 
|  | ret void | 
|  | } | 
|  | ; O2-LABEL: testCondTargetNextBlock | 
|  | ; O2: cmp {{.*}},0x7b | 
|  | ; O2-NEXT: jl | 
|  | ; O2-NOT: j | 
|  | ; O2: call | 
|  | ; O2: ret | 
|  | ; O2: call | 
|  | ; O2: ret | 
|  |  | 
|  | ; OM1-LABEL: testCondTargetNextBlock | 
|  | ; OM1: cmp {{.*}},0x7b | 
|  | ; OM1: setge | 
|  | ; OM1: cmp | 
|  | ; OM1: jne | 
|  | ; OM1: jmp | 
|  | ; OM1: call | 
|  | ; OM1: ret | 
|  | ; OM1: call | 
|  | ; OM1: ret | 
|  |  | 
|  | ; Note that compare and branch folding isn't implemented yet | 
|  | ; (compared to x86-32). | 
|  | ; ARM32O2-LABEL: testCondTargetNextBlock | 
|  | ; ARM32O2: cmp {{.*}}, #123 | 
|  | ; ARM32O2-NEXT: blt | 
|  | ; ARM32O2-NEXT: bl | 
|  | ; ARM32O2: bx lr | 
|  | ; ARM32O2: bl | 
|  | ; ARM32O2: bx lr | 
|  |  | 
|  | ; ARM32OM1-LABEL: testCondTargetNextBlock | 
|  | ; ARM32OM1: cmp {{.*}}, #123 | 
|  | ; ARM32OM1: movge {{.*}}, #1 | 
|  | ; ARM32OM1: tst {{.*}}, #1 | 
|  | ; ARM32OM1: bne | 
|  | ; ARM32OM1: b | 
|  | ; ARM32OM1: bl | 
|  | ; ARM32OM1: bx lr | 
|  | ; ARM32OM1: bl | 
|  | ; ARM32OM1: bx lr | 
|  |  | 
|  | ; MIPS32O2-LABEL: testCondTargetNextBlock | 
|  | ; MIPS32O2: li {{.*}},123 | 
|  | ; MIPS32O2: slt {{.*}},{{.*}},{{.*}} | 
|  | ; MIPS32O2: bnez | 
|  | ; MIPS32O2: nop | 
|  | ; MIPS32O2: .LtestCondTargetNextBlock$fallthrough | 
|  | ; MIPS32O2: jal {{.*}} dummy | 
|  | ; MIPS32O2: nop | 
|  | ; MIPS32O2: jr | 
|  | ; MIPS32O2: nop | 
|  | ; MIPS32O2: .LtestCondTargetNextBlock$target | 
|  | ; MIPS32O2: jal {{.*}} dummy | 
|  | ; MIPS32O2: nop | 
|  | ; MIPS32O2: jr | 
|  | ; MIPS32O2: nop | 
|  |  | 
|  | ; MIPS32OM1-LABEL: testCondTargetNextBlock | 
|  | ; MIPS32OM1: li {{.*}},123 | 
|  | ; MIPS32OM1: slt {{.*}},{{.*}},{{.*}} | 
|  | ; MIPS32OM1: xori {{.*}},{{.*}},{{.*}} | 
|  | ; MIPS32OM1: beqz | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: b | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: .LtestCondTargetNextBlock$fallthrough | 
|  | ; MIPS32OM1: jal {{.*}} dummy | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: jr | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: .LtestCondTargetNextBlock$target | 
|  | ; MIPS32OM1: jal {{.*}} dummy | 
|  | ; MIPS32OM1: nop | 
|  | ; MIPS32OM1: jr | 
|  | ; MIPS32OM1: nop | 
|  |  | 
|  | ; Unconditional branches to the block after a contracted block should be | 
|  | ; removed. | 
|  | define internal void @testUncondToBlockAfterContract() { | 
|  | entry: | 
|  | call void @dummy() | 
|  | br label %target | 
|  | contract: | 
|  | br label %target | 
|  | target: | 
|  | call void @dummy() | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; O2-LABEL: testUncondToBlockAfterContract | 
|  | ; O2: call | 
|  | ; There will be nops for bundle align to end (for NaCl), but there should | 
|  | ; not be a branch. | 
|  | ; O2-NOT: j | 
|  | ; O2: call | 
|  |  | 
|  | ; OM1-LABEL: testUncondToBlockAfterContract | 
|  | ; OM1: call | 
|  | ; OM1-NEXT: jmp | 
|  | ; OM1: call | 
|  |  | 
|  | ; ARM32O2-LABEL: testUncondToBlockAfterContract | 
|  | ; ARM32O2: bl {{.*}} dummy | 
|  | ; ARM32O2-NEXT: bl {{.*}} dummy | 
|  |  | 
|  | ; ARM32OM1-LABEL: testUncondToBlockAfterContract | 
|  | ; ARM32OM1: bl {{.*}} dummy | 
|  | ; ARM32OM1-NEXT: b | 
|  | ; ARM32OM1-NEXT: bl {{.*}} dummy | 
|  |  | 
|  | ; MIPS32O2-LABEL: testUncondToBlockAfterContract | 
|  | ; MIPS32O2: jal {{.*}} dummy | 
|  | ; MIPS32O2: .LtestUncondToBlockAfterContract$target | 
|  |  | 
|  | ; MIPS32OM1-LABEL: testUncondToBlockAfterContract | 
|  | ; MIPS32OM1: jal {{.*}} dummy | 
|  | ; MIPS32OM1: b | 
|  | ; MIPS32OM1: .LtestUncondToBlockAfterContract$target |