Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -2825,6 +2825,7 @@ llvm_unreachable("Unexpected platform trying to use TLS"); } + SDValue AArch64TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDValue Chain = Op.getOperand(0); ISD::CondCode CC = cast(Op.getOperand(1))->get(); @@ -2921,9 +2922,27 @@ } return DAG.getNode(AArch64ISD::CBNZ, dl, MVT::Other, Chain, LHS, Dest); + } else if (CC == ISD::SETLT && + (LHS.getOpcode() == ISD::SUB || LHS.getOpcode() == ISD::ADD)) { + uint64_t Mask = LHS.getValueType().getSizeInBits() - 1; + // TBNZ only operates on i64's, but the ext should be free. + if (LHS.getValueType() == MVT::i32) + LHS = DAG.getAnyExtOrTrunc(LHS, dl, MVT::i64); + + return DAG.getNode(AArch64ISD::TBNZ, dl, MVT::Other, Chain, LHS, + DAG.getConstant(Mask, MVT::i64), Dest); } } - + if (RHSC && RHSC->getSExtValue() == -1 && CC == ISD::SETGT && + (LHS.getOpcode() == ISD::ADD || LHS.getOpcode() == ISD::SUB)) { + uint64_t Mask = LHS.getValueType().getSizeInBits() - 1; + // TBZ only operates on i64's, but the ext should be free. + if (LHS.getValueType() == MVT::i32) + LHS = DAG.getAnyExtOrTrunc(LHS, dl, MVT::i64); + + return DAG.getNode(AArch64ISD::TBZ, dl, MVT::Other, Chain, LHS, + DAG.getConstant(Mask, MVT::i64), Dest); + } SDValue CCVal; SDValue Cmp = getAArch64Cmp(LHS, RHS, CC, CCVal, DAG, dl); return DAG.getNode(AArch64ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, Index: test/CodeGen/AArch64/tbz-tbnz.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/tbz-tbnz.ll @@ -0,0 +1,145 @@ +; RUN: llc -O1 -march=aarch64 < %s | FileCheck %s + +define void @test1(i32 %a, i8* nocapture %ptr) { +; CHECK-LABEL: @test1 +entry: + %sub = add nsw i32 %a, -12 + %cmp = icmp slt i32 %sub, 0 + br i1 %cmp, label %if.then, label %if.end + +; CHECK: sub [[CMP:w[0-9]+]], w0, #12 +; CHECK: tbz [[CMP]], #31 + +if.then: + store i8 1, i8* %ptr, align 1 + br label %if.end + +if.end: + ret void +} + +define void @test2(i64 %a, i8* nocapture %ptr) { +; CHECK-LABEL: @test2 +entry: + %sub = add nsw i64 %a, -12 + %cmp = icmp slt i64 %sub, 0 + br i1 %cmp, label %if.then, label %if.end + +; CHECK: sub [[CMP:x[0-9]+]], x0, #12 +; CHECK: tbz [[CMP]], #63 + +if.then: + store i8 1, i8* %ptr, align 1 + br label %if.end + +if.end: + ret void +} + +define void @test3(i32 %a, i8* nocapture %ptr) { +; CHECK-LABEL: @test3 +entry: + %sub = add nsw i32 %a, -12 + %cmp = icmp sgt i32 %sub, -1 + br i1 %cmp, label %if.then, label %if.end + +; CHECK: sub [[CMP:w[0-9]+]], w0, #12 +; CHECK: tbnz [[CMP]], #31 + +if.then: + store i8 1, i8* %ptr, align 1 + br label %if.end + +if.end: + ret void +} + +define void @test4(i64 %a, i8* nocapture %ptr) { +; CHECK-LABEL: @test4 +entry: + %sub = add nsw i64 %a, -12 + %cmp = icmp sgt i64 %sub, -1 + br i1 %cmp, label %if.then, label %if.end + +; CHECK: sub [[CMP:x[0-9]+]], x0, #12 +; CHECK: tbnz [[CMP]], #63 + +if.then: + store i8 1, i8* %ptr, align 1 + br label %if.end + +if.end: + ret void +} + +define void @test5(i32 %a, i8* nocapture %ptr) { +; CHECK-LABEL: @test5 +entry: + %sub = add nsw i32 %a, -12 + %cmp = icmp sge i32 %sub, 0 + br i1 %cmp, label %if.then, label %if.end + +; CHECK: sub [[CMP:w[0-9]+]], w0, #12 +; CHECK: tbnz [[CMP]], #31 + +if.then: + store i8 1, i8* %ptr, align 1 + br label %if.end + +if.end: + ret void +} + +define void @test6(i64 %a, i8* nocapture %ptr) { +; CHECK-LABEL: @test6 +entry: + %sub = add nsw i64 %a, -12 + %cmp = icmp sge i64 %sub, 0 + br i1 %cmp, label %if.then, label %if.end + +; CHECK: sub [[CMP:x[0-9]+]], x0, #12 +; CHECK: tbnz [[CMP]], #63 + +if.then: + store i8 1, i8* %ptr, align 1 + br label %if.end + +if.end: + ret void +} + +define void @test7(i32 %a, i8* nocapture %ptr) { +; CHECK-LABEL: @test7 +entry: + %sub = sub nsw i32 %a, 12 + %cmp = icmp slt i32 %sub, 0 + br i1 %cmp, label %if.then, label %if.end + +; CHECK: sub [[CMP:w[0-9]+]], w0, #12 +; CHECK: tbz [[CMP]], #31 + +if.then: + store i8 1, i8* %ptr, align 1 + br label %if.end + +if.end: + ret void +} + +define void @test8(i64 %val1, i64 %val2, i64* %ptr) { +; CHECK-LABEL: @test8 + %shifted_op = shl i64 %val2, 63 + %shifted_and = and i64 %val1, %shifted_op + %tst = icmp slt i64 %shifted_and, 0 + br i1 %tst, label %if.then, label %if.end + +; CHECK: tst {{x[0-9]+}}, {{x[0-9]+}}, lsl #63 +; CHECK: b.ge .L + +if.then: + store i64 %val1, i64* %ptr + br label %if.end + +if.end: + ret void +}