From 56eb86806d5d178d42108f17d11098b3e640b996 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Tue, 30 Aug 2005 02:44:00 +0000 Subject: [PATCH] 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 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 29 +++++++++++++++++++---- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 23 ++++++++++++++---- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 695ae23777d..9480ed6f096 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -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(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(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; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index dab757ef8a2..c929806ed11 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -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(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(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(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(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"; -- 2.34.1