diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -16391,6 +16391,26 @@ if (SDValue R = performANDORCSELCombine(N, DAG)) return R; + SDLoc DL(N); + AArch64CC::CondCode AArch64CC; + SDValue Cmp,Cset; + SDValue SetCC = N->getOperand(0); +if (SetCC.getOpcode() == ISD::SETCC && SetCC.getOperand(0).getValueType() == MVT::f32){ + + if (!DCI.isBeforeLegalize() && + (Cmp = emitConjunction(DAG, SDValue(N, 0), AArch64CC))){ + + unsigned ZeroReg = VT.getSizeInBits() == 32 ? AArch64::WZR : AArch64::XZR; + AArch64CC::CondCode InvertedCC = AArch64CC::getInvertedCondCode(AArch64CC); + + Cset = DAG.getNode(AArch64ISD::CSINC, DL, VT, + DAG.getRegister(ZeroReg, VT), DAG.getRegister(ZeroReg, VT), + DAG.getConstant(InvertedCC, DL, MVT::i32), Cmp); + + return Cset; + } +} + if (!DAG.getTargetLoweringInfo().isTypeLegal(VT)) return SDValue(); diff --git a/llvm/test/CodeGen/AArch64/andcompare.ll b/llvm/test/CodeGen/AArch64/andcompare.ll --- a/llvm/test/CodeGen/AArch64/andcompare.ll +++ b/llvm/test/CodeGen/AArch64/andcompare.ll @@ -2522,6 +2522,29 @@ ret i32 %r } +define i1 @cmp_and(float %0, float %1) { +; SDISEL-LABEL: cmp_and: +; SDISEL: // %bb.0: +; SDISEL-NEXT: fcmp s1, s1 +; SDISEL-NEXT: fccmp s0, s0, #0, vs +; SDISEL-NEXT: cset w0, vs +; SDISEL-NEXT: ret +; +; GISEL-LABEL: cmp_and: +; GISEL: // %bb.0: +; GISEL-NEXT: fcmp s0, #0.0 +; GISEL-NEXT: cset w8, vs +; GISEL-NEXT: fcmp s1, #0.0 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: and w0, w8, w9 +; GISEL-NEXT: ret + + %3 = fcmp uno float %0, 0.000000e+00 + %4 = fcmp uno float %1, 0.000000e+00 + %5 = and i1 %3, %4 + ret i1 %5 +} + ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: ; CHECK: {{.*}}