aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h22
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp46
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp57
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp6
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp75
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td22
-rw-r--r--lib/Target/Sparc/SparcISelDAGToDAG.cpp35
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.td24
-rw-r--r--lib/Target/TargetSelectionDAG.td9
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp30
-rw-r--r--lib/Target/X86/X86ISelLowering.h10
-rw-r--r--lib/Target/X86/X86InstrInfo.td65
12 files changed, 130 insertions, 271 deletions
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 1eeb7b31e5..fe75a202d7 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -118,6 +118,21 @@ namespace ISD {
// Simple integer binary arithmetic operators.
ADD, SUB, MUL, SDIV, UDIV, SREM, UREM,
+ // Carry-setting nodes for multiple precision addition and subtraction.
+ // These nodes take two operands of the same value type, and produce two
+ // results. The first result is the normal add or sub result, the second
+ // result is the carry flag result.
+ ADDC, SUBC,
+
+ // Carry-using nodes for multiple precision addition and subtraction. These
+ // nodes take three operands: The first two are the normal lhs and rhs to
+ // the add or sub, and the third is the input carry flag. These nodes
+ // produce two results; the normal result of the add or sub, and the output
+ // carry flag. These nodes both read and write a carry flag to allow them
+ // to them to be chained together for add and sub of arbitrarily large
+ // values.
+ ADDE, SUBE,
+
// Simple binary floating point operators.
FADD, FSUB, FMUL, FDIV, FREM,
@@ -156,13 +171,6 @@ namespace ISD {
// (op #2) as a CondCodeSDNode.
SETCC,
- // ADD_PARTS/SUB_PARTS - These operators take two logical operands which are
- // broken into a multiple pieces each, and return the resulting pieces of
- // doing an atomic add/sub operation. This is used to handle add/sub of
- // expanded types. The operation ordering is:
- // [Lo,Hi] = op [LoLHS,HiLHS], [LoRHS,HiRHS]
- ADD_PARTS, SUB_PARTS,
-
// SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded
// integer shift operations, just like ADD/SUB_PARTS. The operation
// ordering is:
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index e40be3e3ca..48bb2024e4 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -157,14 +157,11 @@ namespace {
SDOperand visitSELECT(SDNode *N);
SDOperand visitSELECT_CC(SDNode *N);
SDOperand visitSETCC(SDNode *N);
- SDOperand visitADD_PARTS(SDNode *N);
- SDOperand visitSUB_PARTS(SDNode *N);
SDOperand visitSIGN_EXTEND(SDNode *N);
SDOperand visitZERO_EXTEND(SDNode *N);
SDOperand visitSIGN_EXTEND_INREG(SDNode *N);
SDOperand visitTRUNCATE(SDNode *N);
SDOperand visitBIT_CONVERT(SDNode *N);
-
SDOperand visitFADD(SDNode *N);
SDOperand visitFSUB(SDNode *N);
SDOperand visitFMUL(SDNode *N);
@@ -183,7 +180,6 @@ namespace {
SDOperand visitBRCONDTWOWAY(SDNode *N);
SDOperand visitBR_CC(SDNode *N);
SDOperand visitBRTWOWAY_CC(SDNode *N);
-
SDOperand visitLOAD(SDNode *N);
SDOperand visitSTORE(SDNode *N);
@@ -550,8 +546,6 @@ SDOperand DAGCombiner::visit(SDNode *N) {
case ISD::SELECT: return visitSELECT(N);
case ISD::SELECT_CC: return visitSELECT_CC(N);
case ISD::SETCC: return visitSETCC(N);
- case ISD::ADD_PARTS: return visitADD_PARTS(N);
- case ISD::SUB_PARTS: return visitSUB_PARTS(N);
case ISD::SIGN_EXTEND: return visitSIGN_EXTEND(N);
case ISD::ZERO_EXTEND: return visitZERO_EXTEND(N);
case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N);
@@ -1509,46 +1503,6 @@ SDOperand DAGCombiner::visitSETCC(SDNode *N) {
cast<CondCodeSDNode>(N->getOperand(2))->get());
}
-SDOperand DAGCombiner::visitADD_PARTS(SDNode *N) {
- SDOperand LHSLo = N->getOperand(0);
- SDOperand RHSLo = N->getOperand(2);
- MVT::ValueType VT = LHSLo.getValueType();
-
- // fold (a_Hi, 0) + (b_Hi, b_Lo) -> (b_Hi + a_Hi, b_Lo)
- if (TLI.MaskedValueIsZero(LHSLo, (1ULL << MVT::getSizeInBits(VT))-1)) {
- SDOperand Hi = DAG.getNode(ISD::ADD, VT, N->getOperand(1),
- N->getOperand(3));
- WorkList.push_back(Hi.Val);
- CombineTo(N, RHSLo, Hi);
- return SDOperand();
- }
- // fold (a_Hi, a_Lo) + (b_Hi, 0) -> (a_Hi + b_Hi, a_Lo)
- if (TLI.MaskedValueIsZero(RHSLo, (1ULL << MVT::getSizeInBits(VT))-1)) {
- SDOperand Hi = DAG.getNode(ISD::ADD, VT, N->getOperand(1),
- N->getOperand(3));
- WorkList.push_back(Hi.Val);
- CombineTo(N, LHSLo, Hi);
- return SDOperand();
- }
- return SDOperand();
-}
-
-SDOperand DAGCombiner::visitSUB_PARTS(SDNode *N) {
- SDOperand LHSLo = N->getOperand(0);
- SDOperand RHSLo = N->getOperand(2);
- MVT::ValueType VT = LHSLo.getValueType();
-
- // fold (a_Hi, a_Lo) - (b_Hi, 0) -> (a_Hi - b_Hi, a_Lo)
- if (TLI.MaskedValueIsZero(RHSLo, (1ULL << MVT::getSizeInBits(VT))-1)) {
- SDOperand Hi = DAG.getNode(ISD::SUB, VT, N->getOperand(1),
- N->getOperand(3));
- WorkList.push_back(Hi.Val);
- CombineTo(N, LHSLo, Hi);
- return SDOperand();
- }
- return SDOperand();
-}
-
SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
SDOperand N0 = N->getOperand(0);
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 70e97ab52e..5a45323c38 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -575,7 +575,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
break;
}
- break;
+ break;
case ISD::Constant:
// We know we don't need to expand constants here, constants only have one
@@ -1749,8 +1749,6 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
}
break;
- case ISD::ADD_PARTS:
- case ISD::SUB_PARTS:
case ISD::SHL_PARTS:
case ISD::SRA_PARTS:
case ISD::SRL_PARTS: {
@@ -1830,7 +1828,32 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break;
}
break;
+
+ case ISD::ADDC:
+ case ISD::SUBC:
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ Tmp2 = LegalizeOp(Node->getOperand(1));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+ // Since this produces two values, make sure to remember that we legalized
+ // both of them.
+ AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
+ AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
+ return Result;
+ break;
+ case ISD::ADDE:
+ case ISD::SUBE:
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ Tmp2 = LegalizeOp(Node->getOperand(1));
+ Tmp3 = LegalizeOp(Node->getOperand(2));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
+ // Since this produces two values, make sure to remember that we legalized
+ // both of them.
+ AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
+ AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
+ return Result;
+ break;
+
case ISD::BUILD_PAIR: {
MVT::ValueType PairTy = Node->getValueType(0);
// TODO: handle the case where the Lo and Hi operands are not of legal type
@@ -3980,17 +4003,23 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
SDOperand LHSL, LHSH, RHSL, RHSH;
ExpandOp(Node->getOperand(0), LHSL, LHSH);
ExpandOp(Node->getOperand(1), RHSL, RHSH);
-
- std::vector<SDOperand> Ops;
- Ops.push_back(LHSL);
- Ops.push_back(LHSH);
- Ops.push_back(RHSL);
- Ops.push_back(RHSH);
- std::vector<MVT::ValueType> VTs(2, LHSL.getValueType());
- unsigned Opc =
- Node->getOpcode() == ISD::ADD ? ISD::ADD_PARTS : ISD::SUB_PARTS;
- Lo = DAG.getNode(Opc, VTs, Ops);
- Hi = Lo.getValue(1);
+ std::vector<MVT::ValueType> VTs;
+ std::vector<SDOperand> LoOps, HiOps;
+ VTs.push_back(LHSL.getValueType());
+ VTs.push_back(MVT::Flag);
+ LoOps.push_back(LHSL);
+ LoOps.push_back(RHSL);
+ HiOps.push_back(LHSH);
+ HiOps.push_back(RHSH);
+ if (Node->getOpcode() == ISD::ADD) {
+ Lo = DAG.getNode(ISD::ADDC, VTs, LoOps);
+ HiOps.push_back(Lo.getValue(1));
+ Hi = DAG.getNode(ISD::ADDE, VTs, HiOps);
+ } else {
+ Lo = DAG.getNode(ISD::SUBC, VTs, LoOps);
+ HiOps.push_back(Lo.getValue(1));
+ Hi = DAG.getNode(ISD::SUBE, VTs, HiOps);
+ }
break;
}
case ISD::MUL: {
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 23d1dc34cc..5fc09671c6 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2552,8 +2552,10 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::SETCC: return "setcc";
case ISD::SELECT: return "select";
case ISD::SELECT_CC: return "select_cc";
- case ISD::ADD_PARTS: return "add_parts";
- case ISD::SUB_PARTS: return "sub_parts";
+ case ISD::ADDC: return "addc";
+ case ISD::ADDE: return "adde";
+ case ISD::SUBC: return "subc";
+ case ISD::SUBE: return "sube";
case ISD::SHL_PARTS: return "shl_parts";
case ISD::SRA_PARTS: return "sra_parts";
case ISD::SRL_PARTS: return "srl_parts";
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index b781ca5cd8..78dbaa64a3 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -535,75 +535,6 @@ static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool& Inv) {
return 0;
}
-
-SDOperand PPCDAGToDAGISel::SelectADD_PARTS(SDOperand Op) {
- SDNode *N = Op.Val;
- SDOperand LHSL, LHSH;
- Select(LHSL, N->getOperand(0));
- Select(LHSH, N->getOperand(1));
-
- unsigned Imm;
- bool ME = false, ZE = false;
- if (isIntImmediate(N->getOperand(3), Imm)) {
- ME = (signed)Imm == -1;
- ZE = Imm == 0;
- }
-
- std::vector<SDOperand> Result;
- SDOperand Tmp;
- SDNode *CarryFromLo;
- if (isIntImmediate(N->getOperand(2), Imm) &&
- ((signed)Imm >= -32768 || (signed)Imm < 32768)) {
- // Codegen the low 32 bits of the add. Interestingly, there is no
- // shifted form of add immediate carrying.
- CarryFromLo = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag,
- LHSL, getI32Imm(Imm));
- } else {
- Select(Tmp, N->getOperand(2));
- CarryFromLo = CurDAG->getTargetNode(PPC::ADDC, MVT::i32, MVT::Flag,
- LHSL, Tmp);
- }
-
- // Codegen the high 32 bits, adding zero, minus one, or the full value
- // along with the carry flag produced by addc/addic.
- SDOperand ResultHi;
- if (ZE)
- ResultHi = SDOperand(CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, LHSH,
- SDOperand(CarryFromLo, 1)), 0);
- else if (ME)
- ResultHi = SDOperand(CurDAG->getTargetNode(PPC::ADDME, MVT::i32, LHSH,
- SDOperand(CarryFromLo, 1)), 0);
- else {
- Select(Tmp, N->getOperand(3));
- ResultHi = SDOperand(CurDAG->getTargetNode(PPC::ADDE, MVT::i32, LHSH,
- Tmp, SDOperand(CarryFromLo, 1)), 0);
- }
- Result.push_back(SDOperand(CarryFromLo, 0));
- Result.push_back(ResultHi);
-
- CodeGenMap[Op.getValue(0)] = Result[0];
- CodeGenMap[Op.getValue(1)] = Result[1];
- return Result[Op.ResNo];
-}
-SDOperand PPCDAGToDAGISel::SelectSUB_PARTS(SDOperand Op) {
- SDNode *N = Op.Val;
- SDOperand LHSL, LHSH, RHSL, RHSH;
- Select(LHSL, N->getOperand(0));
- Select(LHSH, N->getOperand(1));
- Select(RHSL, N->getOperand(2));
- Select(RHSH, N->getOperand(3));
-
- std::vector<SDOperand> Result;
- Result.push_back(SDOperand(CurDAG->getTargetNode(PPC::SUBFC, MVT::i32,
- MVT::Flag, RHSL, LHSL), 0));
- Result.push_back(SDOperand(CurDAG->getTargetNode(PPC::SUBFE, MVT::i32,
- RHSH, LHSH,
- Result[0].getValue(1)), 0));
- CodeGenMap[Op.getValue(0)] = Result[0];
- CodeGenMap[Op.getValue(1)] = Result[1];
- return Result[Op.ResNo];
-}
-
SDOperand PPCDAGToDAGISel::SelectSETCC(SDOperand Op) {
SDNode *N = Op.Val;
unsigned Imm;
@@ -846,12 +777,6 @@ void PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
switch (N->getOpcode()) {
default: break;
- case ISD::ADD_PARTS:
- Result = SelectADD_PARTS(Op);
- return;
- case ISD::SUB_PARTS:
- Result = SelectSUB_PARTS(Op);
- return;
case ISD::SETCC:
Result = SelectSETCC(Op);
return;
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 7c184ab4bc..30f4e9bd2f 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -302,7 +302,7 @@ def ADDI : DForm_2<14, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
[(set GPRC:$rD, (add GPRC:$rA, immSExt16:$imm))]>;
def ADDIC : DForm_2<12, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"addic $rD, $rA, $imm", IntGeneral,
- []>;
+ [(set GPRC:$rD, (addc GPRC:$rA, immSExt16:$imm))]>;
def ADDICo : DForm_2<13, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"addic. $rD, $rA, $imm", IntGeneral,
[]>;
@@ -684,10 +684,10 @@ def ADD8 : XOForm_1<31, 266, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
[(set G8RC:$rT, (add G8RC:$rA, G8RC:$rB))]>;
def ADDC : XOForm_1<31, 10, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"addc $rT, $rA, $rB", IntGeneral,
- []>;
+ [(set GPRC:$rT, (addc GPRC:$rA, GPRC:$rB))]>;
def ADDE : XOForm_1<31, 138, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"adde $rT, $rA, $rB", IntGeneral,
- []>;
+ [(set GPRC:$rT, (adde GPRC:$rA, GPRC:$rB))]>;
def DIVD : XOForm_1<31, 489, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"divd $rT, $rA, $rB", IntDivD,
[(set G8RC:$rT, (sdiv G8RC:$rA, G8RC:$rB))]>, isPPC64;
@@ -723,22 +723,25 @@ def SUBF : XOForm_1<31, 40, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
[(set GPRC:$rT, (sub GPRC:$rB, GPRC:$rA))]>;
def SUBFC : XOForm_1<31, 8, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"subfc $rT, $rA, $rB", IntGeneral,
- []>;
+ [(set GPRC:$rT, (subc GPRC:$rB, GPRC:$rA))]>;
def SUBFE : XOForm_1<31, 136, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"subfe $rT, $rA, $rB", IntGeneral,
- []>;
+ [(set GPRC:$rT, (sube GPRC:$rB, GPRC:$rA))]>;
def ADDME : XOForm_3<31, 234, 0, (ops GPRC:$rT, GPRC:$rA),
"addme $rT, $rA", IntGeneral,
- []>;
+ [(set GPRC:$rT, (adde GPRC:$rA, immAllOnes))]>;
def ADDZE : XOForm_3<31, 202, 0, (ops GPRC:$rT, GPRC:$rA),
"addze $rT, $rA", IntGeneral,
- []>;
+ [(set GPRC:$rT, (adde GPRC:$rA, 0))]>;
def NEG : XOForm_3<31, 104, 0, (ops GPRC:$rT, GPRC:$rA),
"neg $rT, $rA", IntGeneral,
[(set GPRC:$rT, (ineg GPRC:$rA))]>;
+def SUBFME : XOForm_3<31, 232, 0, (ops GPRC:$rT, GPRC:$rA),
+ "subfme $rT, $rA", IntGeneral,
+ [(set GPRC:$rT, (sube immAllOnes, GPRC:$rA))]>;
def SUBFZE : XOForm_3<31, 200, 0, (ops GPRC:$rT, GPRC:$rA),
"subfze $rT, $rA", IntGeneral,
- []>;
+ [(set GPRC:$rT, (sube 0, GPRC:$rA))]>;
// A-Form instructions. Most of the instructions executed in the FPU are of
// this type.
@@ -983,6 +986,9 @@ def : Pat<(or GPRC:$in, imm:$imm),
// XOR an arbitrary immediate.
def : Pat<(xor GPRC:$in, imm:$imm),
(XORIS (XORI GPRC:$in, (LO16 imm:$imm)), (HI16 imm:$imm))>;
+// SUBFIC
+def : Pat<(subc immSExt16:$imm, GPRC:$in),
+ (SUBFIC GPRC:$in, imm:$imm)>;
// Return void support.
def : Pat<(ret), (BLR)>;
diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index d80c0064f3..e66e713cda 100644
--- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -1075,41 +1075,6 @@ void SparcDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
switch (N->getOpcode()) {
default: break;
- case ISD::ADD_PARTS: {
- SDOperand LHSL, LHSH, RHSL, RHSH;
- Select(LHSL, N->getOperand(0));
- Select(LHSH, N->getOperand(1));
- Select(RHSL, N->getOperand(2));
- Select(RHSH, N->getOperand(3));
- // FIXME, handle immediate RHS.
- SDOperand Low =
- SDOperand(CurDAG->getTargetNode(SP::ADDCCrr, MVT::i32, MVT::Flag,
- LHSL, RHSL), 0);
- SDOperand Hi =
- SDOperand(CurDAG->getTargetNode(SP::ADDXrr, MVT::i32, LHSH, RHSH,
- Low.getValue(1)), 0);
- CodeGenMap[SDOperand(N, 0)] = Low;
- CodeGenMap[SDOperand(N, 1)] = Hi;
- Result = Op.ResNo ? Hi : Low;
- return;
- }
- case ISD::SUB_PARTS: {
- SDOperand LHSL, LHSH, RHSL, RHSH;
- Select(LHSL, N->getOperand(0));
- Select(LHSH, N->getOperand(1));
- Select(RHSL, N->getOperand(2));
- Select(RHSH, N->getOperand(3));
- SDOperand Low =
- SDOperand(CurDAG->getTargetNode(SP::SUBCCrr, MVT::i32, MVT::Flag,
- LHSL, RHSL), 0);
- SDOperand Hi =
- SDOperand(CurDAG->getTargetNode(SP::SUBXrr, MVT::i32, LHSH, RHSH,
- Low.getValue(1)), 0);
- CodeGenMap[SDOperand(N, 0)] = Low;
- CodeGenMap[SDOperand(N, 1)] = Hi;
- Result = Op.ResNo ? Hi : Low;
- return;
- }
case ISD::SDIV:
case ISD::UDIV: {
// FIXME: should use a custom expander to expose the SRA to the dag.
diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td
index 6a1b01255a..3d610635cc 100644
--- a/lib/Target/Sparc/SparcInstrInfo.td
+++ b/lib/Target/Sparc/SparcInstrInfo.td
@@ -453,16 +453,20 @@ def LEA_ADDri : F3_2<2, 0b000000,
def ADDCCrr : F3_1<2, 0b010000,
(ops IntRegs:$dst, IntRegs:$b, IntRegs:$c),
- "addcc $b, $c, $dst", []>;
+ "addcc $b, $c, $dst",
+ [(set IntRegs:$dst, (addc IntRegs:$b, IntRegs:$c))]>;
def ADDCCri : F3_2<2, 0b010000,
(ops IntRegs:$dst, IntRegs:$b, i32imm:$c),
- "addcc $b, $c, $dst", []>;
+ "addcc $b, $c, $dst",
+ [(set IntRegs:$dst, (addc IntRegs:$b, simm13:$c))]>;
def ADDXrr : F3_1<2, 0b001000,
(ops IntRegs:$dst, IntRegs:$b, IntRegs:$c),
- "addx $b, $c, $dst", []>;
+ "addx $b, $c, $dst",
+ [(set IntRegs:$dst, (adde IntRegs:$b, IntRegs:$c))]>;
def ADDXri : F3_2<2, 0b001000,
(ops IntRegs:$dst, IntRegs:$b, i32imm:$c),
- "addx $b, $c, $dst", []>;
+ "addx $b, $c, $dst",
+ [(set IntRegs:$dst, (adde IntRegs:$b, simm13:$c))]>;
// Section B.15 - Subtract Instructions, p. 110
def SUBrr : F3_1<2, 0b000100,
@@ -475,10 +479,12 @@ def SUBri : F3_2<2, 0b000100,
[(set IntRegs:$dst, (sub IntRegs:$b, simm13:$c))]>;
def SUBXrr : F3_1<2, 0b001100,
(ops IntRegs:$dst, IntRegs:$b, IntRegs:$c),
- "subx $b, $c, $dst", []>;
+ "subx $b, $c, $dst",
+ [(set IntRegs:$dst, (sube IntRegs:$b, IntRegs:$c))]>;
def SUBXri : F3_2<2, 0b001100,
(ops IntRegs:$dst, IntRegs:$b, i32imm:$c),
- "subx $b, $c, $dst", []>;
+ "subx $b, $c, $dst",
+ [(set IntRegs:$dst, (sube IntRegs:$b, simm13:$c))]>;
def SUBCCrr : F3_1<2, 0b010100,
(ops IntRegs:$dst, IntRegs:$b, IntRegs:$c),
"subcc $b, $c, $dst",
@@ -866,6 +872,12 @@ def : Pat<(i32 simm13:$val),
def : Pat<(i32 imm:$val),
(ORri (SETHIi (HI22 imm:$val)), (LO10 imm:$val))>;
+// subc
+def : Pat<(subc IntRegs:$b, IntRegs:$c),
+ (SUBCCrr IntRegs:$b, IntRegs:$c)>;
+def : Pat<(subc IntRegs:$b, simm13:$val),
+ (SUBCCri IntRegs:$b, imm:$val)>;
+
// Global addresses, constant pool entries
def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>;
def : Pat<(SPlo tglobaladdr:$in), (ORri G0, tglobaladdr:$in)>;
diff --git a/lib/Target/TargetSelectionDAG.td b/lib/Target/TargetSelectionDAG.td
index 03c3e69b63..ab9430e7a3 100644
--- a/lib/Target/TargetSelectionDAG.td
+++ b/lib/Target/TargetSelectionDAG.td
@@ -238,6 +238,14 @@ def or : SDNode<"ISD::OR" , SDTIntBinOp,
[SDNPCommutative, SDNPAssociative]>;
def xor : SDNode<"ISD::XOR" , SDTIntBinOp,
[SDNPCommutative, SDNPAssociative]>;
+def addc : SDNode<"ISD::ADDC" , SDTIntBinOp,
+ [SDNPCommutative, SDNPOutFlag]>;
+def adde : SDNode<"ISD::ADDE" , SDTIntBinOp,
+ [SDNPCommutative, SDNPOutFlag, SDNPInFlag]>;
+def subc : SDNode<"ISD::SUBC" , SDTIntBinOp,
+ [SDNPOutFlag]>;
+def sube : SDNode<"ISD::SUBE" , SDTIntBinOp,
+ [SDNPOutFlag, SDNPInFlag]>;
def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>;
def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>;
@@ -346,7 +354,6 @@ class PatLeaf<dag frag, code pred = [{}], SDNodeXForm xform = NOOP_SDNodeXForm>
// Leaf fragments.
def immAllOnes : PatLeaf<(imm), [{ return N->isAllOnesValue(); }]>;
-def immZero : PatLeaf<(imm), [{ return N->isNullValue(); }]>;
def vtInt : PatLeaf<(vt), [{ return MVT::isInteger(N->getVT()); }]>;
def vtFP : PatLeaf<(vt), [{ return MVT::isFloatingPoint(N->getVT()); }]>;
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 32c2a1fe81..ed82adbe3d 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -160,8 +160,6 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
// Darwin ABI issue.
setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom);
// 64-bit addm sub, shl, sra, srl (iff 32-bit x86)
- setOperationAction(ISD::ADD_PARTS , MVT::i32 , Custom);
- setOperationAction(ISD::SUB_PARTS , MVT::i32 , Custom);
setOperationAction(ISD::SHL_PARTS , MVT::i32 , Custom);
setOperationAction(ISD::SRA_PARTS , MVT::i32 , Custom);
setOperationAction(ISD::SRL_PARTS , MVT::i32 , Custom);
@@ -1270,30 +1268,6 @@ X86TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) {
default: assert(0 && "Should not custom lower this!");
- case ISD::ADD_PARTS:
- case ISD::SUB_PARTS: {
- assert(Op.getNumOperands() == 4 && Op.getValueType() == MVT::i32 &&
- "Not an i64 add/sub!");
- bool isAdd = Op.getOpcode() == ISD::ADD_PARTS;
- std::vector<MVT::ValueType> Tys;
- Tys.push_back(MVT::i32);
- Tys.push_back(MVT::Flag);
- std::vector<SDOperand> Ops;
- Ops.push_back(Op.getOperand(0));
- Ops.push_back(Op.getOperand(2));
- SDOperand Lo = DAG.getNode(isAdd ? X86ISD::ADD_FLAG : X86ISD::SUB_FLAG,
- Tys, Ops);
- SDOperand Hi = DAG.getNode(isAdd ? X86ISD::ADC : X86ISD::SBB, MVT::i32,
- Op.getOperand(1), Op.getOperand(3),
- Lo.getValue(1));
- Tys.clear();
- Tys.push_back(MVT::i32);
- Tys.push_back(MVT::i32);
- Ops.clear();
- Ops.push_back(Lo);
- Ops.push_back(Hi);
- return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
- }
case ISD::SHL_PARTS:
case ISD::SRA_PARTS:
case ISD::SRL_PARTS: {
@@ -1910,10 +1884,6 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
default: return NULL;
- case X86ISD::ADD_FLAG: return "X86ISD::ADD_FLAG";
- case X86ISD::SUB_FLAG: return "X86ISD::SUB_FLAG";
- case X86ISD::ADC: return "X86ISD::ADC";
- case X86ISD::SBB: return "X86ISD::SBB";
case X86ISD::SHLD: return "X86ISD::SHLD";
case X86ISD::SHRD: return "X86ISD::SHRD";
case X86ISD::FAND: return "X86ISD::FAND";
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index dc1a13c79f..2aa365959a 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -26,16 +26,6 @@ namespace llvm {
// Start the numbering where the builtin ops leave off.
FIRST_NUMBER = ISD::BUILTIN_OP_END+X86::INSTRUCTION_LIST_END,
- /// ADD_FLAG, SUB_FLAG - Same as ISD::ADD and ISD::SUB except it also
- /// produces a flag result.
- ADD_FLAG,
- SUB_FLAG,
-
- /// ADC, SBB - Add with carry and subtraction with borrow. These
- /// correspond to X86::ADCxx and X86::SBBxx instructions.
- ADC,
- SBB,
-
/// SHLD, SHRD - Double shift instructions. These correspond to
/// X86::SHLDxx and X86::SHRDxx instructions.
SHLD,
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index c6b1ff55e5..d1c58d7127 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -56,15 +56,6 @@ def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>;
def SDTX86RdTsc : SDTypeProfile<0, 0, []>;
-def X86addflag : SDNode<"X86ISD::ADD_FLAG", SDTIntBinOp ,
- [SDNPCommutative, SDNPAssociative, SDNPOutFlag]>;
-def X86subflag : SDNode<"X86ISD::SUB_FLAG", SDTIntBinOp,
- [SDNPOutFlag]>;
-def X86adc : SDNode<"X86ISD::ADC" , SDTIntBinOp ,
- [SDNPCommutative, SDNPAssociative, SDNPInFlag]>;
-def X86sbb : SDNode<"X86ISD::SBB" , SDTIntBinOp,
- [SDNPInFlag]>;
-
def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>;
def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>;
@@ -1873,28 +1864,28 @@ let isTwoAddress = 0 in {
let isCommutable = 1 in { // X = ADC Y, Z --> X = ADC Z, Y
def ADC32rr : I<0x11, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
"adc{l} {$src2, $dst|$dst, $src2}",
- [(set R32:$dst, (X86adc R32:$src1, R32:$src2))]>;
+ [(set R32:$dst, (adde R32:$src1, R32:$src2))]>;
}
def ADC32rm : I<0x13, MRMSrcMem , (ops R32:$dst, R32:$src1, i32mem:$src2),
"adc{l} {$src2, $dst|$dst, $src2}",
- [(set R32:$dst, (X86adc R32:$src1, (load addr:$src2)))]>;
+ [(set R32:$dst, (adde R32:$src1, (load addr:$src2)))]>;
def ADC32ri : Ii32<0x81, MRM2r, (ops R32:$dst, R32:$src1, i32imm:$src2),
"adc{l} {$src2, $dst|$dst, $src2}",
- [(set R32:$dst, (X86adc R32:$src1, imm:$src2))]>;
+ [(set R32:$dst, (adde R32:$src1, imm:$src2))]>;
def ADC32ri8 : Ii8<0x83, MRM2r, (ops R32:$dst, R32:$src1, i32i8imm:$src2),
"adc{l} {$src2, $dst|$dst, $src2}",
- [(set R32:$dst, (X86adc R32:$src1, i32immSExt8:$src2))]>;
+ [(set R32:$dst, (adde R32:$src1, i32immSExt8:$src2))]>;
let isTwoAddress = 0 in {
def ADC32mr : I<0x11, MRMDestMem, (ops i32mem:$dst, R32:$src2),
"adc{l} {$src2, $dst|$dst, $src2}",
- [(store (X86adc (load addr:$dst), R32:$src2), addr:$dst)]>;
+ [(store (adde (load addr:$dst), R32:$src2), addr:$dst)]>;
def ADC32mi : Ii32<0x81, MRM2m, (ops i32mem:$dst, i32imm:$src2),
"adc{l} {$src2, $dst|$dst, $src2}",
- [(store (X86adc (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
+ [(store (adde (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
def ADC32mi8 : Ii8<0x83, MRM2m, (ops i32mem:$dst, i32i8imm :$src2),
"adc{l} {$src2, $dst|$dst, $src2}",
- [(store (X86adc (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
+ [(store (adde (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
}
def SUB8rr : I<0x28, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2),
@@ -1964,51 +1955,51 @@ let isTwoAddress = 0 in {
def SBB32rr : I<0x19, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
"sbb{l} {$src2, $dst|$dst, $src2}",
- [(set R32:$dst, (X86sbb R32:$src1, R32:$src2))]>;
+ [(set R32:$dst, (sube R32:$src1, R32:$src2))]>;
let isTwoAddress = 0 in {
def SBB32mr : I<0x19, MRMDestMem, (ops i32mem:$dst, R32:$src2),
"sbb{l} {$src2, $dst|$dst, $src2}",
- [(store (X86sbb (load addr:$dst), R32:$src2), addr:$dst)]>;
+ [(store (sube (load addr:$dst), R32:$src2), addr:$dst)]>;
def SBB8mi : Ii32<0x80, MRM3m, (ops i8mem:$dst, i8imm:$src2),
"sbb{b} {$src2, $dst|$dst, $src2}",
- [(store (X86sbb (loadi8 addr:$dst), imm:$src2), addr:$dst)]>;
+ [(store (sube (loadi8 addr:$dst), imm:$src2), addr:$dst)]>;
def SBB16mi : Ii32<0x81, MRM3m, (ops i16mem:$dst, i16imm:$src2),
"sbb{w} {$src2, $dst|$dst, $src2}",
- [(store (X86sbb (loadi16 addr:$dst), imm:$src2), addr:$dst)]>,
+ [(store (sube (loadi16 addr:$dst), imm:$src2), addr:$dst)]>,
OpSize;
def SBB32mi : Ii32<0x81, MRM3m, (ops i32mem:$dst, i32imm:$src2),
"sbb{l} {$src2, $dst|$dst, $src2}",
- [(store (X86sbb (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
+ [(store (sube (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
def SBB16mi8 : Ii8<0x83, MRM3m, (ops i16mem:$dst, i16i8imm :$src2),
"sbb{w} {$src2, $dst|$dst, $src2}",
- [(store (X86sbb (load addr:$dst), i16immSExt8:$src2), addr:$dst)]>,
+ [(store (sube (load addr:$dst), i16immSExt8:$src2), addr:$dst)]>,
OpSize;
def SBB32mi8 : Ii8<0x83, MRM3m, (ops i32mem:$dst, i32i8imm :$src2),
"sbb{l} {$src2, $dst|$dst, $src2}",
- [(store (X86sbb (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
+ [(store (sube (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
}
def SBB8ri : Ii8<0x80, MRM3r, (ops R8:$dst, R8:$src1, i8imm:$src2),
"sbb{b} {$src2, $dst|$dst, $src2}",
- [(set R8:$dst, (X86sbb R8:$src1, imm:$src2))]>;
+ [(set R8:$dst, (sube R8:$src1, imm:$src2))]>;
def SBB16ri : Ii16<0x81, MRM3r, (ops R16:$dst, R16:$src1, i16imm:$src2),
"sbb{w} {$src2, $dst|$dst, $src2}",
- [(set R16:$dst, (X86sbb R16:$src1, imm:$src2))]>, OpSize;
+ [(set R16:$dst, (sube R16:$src1, imm:$src2))]>, OpSize;
def SBB32rm : I<0x1B, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
"sbb{l} {$src2, $dst|$dst, $src2}",
- [(set R32:$dst, (X86sbb R32:$src1, (load addr:$src2)))]>;
+ [(set R32:$dst, (sube R32:$src1, (load addr:$src2)))]>;
def SBB32ri : Ii32<0x81, MRM3r, (ops R32:$dst, R32:$src1, i32imm:$src2),
"sbb{l} {$src2, $dst|$dst, $src2}",
- [(set R32:$dst, (X86sbb R32:$src1, imm:$src2))]>;
+ [(set R32:$dst, (sube R32:$src1, imm:$src2))]>;
def SBB16ri8 : Ii8<0x83, MRM3r, (ops R16:$dst, R16:$src1, i16i8imm:$src2),
"sbb{w} {$src2, $dst|$dst, $src2}",
- [(set R16:$dst, (X86sbb R16:$src1, i16immSExt8:$src2))]>,
+ [(set R16:$dst, (sube R16:$src1, i16immSExt8:$src2))]>,
OpSize;
def SBB32ri8 : Ii8<0x83, MRM3r, (ops R32:$dst, R32:$src1, i32i8imm:$src2),
"sbb{l} {$src2, $dst|$dst, $src2}",
- [(set R32:$dst, (X86sbb R32:$src1, i32immSExt8:$src2))]>;
+ [(set R32:$dst, (sube R32:$src1, i32immSExt8:$src2))]>;
let isCommutable = 1 in { // X = IMUL Y, Z --> X = IMUL Z, Y
def IMUL16rr : I<0xAF, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
@@ -3077,22 +3068,22 @@ def : Pat<(X86call texternalsym:$dst),
(CALLpcrel32 texternalsym:$dst)>;
// X86 specific add which produces a flag.
-def : Pat<(X86addflag R32:$src1, R32:$src2),
+def : Pat<(addc R32:$src1, R32:$src2),
(ADD32rr R32:$src1, R32:$src2)>;
-def : Pat<(X86addflag R32:$src1, (load addr:$src2)),
+def : Pat<(addc R32:$src1, (load addr:$src2)),
(ADD32rm R32:$src1, addr:$src2)>;
-def : Pat<(X86addflag R32:$src1, imm:$src2),
+def : Pat<(addc R32:$src1, imm:$src2),
(ADD32ri R32:$src1, imm:$src2)>;
-def : Pat<(X86addflag R32:$src1, i32immSExt8:$src2),
+def : Pat<(addc R32:$src1, i32immSExt8:$src2),
(ADD32ri8 R32:$src1, i32immSExt8:$src2)>;
-def : Pat<(X86subflag R32:$src1, R32:$src2),
+def : Pat<(subc R32:$src1, R32:$src2),
(SUB32rr R32:$src1, R32:$src2)>;
-def : Pat<(X86subflag R32:$src1, (load addr:$src2)),
+def : Pat<(subc R32:$src1, (load addr:$src2)),
(SUB32rm R32:$src1, addr:$src2)>;
-def : Pat<(X86subflag R32:$src1, imm:$src2),
+def : Pat<(subc R32:$src1, imm:$src2),
(SUB32ri R32:$src1, imm:$src2)>;
-def : Pat<(X86subflag R32:$src1, i32immSExt8:$src2),
+def : Pat<(subc R32:$src1, i32immSExt8:$src2),
(SUB32ri8 R32:$src1, i32immSExt8:$src2)>;
def : Pat<(truncstore (i8 imm:$src), addr:$dst, i1),