diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp | 206 |
1 files changed, 182 insertions, 24 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp b/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp index e7e10ce07a44..33d115945614 100644 --- a/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -1016,6 +1016,10 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM, setTargetDAGCombine(ISD::FP_EXTEND); setTargetDAGCombine(ISD::SELECT); setTargetDAGCombine(ISD::SELECT_CC); + setTargetDAGCombine(ISD::SETCC); + } + if (Subtarget->hasMVEFloatOps()) { + setTargetDAGCombine(ISD::FADD); } if (!Subtarget->hasFP64()) { @@ -10587,10 +10591,9 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI, LPadList.reserve(CallSiteNumToLPad.size()); for (unsigned I = 1; I <= MaxCSNum; ++I) { SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[I]; - for (SmallVectorImpl<MachineBasicBlock*>::iterator - II = MBBList.begin(), IE = MBBList.end(); II != IE; ++II) { - LPadList.push_back(*II); - InvokeBBs.insert((*II)->pred_begin(), (*II)->pred_end()); + for (MachineBasicBlock *MBB : MBBList) { + LPadList.push_back(MBB); + InvokeBBs.insert(MBB->pred_begin(), MBB->pred_end()); } } @@ -10879,9 +10882,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI, // Add the jump table entries as successors to the MBB. SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs; - for (std::vector<MachineBasicBlock*>::iterator - I = LPadList.begin(), E = LPadList.end(); I != E; ++I) { - MachineBasicBlock *CurMBB = *I; + for (MachineBasicBlock *CurMBB : LPadList) { if (SeenMBBs.insert(CurMBB).second) DispContBB->addSuccessor(CurMBB); } @@ -10943,9 +10944,8 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI, // Mark all former landing pads as non-landing pads. The dispatch is the only // landing pad now. - for (SmallVectorImpl<MachineBasicBlock*>::iterator - I = MBBLPads.begin(), E = MBBLPads.end(); I != E; ++I) - (*I)->setIsEHPad(false); + for (MachineBasicBlock *MBBLPad : MBBLPads) + MBBLPad->setIsEHPad(false); // The instruction is gone now. MI.eraseFromParent(); @@ -11771,8 +11771,8 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE; break; } MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc)); - for (unsigned i = 0; i < MI.getNumOperands(); ++i) - MIB.add(MI.getOperand(i)); + for (const MachineOperand &MO : MI.operands()) + MIB.add(MO); MI.eraseFromParent(); return BB; } @@ -13083,6 +13083,65 @@ static SDValue PerformVSELECTCombine(SDNode *N, return DCI.DAG.getNode(ISD::VSELECT, SDLoc(N), Type, Cond, RHS, LHS); } +// Convert vsetcc([0,1,2,..], splat(n), ult) -> vctp n +static SDValue PerformVSetCCToVCTPCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + SDValue Op0 = N->getOperand(0); + SDValue Op1 = N->getOperand(1); + ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); + EVT VT = N->getValueType(0); + + if (!Subtarget->hasMVEIntegerOps() || + !DCI.DAG.getTargetLoweringInfo().isTypeLegal(VT)) + return SDValue(); + + if (CC == ISD::SETUGE) { + std::swap(Op0, Op1); + CC = ISD::SETULT; + } + + if (CC != ISD::SETULT || VT.getScalarSizeInBits() != 1 || + Op0.getOpcode() != ISD::BUILD_VECTOR) + return SDValue(); + + // Check first operand is BuildVector of 0,1,2,... + for (unsigned I = 0; I < VT.getVectorNumElements(); I++) { + if (!Op0.getOperand(I).isUndef() && + !(isa<ConstantSDNode>(Op0.getOperand(I)) && + Op0.getConstantOperandVal(I) == I)) + return SDValue(); + } + + // The second is a Splat of Op1S + SDValue Op1S = DCI.DAG.getSplatValue(Op1); + if (!Op1S) + return SDValue(); + + unsigned Opc; + switch (VT.getVectorNumElements()) { + case 2: + Opc = Intrinsic::arm_mve_vctp64; + break; + case 4: + Opc = Intrinsic::arm_mve_vctp32; + break; + case 8: + Opc = Intrinsic::arm_mve_vctp16; + break; + case 16: + Opc = Intrinsic::arm_mve_vctp8; + break; + default: + return SDValue(); + } + + SDLoc DL(N); + return DCI.DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, + DCI.DAG.getConstant(Opc, DL, MVT::i32), + DCI.DAG.getZExtOrTrunc(Op1S, DL, MVT::i32)); +} + static SDValue PerformABSCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget) { @@ -13427,6 +13486,26 @@ bool ARMTargetLowering::preferIncOfAddToSubOfNot(EVT VT) const { return VT.isScalarInteger(); } +bool ARMTargetLowering::shouldConvertFpToSat(unsigned Op, EVT FPVT, + EVT VT) const { + if (!isOperationLegalOrCustom(Op, VT) || !FPVT.isSimple()) + return false; + + switch (FPVT.getSimpleVT().SimpleTy) { + case MVT::f16: + return Subtarget->hasVFP2Base(); + case MVT::f32: + return Subtarget->hasVFP2Base(); + case MVT::f64: + return Subtarget->hasFP64(); + case MVT::v4f32: + case MVT::v8f16: + return Subtarget->hasMVEFloatOps(); + default: + return false; + } +} + static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST) { @@ -14485,6 +14564,52 @@ static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG) { return SDValue(); } +// Check that N is CMPZ(CSINC(0, 0, CC, X)), return X if valid. +static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC) { + if (Cmp->getOpcode() != ARMISD::CMPZ || !isNullConstant(Cmp->getOperand(1))) + return SDValue(); + SDValue CSInc = Cmp->getOperand(0); + if (CSInc.getOpcode() != ARMISD::CSINC || + !isNullConstant(CSInc.getOperand(0)) || + !isNullConstant(CSInc.getOperand(1)) || !CSInc->hasOneUse()) + return SDValue(); + CC = (ARMCC::CondCodes)CSInc.getConstantOperandVal(2); + return CSInc.getOperand(3); +} + +static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG) { + // Given CMPZ(CSINC(C, 0, 0, EQ), 0), we can just use C directly. As in + // t92: glue = ARMISD::CMPZ t74, 0 + // t93: i32 = ARMISD::CSINC 0, 0, 1, t92 + // t96: glue = ARMISD::CMPZ t93, 0 + // t114: i32 = ARMISD::CSINV 0, 0, 0, t96 + ARMCC::CondCodes Cond; + if (SDValue C = IsCMPZCSINC(N, Cond)) + if (Cond == ARMCC::EQ) + return C; + return SDValue(); +} + +static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG) { + // Fold away an unneccessary CMPZ/CSINC + // CSXYZ A, B, C1 (CMPZ (CSINC 0, 0, C2, D), 0) -> + // if C1==EQ -> CSXYZ A, B, C2, D + // if C1==NE -> CSXYZ A, B, NOT(C2), D + ARMCC::CondCodes Cond; + if (SDValue C = IsCMPZCSINC(N->getOperand(3).getNode(), Cond)) { + if (N->getConstantOperandVal(2) == ARMCC::EQ) + return DAG.getNode(N->getOpcode(), SDLoc(N), MVT::i32, N->getOperand(0), + N->getOperand(1), + DAG.getConstant(Cond, SDLoc(N), MVT::i32), C); + if (N->getConstantOperandVal(2) == ARMCC::NE) + return DAG.getNode( + N->getOpcode(), SDLoc(N), MVT::i32, N->getOperand(0), + N->getOperand(1), + DAG.getConstant(ARMCC::getOppositeCondition(Cond), SDLoc(N), MVT::i32), C); + } + return SDValue(); +} + /// PerformVMOVRRDCombine - Target-specific dag combine xforms for /// ARMISD::VMOVRRD. static SDValue PerformVMOVRRDCombine(SDNode *N, @@ -16411,6 +16536,42 @@ static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, return FixConv; } +static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *Subtarget) { + if (!Subtarget->hasMVEFloatOps()) + return SDValue(); + + // Turn (fadd x, (vselect c, y, -0.0)) into (vselect c, (fadd x, y), x) + // The second form can be more easily turned into a predicated vadd, and + // possibly combined into a fma to become a predicated vfma. + SDValue Op0 = N->getOperand(0); + SDValue Op1 = N->getOperand(1); + EVT VT = N->getValueType(0); + SDLoc DL(N); + + // The identity element for a fadd is -0.0, which these VMOV's represent. + auto isNegativeZeroSplat = [&](SDValue Op) { + if (Op.getOpcode() != ISD::BITCAST || + Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM) + return false; + if (VT == MVT::v4f32 && Op.getOperand(0).getConstantOperandVal(0) == 1664) + return true; + if (VT == MVT::v8f16 && Op.getOperand(0).getConstantOperandVal(0) == 2688) + return true; + return false; + }; + + if (Op0.getOpcode() == ISD::VSELECT && Op1.getOpcode() != ISD::VSELECT) + std::swap(Op0, Op1); + + if (Op1.getOpcode() != ISD::VSELECT || + !isNegativeZeroSplat(Op1.getOperand(2))) + return SDValue(); + SDValue FAdd = + DAG.getNode(ISD::FADD, DL, VT, Op0, Op1.getOperand(1), N->getFlags()); + return DAG.getNode(ISD::VSELECT, DL, VT, Op1.getOperand(0), FAdd, Op0); +} + /// PerformVDIVCombine - VCVT (fixed-point to floating-point, Advanced SIMD) /// can replace combinations of VCVT (integer to floating-point) and VDIV /// when the VDIV has a constant operand that is a power of 2. @@ -17049,18 +17210,6 @@ static SDValue PerformShiftCombine(SDNode *N, const ARMSubtarget *ST) { SelectionDAG &DAG = DCI.DAG; EVT VT = N->getValueType(0); - if (N->getOpcode() == ISD::SRL && VT == MVT::i32 && ST->hasV6Ops()) { - // Canonicalize (srl (bswap x), 16) to (rotr (bswap x), 16) if the high - // 16-bits of x is zero. This optimizes rev + lsr 16 to rev16. - SDValue N1 = N->getOperand(1); - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N1)) { - SDValue N0 = N->getOperand(0); - if (C->getZExtValue() == 16 && N0.getOpcode() == ISD::BSWAP && - DAG.MaskedValueIsZero(N0.getOperand(0), - APInt::getHighBitsSet(32, 16))) - return DAG.getNode(ISD::ROTR, SDLoc(N), VT, N0, N1); - } - } if (ST->isThumb1Only() && N->getOpcode() == ISD::SHL && VT == MVT::i32 && N->getOperand(0)->getOpcode() == ISD::AND && @@ -18173,6 +18322,7 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, case ISD::SELECT_CC: case ISD::SELECT: return PerformSELECTCombine(N, DCI, Subtarget); case ISD::VSELECT: return PerformVSELECTCombine(N, DCI, Subtarget); + case ISD::SETCC: return PerformVSetCCToVCTPCombine(N, DCI, Subtarget); case ISD::ABS: return PerformABSCombine(N, DCI, Subtarget); case ARMISD::ADDE: return PerformADDECombine(N, DCI, Subtarget); case ARMISD::UMLAL: return PerformUMLALCombine(N, DCI.DAG, Subtarget); @@ -18205,6 +18355,8 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: return PerformVCVTCombine(N, DCI.DAG, Subtarget); + case ISD::FADD: + return PerformFAddVSelectCombine(N, DCI.DAG, Subtarget); case ISD::FDIV: return PerformVDIVCombine(N, DCI.DAG, Subtarget); case ISD::INTRINSIC_WO_CHAIN: @@ -18228,6 +18380,12 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, return PerformCMOVCombine(N, DCI.DAG); case ARMISD::BRCOND: return PerformBRCONDCombine(N, DCI.DAG); + case ARMISD::CMPZ: + return PerformCMPZCombine(N, DCI.DAG); + case ARMISD::CSINC: + case ARMISD::CSINV: + case ARMISD::CSNEG: + return PerformCSETCombine(N, DCI.DAG); case ISD::LOAD: return PerformLOADCombine(N, DCI, Subtarget); case ARMISD::VLD1DUP: |
