aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp206
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: