summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>2018-06-01 14:00:32 +0000
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>2018-06-01 14:00:32 +0000
commit0b6187c1a9526a2601bae31248eaaa7ec54987a8 (patch)
treece9e5c98cb33c784e5a39b3d3f58b552ecb31ae2 /llvm/lib/Target
parentb34afcec5ddf9f0fa4ac62468900a2866e644aea (diff)
downloadbcm5719-llvm-0b6187c1a9526a2601bae31248eaaa7ec54987a8.tar.gz
bcm5719-llvm-0b6187c1a9526a2601bae31248eaaa7ec54987a8.zip
[SelectionDAG] Expand UADDO/USUBO into ADD/SUBCARRY if legal for target
Additionally, implement handling of ADD/SUBCARRY on Hexagon, utilizing the UADDO/USUBO expansion. Differential Revision: https://reviews.llvm.org/D47559 llvm-svn: 333751
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp12
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h1
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLowering.cpp37
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLowering.h3
4 files changed, 48 insertions, 5 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index 0d0b35118c1..efb4c2eb0fc 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -762,6 +762,15 @@ void HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
ReplaceNode(N, R);
}
+void HexagonDAGToDAGISel::SelectAddSubCarry(SDNode *N) {
+ unsigned OpcCarry = N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c
+ : Hexagon::A4_subp_c;
+ SDNode *C = CurDAG->getMachineNode(OpcCarry, SDLoc(N), N->getVTList(),
+ { N->getOperand(0), N->getOperand(1),
+ N->getOperand(2) });
+ ReplaceNode(N, C);
+}
+
void HexagonDAGToDAGISel::SelectVAlign(SDNode *N) {
MVT ResTy = N->getValueType(0).getSimpleVT();
if (HST->isHVXVectorType(ResTy, true))
@@ -875,6 +884,9 @@ void HexagonDAGToDAGISel::Select(SDNode *N) {
case ISD::STORE: return SelectStore(N);
case ISD::INTRINSIC_W_CHAIN: return SelectIntrinsicWChain(N);
case ISD::INTRINSIC_WO_CHAIN: return SelectIntrinsicWOChain(N);
+
+ case HexagonISD::ADDC:
+ case HexagonISD::SUBC: return SelectAddSubCarry(N);
case HexagonISD::VALIGN: return SelectVAlign(N);
case HexagonISD::VALIGNADDR: return SelectVAlignAddr(N);
case HexagonISD::TYPECAST: return SelectTypecast(N);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
index 1c3379bf015..f4f09dd4e75 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
@@ -105,6 +105,7 @@ public:
void SelectV65Gather(SDNode *N);
void SelectV65GatherPred(SDNode *N);
void SelectHVXDualOutput(SDNode *N);
+ void SelectAddSubCarry(SDNode *N);
void SelectVAlign(SDNode *N);
void SelectVAlignAddr(SDNode *N);
void SelectTypecast(SDNode *N);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 4a85427032c..a63af51bf86 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1327,13 +1327,18 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
setMinimumJumpTableEntries(std::numeric_limits<int>::max());
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
- // Only add and sub that detect overflow are the saturating ones.
+ // Hexagon has A4_addp_c and A4_subp_c that take and generate a carry bit,
+ // but they only operate on i64.
for (MVT VT : MVT::integer_valuetypes()) {
- setOperationAction(ISD::UADDO, VT, Expand);
- setOperationAction(ISD::SADDO, VT, Expand);
- setOperationAction(ISD::USUBO, VT, Expand);
- setOperationAction(ISD::SSUBO, VT, Expand);
+ setOperationAction(ISD::UADDO, VT, Expand);
+ setOperationAction(ISD::USUBO, VT, Expand);
+ setOperationAction(ISD::SADDO, VT, Expand);
+ setOperationAction(ISD::SSUBO, VT, Expand);
+ setOperationAction(ISD::ADDCARRY, VT, Expand);
+ setOperationAction(ISD::SUBCARRY, VT, Expand);
}
+ setOperationAction(ISD::ADDCARRY, MVT::i64, Custom);
+ setOperationAction(ISD::SUBCARRY, MVT::i64, Custom);
setOperationAction(ISD::CTLZ, MVT::i8, Promote);
setOperationAction(ISD::CTLZ, MVT::i16, Promote);
@@ -1681,6 +1686,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch ((HexagonISD::NodeType)Opcode) {
+ case HexagonISD::ADDC: return "HexagonISD::ADDC";
+ case HexagonISD::SUBC: return "HexagonISD::SUBC";
case HexagonISD::ALLOCA: return "HexagonISD::ALLOCA";
case HexagonISD::AT_GOT: return "HexagonISD::AT_GOT";
case HexagonISD::AT_PCREL: return "HexagonISD::AT_PCREL";
@@ -2706,6 +2713,24 @@ HexagonTargetLowering::LowerUnalignedLoad(SDValue Op, SelectionDAG &DAG)
}
SDValue
+HexagonTargetLowering::LowerAddSubCarry(SDValue Op, SelectionDAG &DAG) const {
+ const SDLoc &dl(Op);
+ unsigned Opc = Op.getOpcode();
+ SDValue X = Op.getOperand(0), Y = Op.getOperand(1), C = Op.getOperand(2);
+
+ if (Opc == ISD::ADDCARRY)
+ return DAG.getNode(HexagonISD::ADDC, dl, Op.getNode()->getVTList(),
+ { X, Y, C });
+
+ EVT CarryTy = C.getValueType();
+ SDValue SubC = DAG.getNode(HexagonISD::SUBC, dl, Op.getNode()->getVTList(),
+ { X, Y, DAG.getLogicalNOT(dl, C, CarryTy) });
+ SDValue Out[] = { SubC.getValue(0),
+ DAG.getLogicalNOT(dl, SubC.getValue(1), CarryTy) };
+ return DAG.getMergeValues(Out, dl);
+}
+
+SDValue
HexagonTargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = Op.getOperand(0);
SDValue Offset = Op.getOperand(1);
@@ -2763,6 +2788,8 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
case ISD::BITCAST: return LowerBITCAST(Op, DAG);
case ISD::LOAD: return LowerUnalignedLoad(Op, DAG);
+ case ISD::ADDCARRY:
+ case ISD::SUBCARRY: return LowerAddSubCarry(Op, DAG);
case ISD::SRA:
case ISD::SHL:
case ISD::SRL: return LowerVECTOR_SHIFT(Op, DAG);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
index 5ed26101d58..cb570b4dc7f 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
@@ -36,6 +36,8 @@ namespace HexagonISD {
CONST32 = OP_BEGIN,
CONST32_GP, // For marking data present in GP.
+ ADDC, // Add with carry: (X, Y, Cin) -> (X+Y, Cout).
+ SUBC, // Sub with carry: (X, Y, Cin) -> (X+~Y+Cin, Cout).
ALLOCA,
AT_GOT, // Index in GOT.
@@ -162,6 +164,7 @@ namespace HexagonISD {
SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerZERO_EXTEND(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerUnalignedLoad(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerAddSubCarry(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;
OpenPOWER on IntegriCloud