| 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 | |