From e720feb1c612654c90a8b476778d89dbf3eb2e41 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 2 Mar 2017 21:49:49 +0000 Subject: [PATCH] [Hexagon] Pick the right branch opcode depending on branch probabilities Specifically, pick the opcode with the correct branch prediction, i.e. jump:t or jump:nt. llvm-svn: 296821 --- llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp | 84 ++++++++++++++++---- llvm/test/CodeGen/Hexagon/builtin-expect.ll | 44 ++++++++++ 2 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 llvm/test/CodeGen/Hexagon/builtin-expect.ll diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp index 6b74c2fd6184..509d838ad118 100644 --- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -3470,20 +3470,75 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const { int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI, const MachineBranchProbabilityInfo *MBPI) const { // We assume that block can have at most two successors. - bool taken = false; const MachineBasicBlock *Src = MI.getParent(); const MachineOperand &BrTarget = MI.getOperand(1); - const MachineBasicBlock *Dst = BrTarget.getMBB(); + bool Taken = false; + const BranchProbability OneHalf(1, 2); - const BranchProbability Prediction = MBPI->getEdgeProbability(Src, Dst); - if (Prediction >= BranchProbability(1,2)) - taken = true; + if (BrTarget.isMBB()) { + const MachineBasicBlock *Dst = BrTarget.getMBB(); + Taken = MBPI->getEdgeProbability(Src, Dst) >= OneHalf; + } else { + // The branch target is not a basic block (most likely a function). + // Since BPI only gives probabilities for targets that are basic blocks, + // try to identify another target of this branch (potentially a fall- + // -through) and check the probability of that target. + // + // The only handled branch combinations are: + // - one conditional branch, + // - one conditional branch followed by one unconditional branch. + // Otherwise, assume not-taken. + assert(MI.isConditionalBranch()); + const MachineBasicBlock &B = *MI.getParent(); + bool SawCond = false, Bad = false; + for (const MachineInstr &I : B) { + if (!I.isBranch()) + continue; + if (I.isConditionalBranch()) { + SawCond = true; + if (&I != &MI) { + Bad = true; + break; + } + } + if (I.isUnconditionalBranch() && !SawCond) { + Bad = true; + break; + } + } + if (!Bad) { + MachineBasicBlock::const_instr_iterator It(MI); + MachineBasicBlock::const_instr_iterator NextIt = std::next(It); + if (NextIt == B.instr_end()) { + // If this branch is the last, look for the fall-through block. + for (const MachineBasicBlock *SB : B.successors()) { + if (!B.isLayoutSuccessor(SB)) + continue; + Taken = MBPI->getEdgeProbability(Src, SB) < OneHalf; + break; + } + } else { + assert(NextIt->isUnconditionalBranch()); + // Find the first MBB operand and assume it's the target. + const MachineBasicBlock *BT = nullptr; + for (const MachineOperand &Op : NextIt->operands()) { + if (!Op.isMBB()) + continue; + BT = Op.getMBB(); + break; + } + Taken = BT && MBPI->getEdgeProbability(Src, BT) < OneHalf; + } + } // if (!Bad) + } + + // The Taken flag should be set to something reasonable by this point. switch (MI.getOpcode()) { case Hexagon::J2_jumpt: - return taken ? Hexagon::J2_jumptnewpt : Hexagon::J2_jumptnew; + return Taken ? Hexagon::J2_jumptnewpt : Hexagon::J2_jumptnew; case Hexagon::J2_jumpf: - return taken ? Hexagon::J2_jumpfnewpt : Hexagon::J2_jumpfnew; + return Taken ? Hexagon::J2_jumpfnewpt : Hexagon::J2_jumpfnew; default: llvm_unreachable("Unexpected jump instruction."); @@ -3493,20 +3548,19 @@ int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI, // Return .new predicate version for an instruction. int HexagonInstrInfo::getDotNewPredOp(const MachineInstr &MI, const MachineBranchProbabilityInfo *MBPI) const { - int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode()); - if (NewOpcode >= 0) // Valid predicate new instruction - return NewOpcode; - switch (MI.getOpcode()) { // Condtional Jumps case Hexagon::J2_jumpt: case Hexagon::J2_jumpf: return getDotNewPredJumpOp(MI, MBPI); - - default: - assert(0 && "Unknown .new type"); } - return 0; + + int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode()); + if (NewOpcode >= 0) + return NewOpcode; + + dbgs() << "Cannot convert to .new: " << getName(MI.getOpcode()) << '\n'; + llvm_unreachable(nullptr); } int HexagonInstrInfo::getDotOldOp(const int opc) const { diff --git a/llvm/test/CodeGen/Hexagon/builtin-expect.ll b/llvm/test/CodeGen/Hexagon/builtin-expect.ll new file mode 100644 index 000000000000..9945da1782b2 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/builtin-expect.ll @@ -0,0 +1,44 @@ +; RUN: llc -march=hexagon -disable-block-placement < %s | FileCheck %s + +; Check that the branch to the block b10 is marked as taken (i.e. ":t"). +; CHECK-LABEL: foo +; CHECK: if ({{.*}}) jump:t .LBB0_[[LAB:[0-9]+]] +; CHECK: [[LAB]]: +; CHECK: add({{.*}},#65) + +target triple = "hexagon" + +define i32 @foo(i32 %a0) local_unnamed_addr #0 { +b1: + %v2 = icmp eq i32 %a0, 0 + br i1 %v2, label %b3, label %b10, !prof !0 + +b3: ; preds = %b1 + br label %b4 + +b4: ; preds = %b4, %b3 + %v5 = phi i32 [ %v6, %b4 ], [ 0, %b3 ] + %v6 = add nuw nsw i32 %v5, 1 + %v7 = mul nuw nsw i32 %v5, 67 + %v8 = tail call i32 @bar(i32 %v7) #0 + %v9 = icmp eq i32 %v6, 10 + br i1 %v9, label %b13, label %b4 + +b10: ; preds = %b1 + %v11 = add nsw i32 %a0, 65 + %v12 = tail call i32 @bar(i32 %v11) #0 + br label %b14 + +b13: ; preds = %b4 + br label %b14 + +b14: ; preds = %b13, %b10 + %v15 = phi i32 [ %v12, %b10 ], [ 0, %b13 ] + ret i32 %v15 +} + +declare i32 @bar(i32) local_unnamed_addr #0 + +attributes #0 = { nounwind "target-cpu"="hexagonv60" "target-features"="+hvx,-hvx-double,-long-calls" } + +!0 = !{!"branch_weights", i32 1, i32 2000}