Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1734,7 +1734,7 @@ return SDValue(N, 0); // fold (a+b) -> (a|b) iff a and b share no bits. - if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) && + if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::OR, VT)) && VT.isInteger() && !VT.isVector() && DAG.haveNoCommonBitsSet(N0, N1)) return DAG.getNode(ISD::OR, SDLoc(N), VT, N0, N1); @@ -6373,7 +6373,7 @@ isa(N0.getOperand(0)) && N0.getOperand(1).getOpcode() == ISD::Constant && TLI.isLoadExtLegal(ISD::ZEXTLOAD, VT, N0.getValueType()) && - (!LegalOperations && TLI.isOperationLegal(N0.getOpcode(), VT))) { + (!LegalOperations && TLI.isOperationLegalOrCustom(N0.getOpcode(), VT))) { LoadSDNode *LN0 = cast(N0.getOperand(0)); if (LN0->getExtensionType() != ISD::SEXTLOAD && LN0->isUnindexed()) { bool DoXform = true; Index: lib/Target/AArch64/AArch64ISelLowering.h =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.h +++ lib/Target/AArch64/AArch64ISelLowering.h @@ -488,6 +488,8 @@ SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) const; SDValue LowerF128Call(SDValue Op, SelectionDAG &DAG, RTLIB::Libcall Call) const; + SDValue LowerAND(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const; Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -144,6 +144,16 @@ setOperationAction(ISD::XOR, MVT::i32, Custom); setOperationAction(ISD::XOR, MVT::i64, Custom); + // Custom lowering hooks are needed for OR + // to fold it into CCMP. + setOperationAction(ISD::OR, MVT::i32, Custom); + setOperationAction(ISD::OR, MVT::i64, Custom); + + // Custom lowering hooks are needed for AND + // to fold it into CCMP. + setOperationAction(ISD::AND, MVT::i32, Custom); + setOperationAction(ISD::AND, MVT::i64, Custom); + // Virtually no operation on f128 is legal, but LLVM can't expand them when // there's a valid register class, so we need custom operations in most cases. setOperationAction(ISD::FABS, MVT::f128, Expand); @@ -1662,6 +1672,60 @@ return makeLibCall(DAG, Call, MVT::f128, Ops, false, SDLoc(Op)).first; } +SDValue AArch64TargetLowering::LowerAND(SDValue Op, SelectionDAG &DAG) const { + + EVT VT = Op.getValueType(); + if (VT.isVector()) + return LowerVectorAND(Op, DAG); + + if (!Op->hasOneUse()) + return Op; + + SDNode *N = cast(Op.getNode()); + SDValue Chain; + if (!(isUsedByReturnOnly(N, Chain))) + return Op; + + SDLoc DL(Op); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + if ((LHS.getOpcode() != ISD::SETCC) || (RHS.getOpcode() != ISD::SETCC)) + return Op; + + SDValue TVal = DAG.getConstant(1, DL, VT); + SDValue FVal = DAG.getConstant(0, DL, VT); + SDValue CCVal; + SDValue Cmp = getAArch64Cmp(Op, FVal, ISD::SETEQ, CCVal, DAG, DL); + return DAG.getNode(AArch64ISD::CSEL, DL, VT, FVal, TVal, CCVal, Cmp); +} + +SDValue AArch64TargetLowering::LowerOR(SDValue Op, SelectionDAG &DAG) const { + + EVT VT = Op.getValueType(); + if (VT.isVector()) + return LowerVectorOR(Op, DAG); + + if (!Op->hasOneUse()) + return Op; + + SDNode *N = cast(Op.getNode()); + SDValue Chain; + if (!(isUsedByReturnOnly(N, Chain))) + return Op; + + SDLoc DL(Op); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + if ((LHS.getOpcode() != ISD::SETCC) || (RHS.getOpcode() != ISD::SETCC)) + return Op; + + SDValue TVal = DAG.getConstant(1, DL, VT); + SDValue FVal = DAG.getConstant(0, DL, VT); + SDValue CCVal; + SDValue Cmp = getAArch64Cmp(Op, FVal, ISD::SETEQ, CCVal, DAG, DL); + return DAG.getNode(AArch64ISD::CSEL, DL, VT, FVal, TVal, CCVal, Cmp); +} + static SDValue LowerXOR(SDValue Op, SelectionDAG &DAG) { SDValue Sel = Op.getOperand(0); SDValue Other = Op.getOperand(1); @@ -2316,9 +2380,9 @@ case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); case ISD::AND: - return LowerVectorAND(Op, DAG); + return LowerAND(Op, DAG); case ISD::OR: - return LowerVectorOR(Op, DAG); + return LowerOR(Op, DAG); case ISD::XOR: return LowerXOR(Op, DAG); case ISD::PREFETCH: Index: test/CodeGen/AArch64/arm64-ccmp.ll =================================================================== --- test/CodeGen/AArch64/arm64-ccmp.ll +++ test/CodeGen/AArch64/arm64-ccmp.ll @@ -389,6 +389,19 @@ ret i32 %sel } +; CHECK-LABEL: single_noselect +define i32 @single_noselect(i32 %A, i32 %B) #0 { +; CHECK: cmp w1, #1 +; CHECK-NEXT: ccmp w0, #1, #8, ge +; CHECK-NEXT: cset w0, lt +; CHECK-NEXT: ret + %notlhs = icmp slt i32 %A, 1 + %notrhs = icmp slt i32 %B, 1 + %lnot = or i1 %notlhs, %notrhs + %conv = zext i1 %lnot to i32 + ret i32 %conv +} + ; CHECK-LABEL: select_noccmp1 define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) { ; CHECK: cmp x0, #0