From d42c812f4a48c16b41cb9db6784fefa37a9d9877 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Wed, 17 Oct 2007 13:49:58 +0000 Subject: [PATCH] Return Expand from getOperationAction for all extended types. This is needed for SIGN_EXTEND_INREG at least. It is not clear if this is correct for other operations. On the other hand, for the various load/store actions it seems to correct to return the type action, as is currently done. Also, it seems that SelectionDAG::getValueType can be called for extended value types; introduce a map for holding these, since we don't really want to extend the vector to be 2^32 pointers long! Generalize DAGTypeLegalizer::PromoteResult_TRUNCATE and DAGTypeLegalizer::PromoteResult_INT_EXTEND to handle the various funky possibilities that apints introduce, for example that you can promote to a type that needs to be expanded. llvm-svn: 43071 --- llvm/include/llvm/CodeGen/SelectionDAG.h | 1 + llvm/include/llvm/Target/TargetLowering.h | 2 +- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 4 +- .../CodeGen/SelectionDAG/LegalizeDAGTypes.cpp | 72 ++++++++++--------- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 27 ++++--- 5 files changed, 60 insertions(+), 46 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index aef63d6edc13..76ed7f6f6614 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -541,6 +541,7 @@ private: std::vector CondCodeNodes; std::vector ValueTypeNodes; + std::map ExtendedValueTypeNodes; std::map ExternalSymbols; std::map TargetExternalSymbols; std::map StringNodes; diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h index a8eff2275265..e7e99a7f7443 100644 --- a/llvm/include/llvm/Target/TargetLowering.h +++ b/llvm/include/llvm/Target/TargetLowering.h @@ -273,7 +273,7 @@ public: /// expanded to some other code sequence, or the target has a custom expander /// for it. LegalizeAction getOperationAction(unsigned Op, MVT::ValueType VT) const { - if (MVT::isExtendedVT(VT)) return getTypeAction(VT); + if (MVT::isExtendedVT(VT)) return Expand; return (LegalizeAction)((OpActions[Op] >> (2*VT)) & 3); } diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 066090032baa..dfb7f306f5d9 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1762,8 +1762,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { Result = DAG.getExtLoad(ExtType, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), LD->getSrcValueOffset(), MVT::i8, LD->isVolatile(), LD->getAlignment()); - Tmp1 = Result.getValue(0); - Tmp2 = Result.getValue(1); + Tmp1 = Result.getValue(0); + Tmp2 = Result.getValue(1); break; case TargetLowering::Custom: isCustom = true; diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp index 8752698098a3..8c87f644b391 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp @@ -390,7 +390,6 @@ void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) { OpEntry = Result; } - void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { std::pair &Entry = ExpandedNodes[Op]; @@ -479,46 +478,53 @@ SDOperand DAGTypeLegalizer::PromoteResult_Constant(SDNode *N) { } SDOperand DAGTypeLegalizer::PromoteResult_TRUNCATE(SDNode *N) { - MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand Res; + switch (getTypeAction(N->getOperand(0).getValueType())) { default: assert(0 && "Unknown type action!"); - case Legal: { - SDOperand Res = N->getOperand(0); - assert(Res.getValueType() >= NVT && "Truncation doesn't make sense!"); - if (Res.getValueType() > NVT) // Truncate to NVT instead of VT - return DAG.getNode(ISD::TRUNCATE, NVT, Res); - return Res; - } - case Promote: - // The truncation is not required, because we don't guarantee anything - // about high bits anyway. - return GetPromotedOp(N->getOperand(0)); + case Legal: case Expand: - // Truncate the low part of the expanded value to the result type - SDOperand Lo, Hi; - GetExpandedOp(N->getOperand(0), Lo, Hi); - return DAG.getNode(ISD::TRUNCATE, NVT, Lo); + Res = N->getOperand(0); + break; + case Promote: + Res = GetPromotedOp(N->getOperand(0)); + break; } + + MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + assert(MVT::getSizeInBits(Res.getValueType()) >= MVT::getSizeInBits(NVT) && + "Truncation doesn't make sense!"); + if (Res.getValueType() == NVT) + return Res; + + // Truncate to NVT instead of VT + return DAG.getNode(ISD::TRUNCATE, NVT, Res); } + SDOperand DAGTypeLegalizer::PromoteResult_INT_EXTEND(SDNode *N) { MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - switch (getTypeAction(N->getOperand(0).getValueType())) { - default: assert(0 && "BUG: Smaller reg should have been promoted!"); - case Legal: - // Input is legal? Just do extend all the way to the larger type. - return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0)); - case Promote: - // Get promoted operand if it is smaller. + + if (getTypeAction(N->getOperand(0).getValueType()) == Promote) { SDOperand Res = GetPromotedOp(N->getOperand(0)); - // The high bits are not guaranteed to be anything. Insert an extend. - if (N->getOpcode() == ISD::SIGN_EXTEND) - return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, - DAG.getValueType(N->getOperand(0).getValueType())); - if (N->getOpcode() == ISD::ZERO_EXTEND) - return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType()); - assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!"); - return Res; + assert(MVT::getSizeInBits(Res.getValueType()) <= MVT::getSizeInBits(NVT) && + "Extension doesn't make sense!"); + + // If the result and operand types are the same after promotion, simplify + // to an in-register extension. + if (NVT == Res.getValueType()) { + // The high bits are not guaranteed to be anything. Insert an extend. + if (N->getOpcode() == ISD::SIGN_EXTEND) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, + DAG.getValueType(N->getOperand(0).getValueType())); + if (N->getOpcode() == ISD::ZERO_EXTEND) + return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType()); + assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!"); + return Res; + } } + + // Otherwise, just extend the original operand all the way to the larger type. + return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0)); } SDOperand DAGTypeLegalizer::PromoteResult_FP_ROUND(SDNode *N) { @@ -527,7 +533,6 @@ SDOperand DAGTypeLegalizer::PromoteResult_FP_ROUND(SDNode *N) { N->getOperand(0), DAG.getValueType(N->getValueType(0))); } - SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) { assert(isTypeLegal(TLI.getSetCCResultTy()) && "SetCC type is not legal??"); return DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), N->getOperand(0), @@ -1198,6 +1203,7 @@ SDOperand DAGTypeLegalizer::PromoteOperand_ZERO_EXTEND(SDNode *N) { Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType()); } + SDOperand DAGTypeLegalizer::PromoteOperand_SIGN_EXTEND(SDNode *N) { SDOperand Op = GetPromotedOp(N->getOperand(0)); Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index b0c949e30ed8..e6ce2eb99512 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -527,10 +527,16 @@ void SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) { Erased = TargetExternalSymbols.erase(cast(N)->getSymbol()); break; - case ISD::VALUETYPE: - Erased = ValueTypeNodes[cast(N)->getVT()] != 0; - ValueTypeNodes[cast(N)->getVT()] = 0; + case ISD::VALUETYPE: { + MVT::ValueType VT = cast(N)->getVT(); + if (MVT::isExtendedVT(VT)) { + Erased = ExtendedValueTypeNodes.erase(VT); + } else { + Erased = ValueTypeNodes[VT] != 0; + ValueTypeNodes[VT] = 0; + } break; + } default: // Remove it from the CSE Map. Erased = CSEMap.RemoveNode(N); @@ -847,15 +853,16 @@ SDOperand SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) { } SDOperand SelectionDAG::getValueType(MVT::ValueType VT) { - assert(!MVT::isExtendedVT(VT) && "Expecting a simple value type!"); - if ((unsigned)VT >= ValueTypeNodes.size()) + if (!MVT::isExtendedVT(VT) && (unsigned)VT >= ValueTypeNodes.size()) ValueTypeNodes.resize(VT+1); - if (ValueTypeNodes[VT] == 0) { - ValueTypeNodes[VT] = new VTSDNode(VT); - AllNodes.push_back(ValueTypeNodes[VT]); - } - return SDOperand(ValueTypeNodes[VT], 0); + SDNode *&N = MVT::isExtendedVT(VT) ? + ExtendedValueTypeNodes[VT] : ValueTypeNodes[VT]; + + if (N) return SDOperand(N, 0); + N = new VTSDNode(VT); + AllNodes.push_back(N); + return SDOperand(N, 0); } SDOperand SelectionDAG::getExternalSymbol(const char *Sym, MVT::ValueType VT) {