From: Nate Begeman Date: Tue, 30 Aug 2005 02:44:00 +0000 (+0000) Subject: Add support for AssertSext and AssertZext, folding other extensions with X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=56eb86806d5d178d42108f17d11098b3e640b996;p=oota-llvm.git 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 --- 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";