forked from OSchip/llvm-project
kill ADD_PARTS & SUB_PARTS and replace them with fancy new ADDC, ADDE, SUBC
and SUBE nodes that actually expose what's going on and allow for significant simplifications in the targets. llvm-svn: 26255
This commit is contained in:
parent
9ec392b2aa
commit
5965bd19f8
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: {
|
||||
|
@ -1831,6 +1829,31 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||
}
|
||||
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: {
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)>;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)>;
|
||||
|
|
|
@ -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()); }]>;
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue