mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-01 18:33:56 +00:00
Add support for AssertSext and AssertZext, folding other extensions with
them. This allows for elminination of redundant extends in the entry blocks of functions on PowerPC. Add support for i32 x i32 -> i64 multiplies, by recognizing when the inputs to ISD::MUL in ExpandOp are actually just extended i32 values and not real i64 values. this allows us to codegen int mulhs(int a, int b) { return ((long long)a * b) >> 32; } as: _mulhs: mulhw r3, r4, r3 blr instead of: _mulhs: mulhwu r2, r4, r3 srawi r5, r3, 31 mullw r5, r4, r5 add r2, r2, r5 srawi r4, r4, 31 mullw r3, r4, r3 add r3, r2, r3 blr with a similar improvement on x86. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23147 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f7f3d32191
commit
56eb86806d
@ -456,6 +456,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
assert(0 && "Do not know how to legalize this operator!");
|
||||
abort();
|
||||
case ISD::EntryToken:
|
||||
case ISD::AssertSext:
|
||||
case ISD::AssertZext:
|
||||
case ISD::FrameIndex:
|
||||
case ISD::GlobalAddress:
|
||||
case ISD::ExternalSymbol:
|
||||
@ -3158,11 +3160,28 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
|
||||
SDOperand LL, LH, RL, RH;
|
||||
ExpandOp(Node->getOperand(0), LL, LH);
|
||||
ExpandOp(Node->getOperand(1), RL, RH);
|
||||
Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
|
||||
RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
|
||||
LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
|
||||
Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
|
||||
Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
|
||||
unsigned SH = MVT::getSizeInBits(RH.getValueType())-1;
|
||||
// MULHS implicitly sign extends its inputs. Check to see if ExpandOp
|
||||
// extended the sign bit of the low half through the upper half, and if so
|
||||
// emit a MULHS instead of the alternate sequence that is valid for any
|
||||
// i64 x i64 multiply.
|
||||
if (TLI.isOperationLegal(ISD::MULHS, NVT) &&
|
||||
// is RH an extension of the sign bit of RL?
|
||||
RH.getOpcode() == ISD::SRA && RH.getOperand(0) == RL &&
|
||||
RH.getOperand(1).getOpcode() == ISD::Constant &&
|
||||
cast<ConstantSDNode>(RH.getOperand(1))->getValue() == SH &&
|
||||
// is LH an extension of the sign bit of LL?
|
||||
LH.getOpcode() == ISD::SRA && LH.getOperand(0) == LL &&
|
||||
LH.getOperand(1).getOpcode() == ISD::Constant &&
|
||||
cast<ConstantSDNode>(LH.getOperand(1))->getValue() == SH) {
|
||||
Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
|
||||
} else {
|
||||
Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
|
||||
RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
|
||||
LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
|
||||
Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
|
||||
Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
|
||||
}
|
||||
Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
|
||||
} else {
|
||||
Lo = ExpandLibCall("__muldi3" , Node, Hi); break;
|
||||
|
@ -631,7 +631,8 @@ SDOperand SelectionDAG::SimplifySetCC(MVT::ValueType VT, SDOperand N1,
|
||||
unsigned ExtSrcTyBits = MVT::getSizeInBits(ExtSrcTy);
|
||||
MVT::ValueType ExtDstTy = N1.getValueType();
|
||||
unsigned ExtDstTyBits = MVT::getSizeInBits(ExtDstTy);
|
||||
|
||||
|
||||
if (Cond == ISD::SETEQ || Cond == ISD::SETNE) {
|
||||
// If the extended part has any inconsistent bits, it cannot ever
|
||||
// compare equal. In other words, they have to be all ones or all
|
||||
// zeros.
|
||||
@ -644,6 +645,7 @@ SDOperand SelectionDAG::SimplifySetCC(MVT::ValueType VT, SDOperand N1,
|
||||
return getSetCC(VT, getZeroExtendInReg(N1.getOperand(0), ExtSrcTy),
|
||||
getConstant(C2 & (~0ULL >> 64-ExtSrcTyBits), ExtDstTy),
|
||||
Cond);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t MinVal, MaxVal;
|
||||
@ -1192,6 +1194,8 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
|
||||
assert(EVT <= VT && "Not rounding down!");
|
||||
break;
|
||||
}
|
||||
case ISD::AssertSext:
|
||||
case ISD::AssertZext:
|
||||
case ISD::SIGN_EXTEND_INREG: {
|
||||
MVT::ValueType EVT = cast<VTSDNode>(N2)->getVT();
|
||||
assert(VT == N1.getValueType() && "Not an inreg extend!");
|
||||
@ -1394,6 +1398,14 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
|
||||
// we know the result of the AND will be the AND mask itself.
|
||||
return N2;
|
||||
}
|
||||
} else if (N1.getOpcode() == ISD::AssertZext) {
|
||||
// If we are masking out the part of our input that was already masked
|
||||
// out, just return the input directly.
|
||||
unsigned ExtendBits =
|
||||
MVT::getSizeInBits(cast<VTSDNode>(N1.getOperand(1))->getVT());
|
||||
uint64_t ExtendMask = (1ULL << ExtendBits) - 1;
|
||||
if (ExtendMask == C2)
|
||||
return N1.getOperand(0);
|
||||
}
|
||||
break;
|
||||
case ISD::OR:
|
||||
@ -1579,14 +1591,15 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
|
||||
if (EVT == VT) return N1; // Not actually extending
|
||||
|
||||
// If we are sign extending an extension, use the original source.
|
||||
if (N1.getOpcode() == ISD::SIGN_EXTEND_INREG)
|
||||
if (N1.getOpcode() == ISD::SIGN_EXTEND_INREG ||
|
||||
N1.getOpcode() == ISD::AssertSext)
|
||||
if (cast<VTSDNode>(N1.getOperand(1))->getVT() <= EVT)
|
||||
return N1;
|
||||
|
||||
// If we are sign extending a sextload, return just the load.
|
||||
if (N1.getOpcode() == ISD::SEXTLOAD)
|
||||
if (cast<VTSDNode>(N1.getOperand(3))->getVT() <= EVT)
|
||||
return N1;
|
||||
return N1;
|
||||
|
||||
// If we are extending the result of a setcc, and we already know the
|
||||
// contents of the top bits, eliminate the extension.
|
||||
@ -1594,7 +1607,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
|
||||
TLI.getSetCCResultContents() ==
|
||||
TargetLowering::ZeroOrNegativeOneSetCCResult)
|
||||
return N1;
|
||||
|
||||
|
||||
// If we are sign extending the result of an (and X, C) operation, and we
|
||||
// know the extended bits are zeros already, don't do the extend.
|
||||
if (N1.getOpcode() == ISD::AND)
|
||||
@ -2195,6 +2208,8 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
case ISD::VALUETYPE: return "ValueType";
|
||||
case ISD::EntryToken: return "EntryToken";
|
||||
case ISD::TokenFactor: return "TokenFactor";
|
||||
case ISD::AssertSext: return "AssertSext";
|
||||
case ISD::AssertZext: return "AssertZext";
|
||||
case ISD::Constant: return "Constant";
|
||||
case ISD::TargetConstant: return "TargetConstant";
|
||||
case ISD::ConstantFP: return "ConstantFP";
|
||||
|
Loading…
x
Reference in New Issue
Block a user