From 42574203e55772022f93904a16f020daeade27cc Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 2 Sep 2015 19:23:23 +0000 Subject: [PATCH] use "unpredictable" metadata in fast-isel when splitting compares This patch uses the metadata defined in D12341 to avoid creating an unpredictable branch. Differential Revision: http://reviews.llvm.org/D12342 llvm-svn: 246692 --- llvm/lib/CodeGen/CodeGenPrepare.cpp | 5 +- .../AArch64/fast-isel-branch-cond-split.ll | 52 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 9e0ac96ba56a..9ed15fb77531 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -4667,6 +4667,10 @@ bool CodeGenPrepare::splitBranchCondition(Function &F) { if (!match(BB.getTerminator(), m_Br(m_OneUse(m_BinOp(LogicOp)), TBB, FBB))) continue; + auto *Br1 = cast(BB.getTerminator()); + if (Br1->getMetadata(LLVMContext::MD_unpredictable)) + continue; + unsigned Opc; Value *Cond1, *Cond2; if (match(LogicOp, m_And(m_OneUse(m_Value(Cond1)), @@ -4693,7 +4697,6 @@ bool CodeGenPrepare::splitBranchCondition(Function &F) { // Update original basic block by using the first condition directly by the // branch instruction and removing the no longer needed and/or instruction. - auto *Br1 = cast(BB.getTerminator()); Br1->setCondition(Cond1); LogicOp->eraseFromParent(); diff --git a/llvm/test/CodeGen/AArch64/fast-isel-branch-cond-split.ll b/llvm/test/CodeGen/AArch64/fast-isel-branch-cond-split.ll index aa6d5f11f362..5248b9253e7a 100644 --- a/llvm/test/CodeGen/AArch64/fast-isel-branch-cond-split.ll +++ b/llvm/test/CodeGen/AArch64/fast-isel-branch-cond-split.ll @@ -36,7 +36,59 @@ bb4: ret i64 %2 } +; If the branch is unpredictable, don't add another branch. + +; CHECK-LABEL: test_or_unpredictable +; CHECK: cmp w0, #0 +; CHECK-NEXT: cset w8, eq +; CHECK-NEXT: cmp w1, #0 +; CHECK-NEXT: cset w9, eq +; CHECK-NEXT: orr w8, w8, w9 +; CHECK-NEXT: and w8, w8, #0x1 +; CHECK-NEXT: cmp w8, #0 +; CHECK-NEXT: b.ne +define i64 @test_or_unpredictable(i32 %a, i32 %b) { +bb1: + %0 = icmp eq i32 %a, 0 + %1 = icmp eq i32 %b, 0 + %or.cond = or i1 %0, %1 + br i1 %or.cond, label %bb3, label %bb4, !unpredictable !2 + +bb3: + ret i64 0 + +bb4: + %2 = call i64 @bar() + ret i64 %2 +} + +; CHECK-LABEL: test_and_unpredictable +; CHECK: cmp w0, #0 +; CHECK-NEXT: cset w8, ne +; CHECK-NEXT: cmp w1, #0 +; CHECK-NEXT: cset w9, ne +; CHECK-NEXT: and w8, w8, w9 +; CHECK-NEXT: and w8, w8, #0x1 +; CHECK-NEXT: cmp w8, #0 +; CHECK-NEXT: b.eq +define i64 @test_and_unpredictable(i32 %a, i32 %b) { +bb1: + %0 = icmp ne i32 %a, 0 + %1 = icmp ne i32 %b, 0 + %or.cond = and i1 %0, %1 + br i1 %or.cond, label %bb4, label %bb3, !unpredictable !2 + +bb3: + ret i64 0 + +bb4: + %2 = call i64 @bar() + ret i64 %2 +} + declare i64 @bar() !0 = !{!"branch_weights", i32 5128, i32 32} !1 = !{!"branch_weights", i32 1024, i32 4136} +!2 = !{} +