52 #define DEBUG_TYPE "legalizevectorops" 56 class VectorLegalizer {
68 LegalizedNodes.
insert(std::make_pair(From, To));
71 LegalizedNodes.
insert(std::make_pair(To, To));
174 bool VectorLegalizer::Run() {
176 bool HasVectors =
false;
178 E = std::prev(DAG.allnodes_end());
I != std::next(
E); ++
I) {
183 HasVectors |= J->isVector();
200 DAG.AssignTopologicalOrder();
202 E = std::prev(DAG.allnodes_end());
I != std::next(
E); ++
I)
206 SDValue OldRoot = DAG.getRoot();
207 assert(LegalizedNodes.count(OldRoot) &&
"Root didn't get legalized?");
208 DAG.setRoot(LegalizedNodes[OldRoot]);
210 LegalizedNodes.clear();
213 DAG.RemoveDeadNodes();
229 if (I != LegalizedNodes.
end())
return I->second;
235 for (
const SDValue &Op : Node->op_values())
251 return TranslateLegalizeResults(Op, Result);
253 if (
SDValue Lowered = TLI.LowerOperation(Result, DAG)) {
255 "Unexpected number of results");
256 if (Lowered != Result) {
258 Lowered = LegalizeOp(Lowered);
261 return TranslateLegalizeResults(Op, Lowered);
266 return LegalizeOp(ExpandLoad(Op));
276 switch (TLI.getTruncStoreAction(ValVT, StVT)) {
279 return TranslateLegalizeResults(Op, Result);
281 SDValue Lowered = TLI.LowerOperation(Result, DAG);
282 if (Lowered != Result) {
284 Lowered = LegalizeOp(Lowered);
287 return TranslateLegalizeResults(Op, Lowered);
291 return LegalizeOp(ExpandStore(Op));
296 bool HasVectorValue =
false;
300 HasVectorValue |= J->isVector();
302 return TranslateLegalizeResults(Op, Result);
307 return TranslateLegalizeResults(Op, Result);
336 Action = TLI.getStrictFPOperationAction(Node->getOpcode(),
337 Node->getValueType(0));
426 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
429 unsigned Scale = Node->getConstantOperandVal(2);
430 Action = TLI.getFixedPointOperationAction(Node->getOpcode(),
431 Node->getValueType(0), Scale);
435 Action = TLI.getOperationAction(Node->getOpcode(),
436 cast<VTSDNode>(Node->getOperand(1))->getVT());
440 Action = TLI.getOperationAction(Node->getOpcode(),
441 Node->getOperand(0).getValueType());
445 LLVM_DEBUG(
dbgs() <<
"\nLegalizing vector op: "; Node->dump(&DAG));
450 Result = Promote(Op);
458 if (
SDValue Tmp1 = TLI.LowerOperation(Op, DAG)) {
472 Result = LegalizeOp(Result);
478 AddLegalizedOperand(Op, Result);
489 return PromoteINT_TO_FP(Op);
493 return PromoteFP_TO_INT(Op);
503 "Can't promote a vector with multiple results!");
514 NVT.isVector() && NVT.getVectorElementType().isFloatingPoint())
525 NVT.isVector() && NVT.getVectorElementType().isFloatingPoint()))
526 return DAG.getNode(
ISD::FP_ROUND, dl, VT, Op, DAG.getIntPtrConstant(0, dl));
537 "Vectors have different number of elements!");
546 Operands[j] = DAG.getNode(Opc, dl, NVT, Op.
getOperand(j));
562 "Vectors have different number of elements!");
593 if (SrcVT.getVectorNumElements() > 1 && !SrcEltVT.
isByteSized()) {
609 EVT WideVT = TLI.getPointerTy(DAG.getDataLayout());
612 "Could not handle the sophisticated case when the widest integer is" 615 "Type is not legalized?");
619 unsigned RemainingBytes = SrcVT.getStoreSize();
621 while (RemainingBytes > 0) {
623 unsigned LoadBytes = WideBytes;
625 if (RemainingBytes >= LoadBytes) {
627 DAG.getLoad(WideVT, dl, Chain, BasePTR,
633 while (RemainingBytes < LoadBytes) {
638 DAG.getExtLoad(
ISD::EXTLOAD, dl, WideVT, Chain, BasePTR,
644 RemainingBytes -= LoadBytes;
647 BasePTR = DAG.getObjectPtrOffset(dl, BasePTR, LoadBytes);
655 SDValue SrcEltBitMask = DAG.getConstant((1U << SrcEltBits) - 1, dl, WideVT);
657 unsigned BitOffset = 0;
658 unsigned WideIdx = 0;
661 for (
unsigned Idx = 0; Idx != NumElem; ++Idx) {
664 if (BitOffset < WideBits) {
665 ShAmt = DAG.getConstant(
666 BitOffset, dl, TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
671 BitOffset += SrcEltBits;
672 if (BitOffset >= WideBits) {
674 BitOffset -= WideBits;
676 ShAmt = DAG.getConstant(
677 SrcEltBits - BitOffset, dl,
678 TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
690 Lo = DAG.getAnyExtOrTrunc(Lo, dl, DstEltVT);
693 Lo = DAG.getZExtOrTrunc(Lo, dl, DstEltVT);
697 DAG.getConstant(WideBits - SrcEltBits, dl,
698 TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
701 Lo = DAG.getSExtOrTrunc(Lo, dl, DstEltVT);
710 SDValue Scalarized = TLI.scalarizeVectorLoad(LD, DAG);
721 AddLegalizedOperand(Op.
getValue(0), Value);
722 AddLegalizedOperand(Op.
getValue(1), NewChain);
724 return (Op.
getResNo() ? NewChain : Value);
729 SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
730 AddLegalizedOperand(Op, TF);
737 return ExpandSEXTINREG(Op);
739 return ExpandANY_EXTEND_VECTOR_INREG(Op);
741 return ExpandSIGN_EXTEND_VECTOR_INREG(Op);
743 return ExpandZERO_EXTEND_VECTOR_INREG(Op);
745 return ExpandBSWAP(Op);
747 return ExpandVSELECT(Op);
749 return ExpandSELECT(Op);
751 return ExpandFP_TO_UINT(Op);
753 return ExpandUINT_TO_FLOAT(Op);
755 return ExpandFNEG(Op);
757 return ExpandFSUB(Op);
759 return UnrollVSETCC(Op);
761 return ExpandABS(Op);
763 return ExpandBITREVERSE(Op);
765 return ExpandCTPOP(Op);
768 return ExpandCTLZ(Op);
771 return ExpandCTTZ(Op);
774 return ExpandFunnelShift(Op);
777 return ExpandROT(Op);
780 return ExpandFMINNUM_FMAXNUM(Op);
785 return ExpandAddSubSat(Op);
810 return ExpandStrictFPOp(Op);
812 return DAG.UnrollVectorOp(Op.
getNode());
839 return DAG.UnrollVectorOp(Op.
getNode());
847 Mask = DAG.getSelect(DL, BitTy, Mask,
850 DAG.getConstant(0, DL, BitTy));
853 Mask = DAG.getSplatBuildVector(MaskTy, DL, Mask);
861 SDValue AllOnes = DAG.getConstant(
877 return DAG.UnrollVectorOp(Op.
getNode());
884 SDValue ShiftSz = DAG.getConstant(BW - OrigBW, DL, VT);
888 return DAG.getNode(
ISD::SRA, DL, VT, Op, ShiftSz);
893 SDValue VectorLegalizer::ExpandANY_EXTEND_VECTOR_INREG(
SDValue Op) {
903 ShuffleMask.
resize(NumSrcElements, -1);
906 int ExtLaneScale = NumSrcElements / NumElements;
907 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
908 for (
int i = 0; i < NumElements; ++i)
909 ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
913 DAG.getVectorShuffle(SrcVT, DL, Src, DAG.getUNDEF(SrcVT), ShuffleMask));
916 SDValue VectorLegalizer::ExpandSIGN_EXTEND_VECTOR_INREG(
SDValue Op) {
931 SDValue ShiftAmount = DAG.getConstant(EltWidth - SrcEltWidth, DL, VT);
933 DAG.getNode(
ISD::SHL, DL, VT, Op, ShiftAmount),
940 SDValue VectorLegalizer::ExpandZERO_EXTEND_VECTOR_INREG(
SDValue Op) {
949 SDValue Zero = DAG.getConstant(0, DL, SrcVT);
954 ShuffleMask.
reserve(NumSrcElements);
955 for (
int i = 0; i < NumSrcElements; ++i)
958 int ExtLaneScale = NumSrcElements / NumElements;
959 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
960 for (
int i = 0; i < NumElements; ++i)
961 ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
964 DAG.getVectorShuffle(SrcVT, DL, Zero, Src, ShuffleMask));
970 for (
int J = ScalarSizeInBytes - 1; J >= 0; --J)
971 ShuffleMask.
push_back((
I * ScalarSizeInBytes) + J);
983 if (!TLI.isShuffleMaskLegal(ShuffleMask, ByteVT))
984 return DAG.UnrollVectorOp(Op.
getNode());
988 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT), ShuffleMask);
997 return DAG.UnrollVectorOp(Op.
getNode());
1003 if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
1008 if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
1010 (TLI.isOperationLegalOrCustom(
ISD::SHL, ByteVT) &&
1011 TLI.isOperationLegalOrCustom(
ISD::SRL, ByteVT) &&
1012 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, ByteVT) &&
1013 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, ByteVT)))) {
1016 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT),
1025 if (!TLI.isOperationLegalOrCustom(
ISD::SHL, VT) ||
1026 !TLI.isOperationLegalOrCustom(
ISD::SRL, VT) ||
1027 !TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, VT) ||
1028 !TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, VT))
1029 return DAG.UnrollVectorOp(Op.
getNode());
1058 return DAG.UnrollVectorOp(Op.
getNode());
1064 return DAG.UnrollVectorOp(Op.
getNode());
1072 SDValue AllOnes = DAG.getConstant(
1085 if (TLI.expandABS(Op.
getNode(), Result, DAG))
1089 return DAG.UnrollVectorOp(Op.
getNode());
1095 if (TLI.expandFP_TO_UINT(Op.
getNode(), Result, DAG))
1099 return DAG.UnrollVectorOp(Op.
getNode());
1108 if (TLI.expandUINT_TO_FP(Op.
getNode(), Result, DAG))
1114 return DAG.UnrollVectorOp(Op.
getNode());
1117 assert((BW == 64 || BW == 32) &&
1118 "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
1120 SDValue HalfWord = DAG.getConstant(BW / 2, DL, VT);
1125 uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1126 SDValue HalfWordMask = DAG.getConstant(HWMask, DL, VT);
1154 return DAG.UnrollVectorOp(Op.
getNode());
1162 if (TLI.isOperationLegalOrCustom(
ISD::FNEG, VT) &&
1163 TLI.isOperationLegalOrCustom(
ISD::FADD, VT))
1166 return DAG.UnrollVectorOp(Op.
getNode());
1171 if (TLI.expandCTPOP(Op.
getNode(), Result, DAG))
1174 return DAG.UnrollVectorOp(Op.
getNode());
1179 if (TLI.expandCTLZ(Op.
getNode(), Result, DAG))
1182 return DAG.UnrollVectorOp(Op.
getNode());
1187 if (TLI.expandCTTZ(Op.
getNode(), Result, DAG))
1190 return DAG.UnrollVectorOp(Op.
getNode());
1195 if (TLI.expandFunnelShift(Op.
getNode(), Result, DAG))
1198 return DAG.UnrollVectorOp(Op.
getNode());
1203 if (TLI.expandROT(Op.
getNode(), Result, DAG))
1206 return DAG.UnrollVectorOp(Op.
getNode());
1210 if (
SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(Op.
getNode(), DAG))
1212 return DAG.UnrollVectorOp(Op.
getNode());
1218 return DAG.UnrollVectorOp(Op.
getNode());
1233 for (
unsigned i = 0; i < NumElems; ++i) {
1235 SDValue Idx = DAG.getConstant(i, dl,
1242 for (
unsigned j = 1; j < NumOpers; ++j) {
1259 SDValue Result = DAG.getBuildVector(VT, dl, OpValues);
1262 AddLegalizedOperand(Op.
getValue(0), Result);
1263 AddLegalizedOperand(Op.
getValue(1), NewChain);
1265 return Op.
getResNo() ? NewChain : Result;
1276 for (
unsigned i = 0; i < NumElems; ++i) {
1279 DAG.getConstant(i, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
1282 DAG.getConstant(i, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
1284 TLI.getSetCCResultType(DAG.getDataLayout(),
1285 *DAG.getContext(), TmpEltVT),
1286 LHSElem, RHSElem, CC);
1287 Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
1290 DAG.getConstant(0, dl, EltVT));
1292 return DAG.getBuildVector(VT, dl, Ops);
1296 return VectorLegalizer(*this).Run();
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two values.
virtual MVT getVectorIdxTy(const DataLayout &DL) const
Returns the type to be used for the index operand of: ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT...
EVT getValueType() const
Return the ValueType of the referenced return value.
Constrained versions of libm-equivalent floating point intrinsics.
static APInt getAllOnesValue(unsigned numBits)
Get the all-ones value.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
This class represents lattice values for constants.
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0...
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
bool isVector() const
Return true if this is a vector value type.
const SDValue & getBasePtr() const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void push_back(const T &Elt)
const SDValue & getValue() const
bool LegalizeVectors()
This transforms the SelectionDAG into a SelectionDAG that only uses vector math operations supported ...
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
unsigned getVectorNumElements() const
const SDValue & getChain() const
unsigned getAlignment() const
Constrained versions of the binary floating point operators.
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
[US]{MIN/MAX} - Binary minimum or maximum or signed or unsigned integers.
const SDNodeFlags getFlags() const
SDNode * getNode() const
get the SDNode which holds the desired result
void reserve(size_type N)
bool isByteSized() const
Return true if the bit size is a multiple of 8.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
unsigned getValueSizeInBits() const
Returns the size of the value in bits.
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
bool isTruncatingStore() const
Return true if the op does a truncation before store.
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Shift and rotation operations.
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth...
RESULT = SMULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same wi...
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
unsigned getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
This file implements a class to represent arbitrary precision integral constant values and operations...
unsigned getScalarSizeInBits() const
unsigned getSizeInBits() const
Return the size of the specified value type in bits.
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Simple integer binary arithmetic operators.
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
MVT getVectorElementType() const
This class is used to represent ISD::STORE nodes.
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the specified, possibly variable...
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
A and B are either alignments or offsets.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
Simple binary floating point operators.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
bool isRound() const
Return true if the size is a power-of-two number of bytes.
const SDValue & getOperand(unsigned Num) const
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Bit counting operators with an undefined result for zero inputs.
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LegalizeAction
This enum indicates whether operations are valid for a target, and if not, what action should be used...
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
TokenFactor - This node takes multiple tokens as input and produces a single token result...
const TargetLowering & getTargetLoweringInfo() const
Iterator for intrusive lists based on ilist_node.
BlockVerifier::State From
Returns platform specific canonical encoding of a floating point number.
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
EVT getVectorElementType() const
Given a vector type, return the type of each element.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
X = FP_ROUND_INREG(Y, VT) - This operator takes an FP register, and rounds it to a floating point val...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on two values, following the IEEE-754 2008 definition.
Byte Swap and Counting operators.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
MachinePointerInfo getWithOffset(int64_t O) const
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT...
EVT getMemoryVT() const
Return the type of the in-memory value.
Select(COND, TRUEVAL, FALSEVAL).
ZERO_EXTEND - Used for integer types, zeroing the new bits.
ANY_EXTEND - Used for integer types. The high bits are undefined.
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
bool isVector() const
Return true if this is a vector value type.
Bitwise operators - logical and, logical or, logical xor.
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Flags getFlags() const
Return the raw flags of the source value,.
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
unsigned getOpcode() const
SDValue getValue(unsigned R) const
const MachinePointerInfo & getPointerInfo() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
FMA - Perform a * b + c with no intermediate rounding step.
unsigned getResNo() const
get the index which selects a specific result in the SDNode
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
SetCC operator - This evaluates to a true value iff the condition is true.
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
unsigned getNumOperands() const
const SDValue & getOperand(unsigned i) const
TRUNCATE - Completely drop the high bits.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
Perform various unary floating-point operations inspired by libm.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl< int > &ShuffleMask)
This file describes how to lower LLVM code to machine code.
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
This class is used to represent ISD::LOAD nodes.