summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp59
1 files changed, 58 insertions, 1 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index e9e3c664350..8fac2435951 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1021,6 +1021,12 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ADDCARRY, MVT::i32, Custom);
setOperationAction(ISD::SUBCARRY, MVT::i32, Custom);
+ if (Subtarget->hasDSP()) {
+ setOperationAction(ISD::SADDSAT, MVT::i8, Custom);
+ setOperationAction(ISD::SSUBSAT, MVT::i8, Custom);
+ setOperationAction(ISD::SADDSAT, MVT::i16, Custom);
+ setOperationAction(ISD::SSUBSAT, MVT::i16, Custom);
+ }
// i64 operation support.
setOperationAction(ISD::MUL, MVT::i64, Expand);
@@ -1622,6 +1628,10 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
case ARMISD::SMLSLDX: return "ARMISD::SMLSLDX";
case ARMISD::SMMLAR: return "ARMISD::SMMLAR";
case ARMISD::SMMLSR: return "ARMISD::SMMLSR";
+ case ARMISD::QADD16b: return "ARMISD::QADD16b";
+ case ARMISD::QSUB16b: return "ARMISD::QSUB16b";
+ case ARMISD::QADD8b: return "ARMISD::QADD8b";
+ case ARMISD::QSUB8b: return "ARMISD::QSUB8b";
case ARMISD::BUILD_VECTOR: return "ARMISD::BUILD_VECTOR";
case ARMISD::BFI: return "ARMISD::BFI";
case ARMISD::VORRIMM: return "ARMISD::VORRIMM";
@@ -4445,6 +4455,35 @@ SDValue ARMTargetLowering::LowerUnsignedALUO(SDValue Op,
return DAG.getNode(ISD::MERGE_VALUES, dl, VTs, Value, Overflow);
}
+static SDValue LowerSADDSUBSAT(SDValue Op, SelectionDAG &DAG,
+ const ARMSubtarget *Subtarget) {
+ EVT VT = Op.getValueType();
+ if (!Subtarget->hasDSP())
+ return SDValue();
+ if (!VT.isSimple())
+ return SDValue();
+
+ unsigned NewOpcode;
+ bool IsAdd = Op->getOpcode() == ISD::SADDSAT;
+ switch (VT.getSimpleVT().SimpleTy) {
+ default:
+ return SDValue();
+ case MVT::i8:
+ NewOpcode = IsAdd ? ARMISD::QADD8b : ARMISD::QSUB8b;
+ break;
+ case MVT::i16:
+ NewOpcode = IsAdd ? ARMISD::QADD16b : ARMISD::QSUB16b;
+ break;
+ }
+
+ SDLoc dl(Op);
+ SDValue Add =
+ DAG.getNode(NewOpcode, dl, MVT::i32,
+ DAG.getSExtOrTrunc(Op->getOperand(0), dl, MVT::i32),
+ DAG.getSExtOrTrunc(Op->getOperand(1), dl, MVT::i32));
+ return DAG.getNode(ISD::TRUNCATE, dl, VT, Add);
+}
+
SDValue ARMTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
SDValue Cond = Op.getOperand(0);
SDValue SelectTrue = Op.getOperand(1);
@@ -9121,6 +9160,9 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::UADDO:
case ISD::USUBO:
return LowerUnsignedALUO(Op, DAG);
+ case ISD::SADDSAT:
+ case ISD::SSUBSAT:
+ return LowerSADDSUBSAT(Op, DAG, Subtarget);
case ISD::LOAD:
return LowerPredicateLoad(Op, DAG);
case ISD::STORE:
@@ -9205,6 +9247,10 @@ void ARMTargetLowering::ReplaceNodeResults(SDNode *N,
Results.push_back(Res.getValue(0));
Results.push_back(Res.getValue(1));
return;
+ case ISD::SADDSAT:
+ case ISD::SSUBSAT:
+ Res = LowerSADDSUBSAT(SDValue(N, 0), DAG, Subtarget);
+ break;
case ISD::READCYCLECOUNTER:
ReplaceREADCYCLECOUNTER(N, Results, DAG, Subtarget);
return;
@@ -14382,7 +14428,9 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N,
return SDValue();
break;
}
- case ARMISD::SMLALBB: {
+ case ARMISD::SMLALBB:
+ case ARMISD::QADD16b:
+ case ARMISD::QSUB16b: {
unsigned BitWidth = N->getValueType(0).getSizeInBits();
APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 16);
if ((SimplifyDemandedBits(N->getOperand(0), DemandedMask, DCI)) ||
@@ -14418,6 +14466,15 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N,
return SDValue();
break;
}
+ case ARMISD::QADD8b:
+ case ARMISD::QSUB8b: {
+ unsigned BitWidth = N->getValueType(0).getSizeInBits();
+ APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 8);
+ if ((SimplifyDemandedBits(N->getOperand(0), DemandedMask, DCI)) ||
+ (SimplifyDemandedBits(N->getOperand(1), DemandedMask, DCI)))
+ return SDValue();
+ break;
+ }
case ISD::INTRINSIC_VOID:
case ISD::INTRINSIC_W_CHAIN:
switch (cast<ConstantSDNode>(N->getOperand(1))->getZExtValue()) {
OpenPOWER on IntegriCloud