Index: lib/Target/AArch64/AArch64FastISel.cpp =================================================================== --- lib/Target/AArch64/AArch64FastISel.cpp +++ lib/Target/AArch64/AArch64FastISel.cpp @@ -2411,19 +2411,17 @@ // Regardless, the compare has been done in the predecessor block, // and it left a value for us in a virtual register. Ergo, we test // the one-bit value left in the virtual register. - // - // FIXME: Optimize this with TBZW/TBZNW. - unsigned ANDReg = emitAnd_ri(MVT::i32, CondReg, CondRegIsKill, 1); - assert(ANDReg && "Unexpected AND instruction emission failure."); - emitICmp_ri(MVT::i32, ANDReg, /*IsKill=*/true, 0); + // i1 conditions come as an i32 value which we can use as input for cbnzw. + assert(CC == AArch64CC::NE); + unsigned Opcode = AArch64::CBNZW; if (FuncInfo.MBB->isLayoutSuccessor(TBB)) { std::swap(TBB, FBB); - CC = AArch64CC::EQ; + Opcode = AArch64::CBZW; } - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::Bcc)) - .addImm(CC) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opcode)) + .addReg(CondReg, getKillRegState(CondRegIsKill)) .addMBB(TBB); finishCondBranch(BI->getParent(), TBB, FBB); Index: test/CodeGen/AArch64/fast-isel-branch-cond-split.ll =================================================================== --- test/CodeGen/AArch64/fast-isel-branch-cond-split.ll +++ test/CodeGen/AArch64/fast-isel-branch-cond-split.ll @@ -44,9 +44,7 @@ ; 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 +; CHECK-NEXT: cbnz w8 define i64 @test_or_unpredictable(i32 %a, i32 %b) { bb1: %0 = icmp eq i32 %a, 0 @@ -68,9 +66,7 @@ ; 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 +; CHECK-NEXT: cbz w8 define i64 @test_and_unpredictable(i32 %a, i32 %b) { bb1: %0 = icmp ne i32 %a, 0