mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-28 06:24:57 +00:00
Make the implicit inputs and outputs of target-independent
ADDC/ADDE use MVT::i1 (later, whatever it gets legalized to) instead of MVT::Flag. Remove CARRY_FALSE in favor of 0; adjust all target-independent code to use this format. Most targets will still produce a Flag-setting target-dependent version when selection is done. X86 is converted to use i32 instead, which means TableGen needs to produce different code in xxxGenDAGISel.inc. This keys off the new supportsHasI1 bit in xxxInstrInfo, currently set only for X86; in principle this is temporary and should go away when all other targets have been converted. All relevant X86 instruction patterns are modified to represent setting and using EFLAGS explicitly. The same can be done on other targets. The immediate behavior change is that an ADC/ADD pair are no longer tightly coupled in the X86 scheduler; they can be separated by instructions that don't clobber the flags (MOV). I will soon add some peephole optimizations based on using other instructions that set the flags to feed into ADC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72707 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -1085,8 +1085,7 @@ SDValue DAGCombiner::visitADDC(SDNode *N) {
|
||||
// If the flag result is dead, turn this into an ADD.
|
||||
if (N->hasNUsesOfValue(0, 1))
|
||||
return CombineTo(N, DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N1, N0),
|
||||
DAG.getNode(ISD::CARRY_FALSE,
|
||||
N->getDebugLoc(), MVT::Flag));
|
||||
DAG.getConstant(0, N->getValueType(1)));
|
||||
|
||||
// canonicalize constant to RHS.
|
||||
if (N0C && !N1C)
|
||||
@ -1094,10 +1093,9 @@ SDValue DAGCombiner::visitADDC(SDNode *N) {
|
||||
|
||||
// fold (addc x, 0) -> x + no carry out
|
||||
if (N1C && N1C->isNullValue())
|
||||
return CombineTo(N, N0, DAG.getNode(ISD::CARRY_FALSE,
|
||||
N->getDebugLoc(), MVT::Flag));
|
||||
return CombineTo(N, N0, DAG.getConstant(0, N1.getValueType()));
|
||||
|
||||
// fold (addc a, b) -> (or a, b), CARRY_FALSE iff a and b share no bits.
|
||||
// fold (addc a, b) -> (or a, b), 0 iff a and b share no bits.
|
||||
APInt LHSZero, LHSOne;
|
||||
APInt RHSZero, RHSOne;
|
||||
APInt Mask = APInt::getAllOnesValue(VT.getSizeInBits());
|
||||
@ -1111,8 +1109,7 @@ SDValue DAGCombiner::visitADDC(SDNode *N) {
|
||||
if ((RHSZero & (~LHSZero & Mask)) == (~LHSZero & Mask) ||
|
||||
(LHSZero & (~RHSZero & Mask)) == (~RHSZero & Mask))
|
||||
return CombineTo(N, DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N1),
|
||||
DAG.getNode(ISD::CARRY_FALSE,
|
||||
N->getDebugLoc(), MVT::Flag));
|
||||
DAG.getConstant(0, N1.getValueType()));
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
@ -1131,8 +1128,9 @@ SDValue DAGCombiner::visitADDE(SDNode *N) {
|
||||
N1, N0, CarryIn);
|
||||
|
||||
// fold (adde x, y, false) -> (addc x, y)
|
||||
if (CarryIn.getOpcode() == ISD::CARRY_FALSE)
|
||||
return DAG.getNode(ISD::ADDC, N->getDebugLoc(), N->getVTList(), N1, N0);
|
||||
if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(CarryIn))
|
||||
if (N2C->getAPIntValue()==0)
|
||||
return DAG.getNode(ISD::ADDC, N->getDebugLoc(), N->getVTList(), N1, N0);
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
@ -98,6 +98,10 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
|
||||
case ISD::USUBO: Res = PromoteIntRes_UADDSUBO(N, ResNo); break;
|
||||
case ISD::SMULO:
|
||||
case ISD::UMULO: Res = PromoteIntRes_XMULO(N, ResNo); break;
|
||||
case ISD::ADDC:
|
||||
case ISD::SUBC: Res = PromoteIntRes_ADDSUBC(N, ResNo); break;
|
||||
case ISD::ADDE:
|
||||
case ISD::SUBE: Res = PromoteIntRes_ADDSUBE(N, ResNo); break;
|
||||
|
||||
case ISD::ATOMIC_LOAD_ADD:
|
||||
case ISD::ATOMIC_LOAD_SUB:
|
||||
@ -121,6 +125,35 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
|
||||
SetPromotedInteger(SDValue(N, ResNo), Res);
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntRes_ADDSUBC(SDNode *N, unsigned ResNo) {
|
||||
// Only the carry bit result is expected to be promoted.
|
||||
assert(ResNo == 1 && "Only carry bit result promotion currently supported!");
|
||||
return PromoteIntRes_Overflow(N);
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntRes_ADDSUBE(SDNode *N, unsigned ResNo) {
|
||||
// Only the carry bit result is expected to be promoted.
|
||||
assert(ResNo == 1 && "Only carry bit result promotion currently supported!");
|
||||
// This is a ternary operator, so clone a slightly modified
|
||||
// PromoteIntRes_Overflow here (this is the only client).
|
||||
if (ResNo == 1) {
|
||||
// Simply change the return type of the boolean result.
|
||||
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(1));
|
||||
MVT ValueVTs[] = { N->getValueType(0), NVT };
|
||||
SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) };
|
||||
SDValue Res = DAG.getNode(N->getOpcode(), N->getDebugLoc(),
|
||||
DAG.getVTList(ValueVTs, 2), Ops, 3);
|
||||
|
||||
// Modified the sum result - switch anything that used the old sum to use
|
||||
// the new one.
|
||||
ReplaceValueWith(SDValue(N, 0), Res);
|
||||
|
||||
return SDValue(Res.getNode(), 1);
|
||||
}
|
||||
assert(0 && "Do not know how to promote this operator!");
|
||||
abort();
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntRes_AssertSext(SDNode *N) {
|
||||
// Sign-extend the new bits, and continue the assertion.
|
||||
SDValue Op = SExtPromotedInteger(N->getOperand(0));
|
||||
@ -419,7 +452,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) {
|
||||
return Res;
|
||||
}
|
||||
|
||||
/// Promote the overflow flag of an overflowing arithmetic node.
|
||||
/// Promote the overflow or carry result of an overflowing arithmetic node.
|
||||
SDValue DAGTypeLegalizer::PromoteIntRes_Overflow(SDNode *N) {
|
||||
// Simply change the return type of the boolean result.
|
||||
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(1));
|
||||
@ -666,6 +699,8 @@ bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) {
|
||||
assert(0 && "Do not know how to promote this operator's operand!");
|
||||
abort();
|
||||
|
||||
case ISD::ADDE:
|
||||
case ISD::SUBE: Res = PromoteIntOp_ADDSUBE(N, OpNo); break;
|
||||
case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break;
|
||||
case ISD::BIT_CONVERT: Res = PromoteIntOp_BIT_CONVERT(N); break;
|
||||
case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break;
|
||||
@ -743,6 +778,13 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDValue &NewLHS,SDValue &NewRHS,
|
||||
}
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntOp_ADDSUBE(SDNode *N, unsigned OpNo) {
|
||||
assert(OpNo == 2 && "Don't know how to promote this operand!");
|
||||
return DAG.UpdateNodeOperands(SDValue(N, 0), N->getOperand(0),
|
||||
N->getOperand(1),
|
||||
GetPromotedInteger(N->getOperand(2)));
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntOp_ANY_EXTEND(SDNode *N) {
|
||||
SDValue Op = GetPromotedInteger(N->getOperand(0));
|
||||
return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), N->getValueType(0), Op);
|
||||
@ -1063,7 +1105,7 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
|
||||
TLI.isOperationLegalOrCustom(ISD::ADDC,
|
||||
TLI.getTypeToExpandTo(NVT))) {
|
||||
// Emit this X << 1 as X+X.
|
||||
SDVTList VTList = DAG.getVTList(NVT, MVT::Flag);
|
||||
SDVTList VTList = DAG.getVTList(NVT, MVT::i1);
|
||||
SDValue LoOps[2] = { InL, InL };
|
||||
Lo = DAG.getNode(ISD::ADDC, dl, VTList, LoOps, 2);
|
||||
SDValue HiOps[3] = { InH, InH, Lo.getValue(1) };
|
||||
@ -1299,7 +1341,7 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N,
|
||||
TLI.getTypeToExpandTo(NVT));
|
||||
|
||||
if (hasCarry) {
|
||||
SDVTList VTList = DAG.getVTList(NVT, MVT::Flag);
|
||||
SDVTList VTList = DAG.getVTList(NVT, MVT::i1);
|
||||
if (N->getOpcode() == ISD::ADD) {
|
||||
Lo = DAG.getNode(ISD::ADDC, dl, VTList, LoOps, 2);
|
||||
HiOps[2] = Lo.getValue(1);
|
||||
@ -1344,7 +1386,7 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUBC(SDNode *N,
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
GetExpandedInteger(N->getOperand(0), LHSL, LHSH);
|
||||
GetExpandedInteger(N->getOperand(1), RHSL, RHSH);
|
||||
SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
|
||||
SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::i1);
|
||||
SDValue LoOps[2] = { LHSL, RHSL };
|
||||
SDValue HiOps[3] = { LHSH, RHSH };
|
||||
|
||||
@ -1358,8 +1400,8 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUBC(SDNode *N,
|
||||
Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3);
|
||||
}
|
||||
|
||||
// Legalized the flag result - switch anything that used the old flag to
|
||||
// use the new one.
|
||||
// Legalized the second result (carry bit) - switch anything that used the
|
||||
// result to use the new one.
|
||||
ReplaceValueWith(SDValue(N, 1), Hi.getValue(1));
|
||||
}
|
||||
|
||||
@ -1370,7 +1412,7 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUBE(SDNode *N,
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
GetExpandedInteger(N->getOperand(0), LHSL, LHSH);
|
||||
GetExpandedInteger(N->getOperand(1), RHSL, RHSH);
|
||||
SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
|
||||
SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::i1);
|
||||
SDValue LoOps[3] = { LHSL, RHSL, N->getOperand(2) };
|
||||
SDValue HiOps[3] = { LHSH, RHSH };
|
||||
|
||||
@ -1378,8 +1420,8 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUBE(SDNode *N,
|
||||
HiOps[2] = Lo.getValue(1);
|
||||
Hi = DAG.getNode(N->getOpcode(), dl, VTList, HiOps, 3);
|
||||
|
||||
// Legalized the flag result - switch anything that used the old flag to
|
||||
// use the new one.
|
||||
// Legalized the second result (carry bit) - switch anything that used the
|
||||
// result to use the new one.
|
||||
ReplaceValueWith(SDValue(N, 1), Hi.getValue(1));
|
||||
}
|
||||
|
||||
|
@ -242,6 +242,8 @@ private:
|
||||
|
||||
// Integer Result Promotion.
|
||||
void PromoteIntegerResult(SDNode *N, unsigned ResNo);
|
||||
SDValue PromoteIntRes_ADDSUBC(SDNode *N, unsigned ResNo);
|
||||
SDValue PromoteIntRes_ADDSUBE(SDNode *N, unsigned ResNo);
|
||||
SDValue PromoteIntRes_AssertSext(SDNode *N);
|
||||
SDValue PromoteIntRes_AssertZext(SDNode *N);
|
||||
SDValue PromoteIntRes_Atomic1(AtomicSDNode *N);
|
||||
@ -278,6 +280,7 @@ private:
|
||||
|
||||
// Integer Operand Promotion.
|
||||
bool PromoteIntegerOperand(SDNode *N, unsigned OperandNo);
|
||||
SDValue PromoteIntOp_ADDSUBE(SDNode *N, unsigned OpNo);
|
||||
SDValue PromoteIntOp_ANY_EXTEND(SDNode *N);
|
||||
SDValue PromoteIntOp_BIT_CONVERT(SDNode *N);
|
||||
SDValue PromoteIntOp_BUILD_PAIR(SDNode *N);
|
||||
|
@ -268,6 +268,13 @@ unsigned ScheduleDAGSDNodes::ComputeMemOperandsEnd(SDNode *Node) {
|
||||
unsigned N = Node->getNumOperands();
|
||||
while (N && Node->getOperand(N - 1).getValueType() == MVT::Flag)
|
||||
--N;
|
||||
// Skip hard registers set as a side effect (i.e. not result 0).
|
||||
while (N && Node->getOperand(N - 1).getOpcode() == ISD::CopyToReg &&
|
||||
Node->getOperand(N-1).getResNo() != 0 &&
|
||||
!TargetRegisterInfo::isVirtualRegister(
|
||||
dyn_cast<RegisterSDNode>(Node->getOperand(N-1).getOperand(1))
|
||||
->getReg()))
|
||||
--N;
|
||||
if (N && Node->getOperand(N - 1).getValueType() == MVT::Other)
|
||||
--N; // Ignore chain if it exists.
|
||||
return N;
|
||||
|
@ -5257,7 +5257,6 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
case ISD::EXTRACT_SUBVECTOR: return "extract_subvector";
|
||||
case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector";
|
||||
case ISD::VECTOR_SHUFFLE: return "vector_shuffle";
|
||||
case ISD::CARRY_FALSE: return "carry_false";
|
||||
case ISD::ADDC: return "addc";
|
||||
case ISD::ADDE: return "adde";
|
||||
case ISD::SADDO: return "saddo";
|
||||
|
Reference in New Issue
Block a user