1 | //===-------- LegalizeTypesGeneric.cpp - Generic type legalization --------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements generic type expansion and splitting for LegalizeTypes. |
10 | // The routines here perform legalization when the details of the type (such as |
11 | // whether it is an integer or a float) do not matter. |
12 | // Expansion is the act of changing a computation in an illegal type to be a |
13 | // computation in two identical registers of a smaller type. The Lo/Hi part |
14 | // is required to be stored first in memory on little/big-endian machines. |
15 | // Splitting is the act of changing a computation in an illegal type to be a |
16 | // computation in two not necessarily identical registers of a smaller type. |
17 | // There are no requirements on how the type is represented in memory. |
18 | // |
19 | //===----------------------------------------------------------------------===// |
20 | |
21 | #include "LegalizeTypes.h" |
22 | #include "llvm/IR/DataLayout.h" |
23 | using namespace llvm; |
24 | |
25 | #define DEBUG_TYPE "legalize-types" |
26 | |
27 | //===----------------------------------------------------------------------===// |
28 | // Generic Result Expansion. |
29 | //===----------------------------------------------------------------------===// |
30 | |
31 | // These routines assume that the Lo/Hi part is stored first in memory on |
32 | // little/big-endian machines, followed by the Hi/Lo part. This means that |
33 | // they cannot be used as is on vectors, for which Lo is always stored first. |
34 | void DAGTypeLegalizer::ExpandRes_MERGE_VALUES(SDNode *N, unsigned ResNo, |
35 | SDValue &Lo, SDValue &Hi) { |
36 | SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); |
37 | GetExpandedOp(Op, Lo, Hi); |
38 | } |
39 | |
40 | void DAGTypeLegalizer::ExpandRes_BITCAST(SDNode *N, SDValue &Lo, SDValue &Hi) { |
41 | EVT OutVT = N->getValueType(ResNo: 0); |
42 | EVT NOutVT = TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: OutVT); |
43 | SDValue InOp = N->getOperand(Num: 0); |
44 | EVT InVT = InOp.getValueType(); |
45 | SDLoc dl(N); |
46 | |
47 | // Handle some special cases efficiently. |
48 | switch (getTypeAction(VT: InVT)) { |
49 | case TargetLowering::TypeLegal: |
50 | case TargetLowering::TypePromoteInteger: |
51 | break; |
52 | case TargetLowering::TypePromoteFloat: |
53 | case TargetLowering::TypeSoftPromoteHalf: |
54 | llvm_unreachable("Bitcast of a promotion-needing float should never need" |
55 | "expansion" ); |
56 | case TargetLowering::TypeSoftenFloat: |
57 | SplitInteger(Op: GetSoftenedFloat(Op: InOp), Lo, Hi); |
58 | Lo = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Lo); |
59 | Hi = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Hi); |
60 | return; |
61 | case TargetLowering::TypeExpandInteger: |
62 | case TargetLowering::TypeExpandFloat: { |
63 | auto &DL = DAG.getDataLayout(); |
64 | // Convert the expanded pieces of the input. |
65 | GetExpandedOp(Op: InOp, Lo, Hi); |
66 | if (TLI.hasBigEndianPartOrdering(VT: InVT, DL) != |
67 | TLI.hasBigEndianPartOrdering(VT: OutVT, DL)) |
68 | std::swap(a&: Lo, b&: Hi); |
69 | Lo = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Lo); |
70 | Hi = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Hi); |
71 | return; |
72 | } |
73 | case TargetLowering::TypeSplitVector: |
74 | GetSplitVector(Op: InOp, Lo, Hi); |
75 | if (TLI.hasBigEndianPartOrdering(VT: OutVT, DL: DAG.getDataLayout())) |
76 | std::swap(a&: Lo, b&: Hi); |
77 | Lo = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Lo); |
78 | Hi = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Hi); |
79 | return; |
80 | case TargetLowering::TypeScalarizeVector: |
81 | // Convert the element instead. |
82 | SplitInteger(Op: BitConvertToInteger(Op: GetScalarizedVector(Op: InOp)), Lo, Hi); |
83 | Lo = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Lo); |
84 | Hi = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Hi); |
85 | return; |
86 | case TargetLowering::TypeScalarizeScalableVector: |
87 | report_fatal_error(reason: "Scalarization of scalable vectors is not supported." ); |
88 | case TargetLowering::TypeWidenVector: { |
89 | assert(!(InVT.getVectorNumElements() & 1) && "Unsupported BITCAST" ); |
90 | InOp = GetWidenedVector(Op: InOp); |
91 | EVT LoVT, HiVT; |
92 | std::tie(args&: LoVT, args&: HiVT) = DAG.GetSplitDestVTs(VT: InVT); |
93 | std::tie(args&: Lo, args&: Hi) = DAG.SplitVector(N: InOp, DL: dl, LoVT, HiVT); |
94 | if (TLI.hasBigEndianPartOrdering(VT: OutVT, DL: DAG.getDataLayout())) |
95 | std::swap(a&: Lo, b&: Hi); |
96 | Lo = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Lo); |
97 | Hi = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NOutVT, Operand: Hi); |
98 | return; |
99 | } |
100 | } |
101 | |
102 | if (InVT.isVector() && OutVT.isInteger()) { |
103 | // Handle cases like i64 = BITCAST v1i64 on x86, where the operand |
104 | // is legal but the result is not. |
105 | unsigned NumElems = 2; |
106 | EVT ElemVT = NOutVT; |
107 | EVT NVT = EVT::getVectorVT(Context&: *DAG.getContext(), VT: ElemVT, NumElements: NumElems); |
108 | |
109 | // If <ElemVT * N> is not a legal type, try <ElemVT/2 * (N*2)>. |
110 | while (!isTypeLegal(VT: NVT)) { |
111 | unsigned NewSizeInBits = ElemVT.getSizeInBits() / 2; |
112 | // If the element size is smaller than byte, bail. |
113 | if (NewSizeInBits < 8) |
114 | break; |
115 | NumElems *= 2; |
116 | ElemVT = EVT::getIntegerVT(Context&: *DAG.getContext(), BitWidth: NewSizeInBits); |
117 | NVT = EVT::getVectorVT(Context&: *DAG.getContext(), VT: ElemVT, NumElements: NumElems); |
118 | } |
119 | |
120 | if (isTypeLegal(VT: NVT)) { |
121 | SDValue CastInOp = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: NVT, Operand: InOp); |
122 | |
123 | SmallVector<SDValue, 8> Vals; |
124 | for (unsigned i = 0; i < NumElems; ++i) |
125 | Vals.push_back(Elt: DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL: dl, VT: ElemVT, |
126 | N1: CastInOp, N2: DAG.getVectorIdxConstant(Val: i, DL: dl))); |
127 | |
128 | // Build Lo, Hi pair by pairing extracted elements if needed. |
129 | unsigned Slot = 0; |
130 | for (unsigned e = Vals.size(); e - Slot > 2; Slot += 2, e += 1) { |
131 | // Each iteration will BUILD_PAIR two nodes and append the result until |
132 | // there are only two nodes left, i.e. Lo and Hi. |
133 | SDValue LHS = Vals[Slot]; |
134 | SDValue RHS = Vals[Slot + 1]; |
135 | |
136 | if (DAG.getDataLayout().isBigEndian()) |
137 | std::swap(a&: LHS, b&: RHS); |
138 | |
139 | Vals.push_back(Elt: DAG.getNode( |
140 | Opcode: ISD::BUILD_PAIR, DL: dl, |
141 | VT: EVT::getIntegerVT(Context&: *DAG.getContext(), BitWidth: LHS.getValueSizeInBits() << 1), |
142 | N1: LHS, N2: RHS)); |
143 | } |
144 | Lo = Vals[Slot++]; |
145 | Hi = Vals[Slot++]; |
146 | |
147 | if (DAG.getDataLayout().isBigEndian()) |
148 | std::swap(a&: Lo, b&: Hi); |
149 | |
150 | return; |
151 | } |
152 | } |
153 | |
154 | // Lower the bit-convert to a store/load from the stack. |
155 | assert(NOutVT.isByteSized() && "Expanded type not byte sized!" ); |
156 | |
157 | // Create the stack frame object. Make sure it is aligned for both |
158 | // the source and expanded destination types. |
159 | |
160 | // In cases where the vector is illegal it will be broken down into parts |
161 | // and stored in parts - we should use the alignment for the smallest part. |
162 | Align InAlign = DAG.getReducedAlign(VT: InVT, /*UseABI=*/false); |
163 | Align NOutAlign = DAG.getReducedAlign(VT: NOutVT, /*UseABI=*/false); |
164 | Align Align = std::max(a: InAlign, b: NOutAlign); |
165 | SDValue StackPtr = DAG.CreateStackTemporary(Bytes: InVT.getStoreSize(), Alignment: Align); |
166 | int SPFI = cast<FrameIndexSDNode>(Val: StackPtr.getNode())->getIndex(); |
167 | MachinePointerInfo PtrInfo = |
168 | MachinePointerInfo::getFixedStack(MF&: DAG.getMachineFunction(), FI: SPFI); |
169 | |
170 | // Emit a store to the stack slot. |
171 | SDValue Store = DAG.getStore(Chain: DAG.getEntryNode(), dl, Val: InOp, Ptr: StackPtr, PtrInfo); |
172 | |
173 | // Load the first half from the stack slot. |
174 | Lo = DAG.getLoad(VT: NOutVT, dl, Chain: Store, Ptr: StackPtr, PtrInfo, Alignment: NOutAlign); |
175 | |
176 | // Increment the pointer to the other half. |
177 | unsigned IncrementSize = NOutVT.getSizeInBits() / 8; |
178 | StackPtr = |
179 | DAG.getMemBasePlusOffset(Base: StackPtr, Offset: TypeSize::getFixed(ExactSize: IncrementSize), DL: dl); |
180 | |
181 | // Load the second half from the stack slot. |
182 | Hi = DAG.getLoad(VT: NOutVT, dl, Chain: Store, Ptr: StackPtr, |
183 | PtrInfo: PtrInfo.getWithOffset(O: IncrementSize), Alignment: NOutAlign); |
184 | |
185 | // Handle endianness of the load. |
186 | if (TLI.hasBigEndianPartOrdering(VT: OutVT, DL: DAG.getDataLayout())) |
187 | std::swap(a&: Lo, b&: Hi); |
188 | } |
189 | |
190 | void DAGTypeLegalizer::ExpandRes_BUILD_PAIR(SDNode *N, SDValue &Lo, |
191 | SDValue &Hi) { |
192 | // Return the operands. |
193 | Lo = N->getOperand(Num: 0); |
194 | Hi = N->getOperand(Num: 1); |
195 | } |
196 | |
197 | void DAGTypeLegalizer::ExpandRes_EXTRACT_ELEMENT(SDNode *N, SDValue &Lo, |
198 | SDValue &Hi) { |
199 | GetExpandedOp(Op: N->getOperand(Num: 0), Lo, Hi); |
200 | SDValue Part = N->getConstantOperandVal(Num: 1) ? Hi : Lo; |
201 | |
202 | assert(Part.getValueType() == N->getValueType(0) && |
203 | "Type twice as big as expanded type not itself expanded!" ); |
204 | |
205 | GetPairElements(Pair: Part, Lo, Hi); |
206 | } |
207 | |
208 | void DAGTypeLegalizer::ExpandRes_EXTRACT_VECTOR_ELT(SDNode *N, SDValue &Lo, |
209 | SDValue &Hi) { |
210 | SDValue OldVec = N->getOperand(Num: 0); |
211 | ElementCount OldEltCount = OldVec.getValueType().getVectorElementCount(); |
212 | EVT OldEltVT = OldVec.getValueType().getVectorElementType(); |
213 | SDLoc dl(N); |
214 | |
215 | // Convert to a vector of the expanded element type, for example |
216 | // <3 x i64> -> <6 x i32>. |
217 | EVT OldVT = N->getValueType(ResNo: 0); |
218 | EVT NewVT = TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: OldVT); |
219 | |
220 | if (OldVT != OldEltVT) { |
221 | // The result of EXTRACT_VECTOR_ELT may be larger than the element type of |
222 | // the input vector. If so, extend the elements of the input vector to the |
223 | // same bitwidth as the result before expanding. |
224 | assert(OldEltVT.bitsLT(OldVT) && "Result type smaller then element type!" ); |
225 | EVT NVecVT = EVT::getVectorVT(Context&: *DAG.getContext(), VT: OldVT, EC: OldEltCount); |
226 | OldVec = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL: dl, VT: NVecVT, Operand: N->getOperand(Num: 0)); |
227 | } |
228 | |
229 | SDValue NewVec = DAG.getNode( |
230 | Opcode: ISD::BITCAST, DL: dl, |
231 | VT: EVT::getVectorVT(Context&: *DAG.getContext(), VT: NewVT, EC: OldEltCount * 2), Operand: OldVec); |
232 | |
233 | // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector. |
234 | SDValue Idx = N->getOperand(Num: 1); |
235 | |
236 | Idx = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: Idx.getValueType(), N1: Idx, N2: Idx); |
237 | Lo = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL: dl, VT: NewVT, N1: NewVec, N2: Idx); |
238 | |
239 | Idx = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: Idx.getValueType(), N1: Idx, |
240 | N2: DAG.getConstant(Val: 1, DL: dl, VT: Idx.getValueType())); |
241 | Hi = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL: dl, VT: NewVT, N1: NewVec, N2: Idx); |
242 | |
243 | if (DAG.getDataLayout().isBigEndian()) |
244 | std::swap(a&: Lo, b&: Hi); |
245 | } |
246 | |
247 | void DAGTypeLegalizer::ExpandRes_NormalLoad(SDNode *N, SDValue &Lo, |
248 | SDValue &Hi) { |
249 | assert(ISD::isNormalLoad(N) && "This routine only for normal loads!" ); |
250 | SDLoc dl(N); |
251 | |
252 | LoadSDNode *LD = cast<LoadSDNode>(Val: N); |
253 | assert(!LD->isAtomic() && "Atomics can not be split" ); |
254 | EVT ValueVT = LD->getValueType(ResNo: 0); |
255 | EVT NVT = TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: ValueVT); |
256 | SDValue Chain = LD->getChain(); |
257 | SDValue Ptr = LD->getBasePtr(); |
258 | AAMDNodes AAInfo = LD->getAAInfo(); |
259 | |
260 | assert(NVT.isByteSized() && "Expanded type not byte sized!" ); |
261 | |
262 | Lo = DAG.getLoad(VT: NVT, dl, Chain, Ptr, PtrInfo: LD->getPointerInfo(), |
263 | Alignment: LD->getBaseAlign(), MMOFlags: LD->getMemOperand()->getFlags(), AAInfo); |
264 | |
265 | // Increment the pointer to the other half. |
266 | unsigned IncrementSize = NVT.getSizeInBits() / 8; |
267 | Ptr = DAG.getObjectPtrOffset(SL: dl, Ptr, Offset: TypeSize::getFixed(ExactSize: IncrementSize)); |
268 | Hi = DAG.getLoad(VT: NVT, dl, Chain, Ptr, |
269 | PtrInfo: LD->getPointerInfo().getWithOffset(O: IncrementSize), |
270 | Alignment: LD->getBaseAlign(), MMOFlags: LD->getMemOperand()->getFlags(), AAInfo); |
271 | |
272 | // Build a factor node to remember that this load is independent of the |
273 | // other one. |
274 | Chain = DAG.getNode(Opcode: ISD::TokenFactor, DL: dl, VT: MVT::Other, N1: Lo.getValue(R: 1), |
275 | N2: Hi.getValue(R: 1)); |
276 | |
277 | // Handle endianness of the load. |
278 | if (TLI.hasBigEndianPartOrdering(VT: ValueVT, DL: DAG.getDataLayout())) |
279 | std::swap(a&: Lo, b&: Hi); |
280 | |
281 | // Modified the chain - switch anything that used the old chain to use |
282 | // the new one. |
283 | ReplaceValueWith(From: SDValue(N, 1), To: Chain); |
284 | } |
285 | |
286 | void DAGTypeLegalizer::ExpandRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) { |
287 | EVT OVT = N->getValueType(ResNo: 0); |
288 | EVT NVT = TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: OVT); |
289 | SDValue Chain = N->getOperand(Num: 0); |
290 | SDValue Ptr = N->getOperand(Num: 1); |
291 | SDLoc dl(N); |
292 | const unsigned Align = N->getConstantOperandVal(Num: 3); |
293 | |
294 | Lo = DAG.getVAArg(VT: NVT, dl, Chain, Ptr, SV: N->getOperand(Num: 2), Align); |
295 | Hi = DAG.getVAArg(VT: NVT, dl, Chain: Lo.getValue(R: 1), Ptr, SV: N->getOperand(Num: 2), Align: 0); |
296 | Chain = Hi.getValue(R: 1); |
297 | |
298 | // Handle endianness of the load. |
299 | if (TLI.hasBigEndianPartOrdering(VT: OVT, DL: DAG.getDataLayout())) |
300 | std::swap(a&: Lo, b&: Hi); |
301 | |
302 | // Modified the chain - switch anything that used the old chain to use |
303 | // the new one. |
304 | ReplaceValueWith(From: SDValue(N, 1), To: Chain); |
305 | } |
306 | |
307 | |
308 | //===--------------------------------------------------------------------===// |
309 | // Generic Operand Expansion. |
310 | //===--------------------------------------------------------------------===// |
311 | |
312 | void DAGTypeLegalizer::IntegerToVector(SDValue Op, unsigned NumElements, |
313 | SmallVectorImpl<SDValue> &Ops, |
314 | EVT EltVT) { |
315 | assert(Op.getValueType().isInteger()); |
316 | SDLoc DL(Op); |
317 | SDValue Parts[2]; |
318 | |
319 | if (NumElements > 1) { |
320 | NumElements >>= 1; |
321 | SplitInteger(Op, Lo&: Parts[0], Hi&: Parts[1]); |
322 | if (DAG.getDataLayout().isBigEndian()) |
323 | std::swap(a&: Parts[0], b&: Parts[1]); |
324 | IntegerToVector(Op: Parts[0], NumElements, Ops, EltVT); |
325 | IntegerToVector(Op: Parts[1], NumElements, Ops, EltVT); |
326 | } else { |
327 | Ops.push_back(Elt: DAG.getNode(Opcode: ISD::BITCAST, DL, VT: EltVT, Operand: Op)); |
328 | } |
329 | } |
330 | |
331 | SDValue DAGTypeLegalizer::ExpandOp_BITCAST(SDNode *N) { |
332 | SDLoc dl(N); |
333 | if (N->getValueType(ResNo: 0).isVector() && |
334 | N->getOperand(Num: 0).getValueType().isInteger()) { |
335 | // An illegal expanding type is being converted to a legal vector type. |
336 | // Make a two element vector out of the expanded parts and convert that |
337 | // instead, but only if the new vector type is legal (otherwise there |
338 | // is no point, and it might create expansion loops). For example, on |
339 | // x86 this turns v1i64 = BITCAST i64 into v1i64 = BITCAST v2i32. |
340 | // |
341 | // FIXME: I'm not sure why we are first trying to split the input into |
342 | // a 2 element vector, so I'm leaving it here to maintain the current |
343 | // behavior. |
344 | unsigned NumElts = 2; |
345 | EVT OVT = N->getOperand(Num: 0).getValueType(); |
346 | EVT NVT = EVT::getVectorVT(Context&: *DAG.getContext(), |
347 | VT: TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: OVT), |
348 | NumElements: NumElts); |
349 | if (!isTypeLegal(VT: NVT)) { |
350 | // If we can't find a legal type by splitting the integer in half, |
351 | // then we can use the node's value type. |
352 | NumElts = N->getValueType(ResNo: 0).getVectorNumElements(); |
353 | NVT = N->getValueType(ResNo: 0); |
354 | } |
355 | |
356 | SmallVector<SDValue, 8> Ops; |
357 | IntegerToVector(Op: N->getOperand(Num: 0), NumElements: NumElts, Ops, EltVT: NVT.getVectorElementType()); |
358 | |
359 | SDValue Vec = DAG.getBuildVector(VT: NVT, DL: dl, Ops: ArrayRef(Ops.data(), NumElts)); |
360 | return DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: N->getValueType(ResNo: 0), Operand: Vec); |
361 | } |
362 | |
363 | // Otherwise, store to a temporary and load out again as the new type. |
364 | return CreateStackStoreLoad(Op: N->getOperand(Num: 0), DestVT: N->getValueType(ResNo: 0)); |
365 | } |
366 | |
367 | SDValue DAGTypeLegalizer::ExpandOp_BUILD_VECTOR(SDNode *N) { |
368 | // The vector type is legal but the element type needs expansion. |
369 | EVT VecVT = N->getValueType(ResNo: 0); |
370 | unsigned NumElts = VecVT.getVectorNumElements(); |
371 | EVT OldVT = N->getOperand(Num: 0).getValueType(); |
372 | EVT NewVT = TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: OldVT); |
373 | SDLoc dl(N); |
374 | |
375 | assert(OldVT == VecVT.getVectorElementType() && |
376 | "BUILD_VECTOR operand type doesn't match vector element type!" ); |
377 | |
378 | if (VecVT.isInteger() && TLI.isOperationLegal(Op: ISD::SPLAT_VECTOR, VT: VecVT) && |
379 | TLI.isOperationLegalOrCustom(Op: ISD::SPLAT_VECTOR_PARTS, VT: VecVT)) { |
380 | if (SDValue V = cast<BuildVectorSDNode>(Val: N)->getSplatValue()) { |
381 | SDValue Lo, Hi; |
382 | GetExpandedOp(Op: V, Lo, Hi); |
383 | return DAG.getNode(Opcode: ISD::SPLAT_VECTOR_PARTS, DL: dl, VT: VecVT, N1: Lo, N2: Hi); |
384 | } |
385 | } |
386 | |
387 | // Build a vector of twice the length out of the expanded elements. |
388 | // For example <3 x i64> -> <6 x i32>. |
389 | SmallVector<SDValue, 16> NewElts; |
390 | NewElts.reserve(N: NumElts*2); |
391 | |
392 | for (unsigned i = 0; i < NumElts; ++i) { |
393 | SDValue Lo, Hi; |
394 | GetExpandedOp(Op: N->getOperand(Num: i), Lo, Hi); |
395 | if (DAG.getDataLayout().isBigEndian()) |
396 | std::swap(a&: Lo, b&: Hi); |
397 | NewElts.push_back(Elt: Lo); |
398 | NewElts.push_back(Elt: Hi); |
399 | } |
400 | |
401 | EVT NewVecVT = EVT::getVectorVT(Context&: *DAG.getContext(), VT: NewVT, NumElements: NewElts.size()); |
402 | SDValue NewVec = DAG.getBuildVector(VT: NewVecVT, DL: dl, Ops: NewElts); |
403 | |
404 | // Convert the new vector to the old vector type. |
405 | return DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: VecVT, Operand: NewVec); |
406 | } |
407 | |
408 | SDValue DAGTypeLegalizer::ExpandOp_EXTRACT_ELEMENT(SDNode *N) { |
409 | SDValue Lo, Hi; |
410 | GetExpandedOp(Op: N->getOperand(Num: 0), Lo, Hi); |
411 | return N->getConstantOperandVal(Num: 1) ? Hi : Lo; |
412 | } |
413 | |
414 | // Split the integer operand in two and create a second FAKE_USE node for |
415 | // the other half. The original SDNode is updated in place. |
416 | SDValue DAGTypeLegalizer::ExpandOp_FAKE_USE(SDNode *N) { |
417 | SDValue Lo, Hi; |
418 | SDValue Chain = N->getOperand(Num: 0); |
419 | GetExpandedOp(Op: N->getOperand(Num: 1), Lo, Hi); |
420 | SDValue LoUse = DAG.getNode(Opcode: ISD::FAKE_USE, DL: SDLoc(), VT: MVT::Other, N1: Chain, N2: Lo); |
421 | DAG.UpdateNodeOperands(N, Op1: LoUse, Op2: Hi); |
422 | return SDValue(N, 0); |
423 | } |
424 | |
425 | SDValue DAGTypeLegalizer::ExpandOp_INSERT_VECTOR_ELT(SDNode *N) { |
426 | // The vector type is legal but the element type needs expansion. |
427 | EVT VecVT = N->getValueType(ResNo: 0); |
428 | unsigned NumElts = VecVT.getVectorNumElements(); |
429 | SDLoc dl(N); |
430 | |
431 | SDValue Val = N->getOperand(Num: 1); |
432 | EVT OldEVT = Val.getValueType(); |
433 | EVT NewEVT = TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: OldEVT); |
434 | |
435 | assert(OldEVT == VecVT.getVectorElementType() && |
436 | "Inserted element type doesn't match vector element type!" ); |
437 | |
438 | // Bitconvert to a vector of twice the length with elements of the expanded |
439 | // type, insert the expanded vector elements, and then convert back. |
440 | EVT NewVecVT = EVT::getVectorVT(Context&: *DAG.getContext(), VT: NewEVT, NumElements: NumElts*2); |
441 | SDValue NewVec = DAG.getNode(Opcode: ISD::BITCAST, DL: dl, |
442 | VT: NewVecVT, Operand: N->getOperand(Num: 0)); |
443 | |
444 | SDValue Lo, Hi; |
445 | GetExpandedOp(Op: Val, Lo, Hi); |
446 | if (DAG.getDataLayout().isBigEndian()) |
447 | std::swap(a&: Lo, b&: Hi); |
448 | |
449 | SDValue Idx = N->getOperand(Num: 2); |
450 | Idx = DAG.getNode(Opcode: ISD::ADD, DL: dl, VT: Idx.getValueType(), N1: Idx, N2: Idx); |
451 | NewVec = DAG.getNode(Opcode: ISD::INSERT_VECTOR_ELT, DL: dl, VT: NewVecVT, N1: NewVec, N2: Lo, N3: Idx); |
452 | Idx = DAG.getNode(Opcode: ISD::ADD, DL: dl, |
453 | VT: Idx.getValueType(), N1: Idx, |
454 | N2: DAG.getConstant(Val: 1, DL: dl, VT: Idx.getValueType())); |
455 | NewVec = DAG.getNode(Opcode: ISD::INSERT_VECTOR_ELT, DL: dl, VT: NewVecVT, N1: NewVec, N2: Hi, N3: Idx); |
456 | |
457 | // Convert the new vector to the old vector type. |
458 | return DAG.getNode(Opcode: ISD::BITCAST, DL: dl, VT: VecVT, Operand: NewVec); |
459 | } |
460 | |
461 | SDValue DAGTypeLegalizer::ExpandOp_SCALAR_TO_VECTOR(SDNode *N) { |
462 | SDLoc dl(N); |
463 | EVT VT = N->getValueType(ResNo: 0); |
464 | assert(VT.getVectorElementType() == N->getOperand(0).getValueType() && |
465 | "SCALAR_TO_VECTOR operand type doesn't match vector element type!" ); |
466 | unsigned NumElts = VT.getVectorNumElements(); |
467 | SmallVector<SDValue, 16> Ops(NumElts); |
468 | Ops[0] = N->getOperand(Num: 0); |
469 | SDValue UndefVal = DAG.getUNDEF(VT: Ops[0].getValueType()); |
470 | for (unsigned i = 1; i < NumElts; ++i) |
471 | Ops[i] = UndefVal; |
472 | return DAG.getBuildVector(VT, DL: dl, Ops); |
473 | } |
474 | |
475 | SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) { |
476 | assert(ISD::isNormalStore(N) && "This routine only for normal stores!" ); |
477 | assert(OpNo == 1 && "Can only expand the stored value so far" ); |
478 | SDLoc dl(N); |
479 | |
480 | StoreSDNode *St = cast<StoreSDNode>(Val: N); |
481 | assert(!St->isAtomic() && "Atomics can not be split" ); |
482 | EVT ValueVT = St->getValue().getValueType(); |
483 | EVT NVT = TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: ValueVT); |
484 | SDValue Chain = St->getChain(); |
485 | SDValue Ptr = St->getBasePtr(); |
486 | AAMDNodes AAInfo = St->getAAInfo(); |
487 | |
488 | assert(NVT.isByteSized() && "Expanded type not byte sized!" ); |
489 | unsigned IncrementSize = NVT.getSizeInBits() / 8; |
490 | |
491 | SDValue Lo, Hi; |
492 | GetExpandedOp(Op: St->getValue(), Lo, Hi); |
493 | |
494 | if (TLI.hasBigEndianPartOrdering(VT: ValueVT, DL: DAG.getDataLayout())) |
495 | std::swap(a&: Lo, b&: Hi); |
496 | |
497 | Lo = |
498 | DAG.getStore(Chain, dl, Val: Lo, Ptr, PtrInfo: St->getPointerInfo(), Alignment: St->getBaseAlign(), |
499 | MMOFlags: St->getMemOperand()->getFlags(), AAInfo); |
500 | |
501 | Ptr = DAG.getObjectPtrOffset(SL: dl, Ptr, Offset: TypeSize::getFixed(ExactSize: IncrementSize)); |
502 | Hi = DAG.getStore( |
503 | Chain, dl, Val: Hi, Ptr, PtrInfo: St->getPointerInfo().getWithOffset(O: IncrementSize), |
504 | Alignment: St->getBaseAlign(), MMOFlags: St->getMemOperand()->getFlags(), AAInfo); |
505 | |
506 | return DAG.getNode(Opcode: ISD::TokenFactor, DL: dl, VT: MVT::Other, N1: Lo, N2: Hi); |
507 | } |
508 | |
509 | |
510 | //===--------------------------------------------------------------------===// |
511 | // Generic Result Splitting. |
512 | //===--------------------------------------------------------------------===// |
513 | |
514 | // Be careful to make no assumptions about which of Lo/Hi is stored first in |
515 | // memory (for vectors it is always Lo first followed by Hi in the following |
516 | // bytes; for integers and floats it is Lo first if and only if the machine is |
517 | // little-endian). |
518 | |
519 | void DAGTypeLegalizer::SplitRes_MERGE_VALUES(SDNode *N, unsigned ResNo, |
520 | SDValue &Lo, SDValue &Hi) { |
521 | SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); |
522 | GetSplitOp(Op, Lo, Hi); |
523 | } |
524 | |
525 | void DAGTypeLegalizer::SplitRes_Select(SDNode *N, SDValue &Lo, SDValue &Hi) { |
526 | SDValue LL, LH, RL, RH, CL, CH; |
527 | SDLoc dl(N); |
528 | unsigned Opcode = N->getOpcode(); |
529 | GetSplitOp(Op: N->getOperand(Num: 1), Lo&: LL, Hi&: LH); |
530 | GetSplitOp(Op: N->getOperand(Num: 2), Lo&: RL, Hi&: RH); |
531 | |
532 | SDValue Cond = N->getOperand(Num: 0); |
533 | CL = CH = Cond; |
534 | if (Cond.getValueType().isVector()) { |
535 | if (SDValue Res = WidenVSELECTMask(N)) |
536 | std::tie(args&: CL, args&: CH) = DAG.SplitVector(N: Res, DL: dl); |
537 | // Check if there are already splitted versions of the vector available and |
538 | // use those instead of splitting the mask operand again. |
539 | else if (getTypeAction(VT: Cond.getValueType()) == |
540 | TargetLowering::TypeSplitVector) |
541 | GetSplitVector(Op: Cond, Lo&: CL, Hi&: CH); |
542 | // It seems to improve code to generate two narrow SETCCs as opposed to |
543 | // splitting a wide result vector. |
544 | else if (Cond.getOpcode() == ISD::SETCC) { |
545 | // If the condition is a vXi1 vector, and the LHS of the setcc is a legal |
546 | // type and the setcc result type is the same vXi1, then leave the setcc |
547 | // alone. |
548 | EVT CondLHSVT = Cond.getOperand(i: 0).getValueType(); |
549 | if (Cond.getValueType().getVectorElementType() == MVT::i1 && |
550 | isTypeLegal(VT: CondLHSVT) && |
551 | getSetCCResultType(VT: CondLHSVT) == Cond.getValueType()) |
552 | std::tie(args&: CL, args&: CH) = DAG.SplitVector(N: Cond, DL: dl); |
553 | else |
554 | SplitVecRes_SETCC(N: Cond.getNode(), Lo&: CL, Hi&: CH); |
555 | } else |
556 | std::tie(args&: CL, args&: CH) = DAG.SplitVector(N: Cond, DL: dl); |
557 | } |
558 | |
559 | if (Opcode != ISD::VP_SELECT && Opcode != ISD::VP_MERGE) { |
560 | Lo = DAG.getNode(Opcode, DL: dl, VT: LL.getValueType(), N1: CL, N2: LL, N3: RL); |
561 | Hi = DAG.getNode(Opcode, DL: dl, VT: LH.getValueType(), N1: CH, N2: LH, N3: RH); |
562 | return; |
563 | } |
564 | |
565 | SDValue EVLLo, EVLHi; |
566 | std::tie(args&: EVLLo, args&: EVLHi) = |
567 | DAG.SplitEVL(N: N->getOperand(Num: 3), VecVT: N->getValueType(ResNo: 0), DL: dl); |
568 | |
569 | Lo = DAG.getNode(Opcode, DL: dl, VT: LL.getValueType(), N1: CL, N2: LL, N3: RL, N4: EVLLo); |
570 | Hi = DAG.getNode(Opcode, DL: dl, VT: LH.getValueType(), N1: CH, N2: LH, N3: RH, N4: EVLHi); |
571 | } |
572 | |
573 | void DAGTypeLegalizer::SplitRes_SELECT_CC(SDNode *N, SDValue &Lo, |
574 | SDValue &Hi) { |
575 | SDValue LL, LH, RL, RH; |
576 | SDLoc dl(N); |
577 | GetSplitOp(Op: N->getOperand(Num: 2), Lo&: LL, Hi&: LH); |
578 | GetSplitOp(Op: N->getOperand(Num: 3), Lo&: RL, Hi&: RH); |
579 | |
580 | Lo = DAG.getNode(Opcode: ISD::SELECT_CC, DL: dl, VT: LL.getValueType(), N1: N->getOperand(Num: 0), |
581 | N2: N->getOperand(Num: 1), N3: LL, N4: RL, N5: N->getOperand(Num: 4)); |
582 | Hi = DAG.getNode(Opcode: ISD::SELECT_CC, DL: dl, VT: LH.getValueType(), N1: N->getOperand(Num: 0), |
583 | N2: N->getOperand(Num: 1), N3: LH, N4: RH, N5: N->getOperand(Num: 4)); |
584 | } |
585 | |
586 | void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi) { |
587 | EVT LoVT, HiVT; |
588 | std::tie(args&: LoVT, args&: HiVT) = DAG.GetSplitDestVTs(VT: N->getValueType(ResNo: 0)); |
589 | Lo = DAG.getUNDEF(VT: LoVT); |
590 | Hi = DAG.getUNDEF(VT: HiVT); |
591 | } |
592 | |
593 | void DAGTypeLegalizer::SplitVecRes_AssertZext(SDNode *N, SDValue &Lo, |
594 | SDValue &Hi) { |
595 | SDValue L, H; |
596 | SDLoc dl(N); |
597 | GetSplitOp(Op: N->getOperand(Num: 0), Lo&: L, Hi&: H); |
598 | |
599 | Lo = DAG.getNode(Opcode: ISD::AssertZext, DL: dl, VT: L.getValueType(), N1: L, N2: N->getOperand(Num: 1)); |
600 | Hi = DAG.getNode(Opcode: ISD::AssertZext, DL: dl, VT: H.getValueType(), N1: H, N2: N->getOperand(Num: 1)); |
601 | } |
602 | |
603 | void DAGTypeLegalizer::SplitRes_FREEZE(SDNode *N, SDValue &Lo, SDValue &Hi) { |
604 | SDValue L, H; |
605 | SDLoc dl(N); |
606 | GetSplitOp(Op: N->getOperand(Num: 0), Lo&: L, Hi&: H); |
607 | |
608 | Lo = DAG.getNode(Opcode: ISD::FREEZE, DL: dl, VT: L.getValueType(), Operand: L); |
609 | Hi = DAG.getNode(Opcode: ISD::FREEZE, DL: dl, VT: H.getValueType(), Operand: H); |
610 | } |
611 | |
612 | void DAGTypeLegalizer::SplitRes_ARITH_FENCE(SDNode *N, SDValue &Lo, |
613 | SDValue &Hi) { |
614 | SDValue L, H; |
615 | SDLoc DL(N); |
616 | GetSplitOp(Op: N->getOperand(Num: 0), Lo&: L, Hi&: H); |
617 | |
618 | Lo = DAG.getNode(Opcode: ISD::ARITH_FENCE, DL, VT: L.getValueType(), Operand: L); |
619 | Hi = DAG.getNode(Opcode: ISD::ARITH_FENCE, DL, VT: H.getValueType(), Operand: H); |
620 | } |
621 | |