Chris Lattner | 13c6a17 | 2007-12-08 22:37:41 +0000 | [diff] [blame] | 1 | //===-- LegalizeTypesSplit.cpp - Vector Splitting for LegalizeTypes -------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
Chris Lattner | 4ee451d | 2007-12-29 20:36:04 +0000 | [diff] [blame^] | 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
Chris Lattner | 13c6a17 | 2007-12-08 22:37:41 +0000 | [diff] [blame] | 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements vector splitting support for LegalizeTypes. Vector |
| 11 | // splitting is the act of changing a computation in an invalid vector type to |
| 12 | // be a computation in multiple vectors of a smaller type. For example, |
| 13 | // implementing <128 x f32> operations in terms of two <64 x f32> operations. |
| 14 | // |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | |
| 17 | #include "LegalizeTypes.h" |
| 18 | using namespace llvm; |
| 19 | |
Chris Lattner | 697b53e | 2007-12-08 23:08:49 +0000 | [diff] [blame] | 20 | /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector |
| 21 | /// type that needs to be split. This handles non-power of two vectors. |
| 22 | static void GetSplitDestVTs(MVT::ValueType InVT, |
| 23 | MVT::ValueType &Lo, MVT::ValueType &Hi) { |
| 24 | MVT::ValueType NewEltVT = MVT::getVectorElementType(InVT); |
| 25 | unsigned NumElements = MVT::getVectorNumElements(InVT); |
| 26 | if ((NumElements & (NumElements-1)) == 0) { // Simple power of two vector. |
| 27 | NumElements >>= 1; |
| 28 | Lo = Hi = MVT::getVectorType(NewEltVT, NumElements); |
| 29 | } else { // Non-power-of-two vectors. |
Chris Lattner | 46a6e79 | 2007-12-09 17:56:34 +0000 | [diff] [blame] | 30 | unsigned NewNumElts_Lo = 1 << Log2_32(NumElements); |
Chris Lattner | 697b53e | 2007-12-08 23:08:49 +0000 | [diff] [blame] | 31 | unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo; |
| 32 | Lo = MVT::getVectorType(NewEltVT, NewNumElts_Lo); |
| 33 | Hi = MVT::getVectorType(NewEltVT, NewNumElts_Hi); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | |
Chris Lattner | 13c6a17 | 2007-12-08 22:37:41 +0000 | [diff] [blame] | 38 | //===----------------------------------------------------------------------===// |
| 39 | // Result Vector Splitting |
| 40 | //===----------------------------------------------------------------------===// |
| 41 | |
| 42 | /// SplitResult - This method is called when the specified result of the |
| 43 | /// specified node is found to need vector splitting. At this point, the node |
| 44 | /// may also have invalid operands or may have other results that need |
| 45 | /// legalization, we just know that (at least) one result needs vector |
| 46 | /// splitting. |
| 47 | void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { |
| 48 | DEBUG(cerr << "Expand node result: "; N->dump(&DAG); cerr << "\n"); |
| 49 | SDOperand Lo, Hi; |
Chris Lattner | 13c6a17 | 2007-12-08 22:37:41 +0000 | [diff] [blame] | 50 | |
| 51 | #if 0 |
| 52 | // See if the target wants to custom expand this node. |
| 53 | if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == |
| 54 | TargetLowering::Custom) { |
| 55 | // If the target wants to, allow it to lower this itself. |
| 56 | if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { |
| 57 | // Everything that once used N now uses P. We are guaranteed that the |
| 58 | // result value types of N and the result value types of P match. |
| 59 | ReplaceNodeWith(N, P); |
| 60 | return; |
| 61 | } |
| 62 | } |
| 63 | #endif |
| 64 | |
| 65 | switch (N->getOpcode()) { |
| 66 | default: |
| 67 | #ifndef NDEBUG |
| 68 | cerr << "SplitResult #" << ResNo << ": "; |
| 69 | N->dump(&DAG); cerr << "\n"; |
| 70 | #endif |
| 71 | assert(0 && "Do not know how to split the result of this operator!"); |
| 72 | abort(); |
| 73 | |
Chris Lattner | eeaad40 | 2007-12-08 23:58:27 +0000 | [diff] [blame] | 74 | case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; |
| 75 | case ISD::LOAD: SplitRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); break; |
| 76 | case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break; |
| 77 | case ISD::INSERT_VECTOR_ELT:SplitRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; |
| 78 | case ISD::VECTOR_SHUFFLE: SplitRes_VECTOR_SHUFFLE(N, Lo, Hi); break; |
| 79 | case ISD::BUILD_VECTOR: SplitRes_BUILD_VECTOR(N, Lo, Hi); break; |
| 80 | case ISD::CONCAT_VECTORS: SplitRes_CONCAT_VECTORS(N, Lo, Hi); break; |
| 81 | case ISD::BIT_CONVERT: SplitRes_BIT_CONVERT(N, Lo, Hi); break; |
| 82 | case ISD::CTTZ: |
| 83 | case ISD::CTLZ: |
| 84 | case ISD::CTPOP: |
| 85 | case ISD::FNEG: |
| 86 | case ISD::FABS: |
| 87 | case ISD::FSQRT: |
| 88 | case ISD::FSIN: |
| 89 | case ISD::FCOS: |
| 90 | case ISD::FP_TO_SINT: |
| 91 | case ISD::FP_TO_UINT: |
| 92 | case ISD::SINT_TO_FP: |
| 93 | case ISD::UINT_TO_FP: SplitRes_UnOp(N, Lo, Hi); break; |
Chris Lattner | 697b53e | 2007-12-08 23:08:49 +0000 | [diff] [blame] | 94 | case ISD::ADD: |
| 95 | case ISD::SUB: |
| 96 | case ISD::MUL: |
| 97 | case ISD::FADD: |
| 98 | case ISD::FSUB: |
| 99 | case ISD::FMUL: |
| 100 | case ISD::SDIV: |
| 101 | case ISD::UDIV: |
| 102 | case ISD::FDIV: |
| 103 | case ISD::FPOW: |
| 104 | case ISD::AND: |
| 105 | case ISD::OR: |
| 106 | case ISD::XOR: |
| 107 | case ISD::UREM: |
| 108 | case ISD::SREM: |
Chris Lattner | eeaad40 | 2007-12-08 23:58:27 +0000 | [diff] [blame] | 109 | case ISD::FREM: SplitRes_BinOp(N, Lo, Hi); break; |
| 110 | case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break; |
| 111 | case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; |
Chris Lattner | 13c6a17 | 2007-12-08 22:37:41 +0000 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | // If Lo/Hi is null, the sub-method took care of registering results etc. |
| 115 | if (Lo.Val) |
| 116 | SetSplitOp(SDOperand(N, ResNo), Lo, Hi); |
| 117 | } |
| 118 | |
Chris Lattner | 697b53e | 2007-12-08 23:08:49 +0000 | [diff] [blame] | 119 | void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { |
| 120 | MVT::ValueType LoVT, HiVT; |
| 121 | GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); |
| 122 | |
| 123 | Lo = DAG.getNode(ISD::UNDEF, LoVT); |
| 124 | Hi = DAG.getNode(ISD::UNDEF, HiVT); |
| 125 | } |
| 126 | |
| 127 | void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD, |
| 128 | SDOperand &Lo, SDOperand &Hi) { |
| 129 | MVT::ValueType LoVT, HiVT; |
| 130 | GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT); |
| 131 | |
| 132 | SDOperand Ch = LD->getChain(); |
| 133 | SDOperand Ptr = LD->getBasePtr(); |
| 134 | const Value *SV = LD->getSrcValue(); |
| 135 | int SVOffset = LD->getSrcValueOffset(); |
| 136 | unsigned Alignment = LD->getAlignment(); |
| 137 | bool isVolatile = LD->isVolatile(); |
| 138 | |
| 139 | Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); |
| 140 | unsigned IncrementSize = MVT::getSizeInBits(LoVT)/8; |
| 141 | Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, |
| 142 | getIntPtrConstant(IncrementSize)); |
| 143 | SVOffset += IncrementSize; |
| 144 | Alignment = MinAlign(Alignment, IncrementSize); |
| 145 | Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); |
| 146 | |
| 147 | // Build a factor node to remember that this load is independent of the |
| 148 | // other one. |
| 149 | SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), |
| 150 | Hi.getValue(1)); |
| 151 | |
| 152 | // Legalized the chain result - switch anything that used the old chain to |
| 153 | // use the new one. |
| 154 | ReplaceValueWith(SDOperand(LD, 1), TF); |
| 155 | } |
| 156 | |
Chris Lattner | eeaad40 | 2007-12-08 23:58:27 +0000 | [diff] [blame] | 157 | void DAGTypeLegalizer::SplitRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, |
| 158 | SDOperand &Hi) { |
| 159 | Lo = N->getOperand(0); |
| 160 | Hi = N->getOperand(1); |
| 161 | } |
| 162 | |
| 163 | void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, |
| 164 | SDOperand &Hi) { |
| 165 | GetSplitOp(N->getOperand(0), Lo, Hi); |
| 166 | unsigned Index = cast<ConstantSDNode>(N->getOperand(2))->getValue(); |
| 167 | SDOperand ScalarOp = N->getOperand(1); |
| 168 | unsigned LoNumElts = MVT::getVectorNumElements(Lo.getValueType()); |
| 169 | if (Index < LoNumElts) |
| 170 | Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, Lo.getValueType(), Lo, ScalarOp, |
| 171 | N->getOperand(2)); |
| 172 | else |
| 173 | Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi, ScalarOp, |
| 174 | DAG.getConstant(Index - LoNumElts, TLI.getPointerTy())); |
| 175 | |
| 176 | } |
| 177 | |
| 178 | void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, |
| 179 | SDOperand &Lo, SDOperand &Hi) { |
| 180 | // Build the low part. |
| 181 | SDOperand Mask = N->getOperand(2); |
| 182 | SmallVector<SDOperand, 16> Ops; |
| 183 | MVT::ValueType PtrVT = TLI.getPointerTy(); |
| 184 | |
| 185 | MVT::ValueType LoVT, HiVT; |
| 186 | GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); |
| 187 | MVT::ValueType EltVT = MVT::getVectorElementType(LoVT); |
| 188 | unsigned LoNumElts = MVT::getVectorNumElements(LoVT); |
| 189 | unsigned NumElements = Mask.getNumOperands(); |
| 190 | |
| 191 | // Insert all of the elements from the input that are needed. We use |
| 192 | // buildvector of extractelement here because the input vectors will have |
| 193 | // to be legalized, so this makes the code simpler. |
| 194 | for (unsigned i = 0; i != LoNumElts; ++i) { |
| 195 | unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue(); |
| 196 | SDOperand InVec = N->getOperand(0); |
| 197 | if (Idx >= NumElements) { |
| 198 | InVec = N->getOperand(1); |
| 199 | Idx -= NumElements; |
| 200 | } |
| 201 | Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec, |
| 202 | DAG.getConstant(Idx, PtrVT))); |
| 203 | } |
| 204 | Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &Ops[0], Ops.size()); |
| 205 | Ops.clear(); |
| 206 | |
| 207 | for (unsigned i = LoNumElts; i != NumElements; ++i) { |
| 208 | unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue(); |
| 209 | SDOperand InVec = N->getOperand(0); |
| 210 | if (Idx >= NumElements) { |
| 211 | InVec = N->getOperand(1); |
| 212 | Idx -= NumElements; |
| 213 | } |
| 214 | Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec, |
| 215 | DAG.getConstant(Idx, PtrVT))); |
| 216 | } |
| 217 | Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size()); |
| 218 | } |
| 219 | |
| 220 | void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, |
| 221 | SDOperand &Hi) { |
| 222 | MVT::ValueType LoVT, HiVT; |
| 223 | GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); |
| 224 | unsigned LoNumElts = MVT::getVectorNumElements(LoVT); |
| 225 | SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts); |
| 226 | Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &LoOps[0], LoOps.size()); |
| 227 | |
| 228 | SmallVector<SDOperand, 8> HiOps(N->op_begin()+LoNumElts, N->op_end()); |
| 229 | Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size()); |
| 230 | } |
| 231 | |
| 232 | void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N, |
| 233 | SDOperand &Lo, SDOperand &Hi) { |
| 234 | // FIXME: Handle non-power-of-two vectors? |
| 235 | unsigned NumSubvectors = N->getNumOperands() / 2; |
| 236 | if (NumSubvectors == 1) { |
| 237 | Lo = N->getOperand(0); |
| 238 | Hi = N->getOperand(1); |
| 239 | return; |
| 240 | } |
| 241 | |
| 242 | MVT::ValueType LoVT, HiVT; |
| 243 | GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); |
| 244 | |
| 245 | SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors); |
| 246 | Lo = DAG.getNode(ISD::CONCAT_VECTORS, LoVT, &LoOps[0], LoOps.size()); |
| 247 | |
| 248 | SmallVector<SDOperand, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end()); |
| 249 | Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size()); |
| 250 | } |
| 251 | |
| 252 | void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, |
| 253 | SDOperand &Lo, SDOperand &Hi) { |
| 254 | // We know the result is a vector. The input may be either a vector or a |
| 255 | // scalar value. |
| 256 | SDOperand InOp = N->getOperand(0); |
| 257 | if (MVT::isVector(InOp.getValueType()) && |
| 258 | MVT::getVectorNumElements(InOp.getValueType()) != 1) { |
| 259 | // If this is a vector, split the vector and convert each of the pieces now. |
| 260 | GetSplitOp(InOp, Lo, Hi); |
| 261 | |
| 262 | MVT::ValueType LoVT, HiVT; |
| 263 | GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); |
| 264 | |
| 265 | Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); |
| 266 | Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); |
| 267 | return; |
| 268 | } |
| 269 | |
| 270 | // Lower the bit-convert to a store/load from the stack, then split the load. |
| 271 | SDOperand Op = CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); |
| 272 | SplitRes_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi); |
| 273 | } |
| 274 | |
Chris Lattner | 697b53e | 2007-12-08 23:08:49 +0000 | [diff] [blame] | 275 | void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { |
| 276 | SDOperand LHSLo, LHSHi; |
| 277 | GetSplitOp(N->getOperand(0), LHSLo, LHSHi); |
| 278 | SDOperand RHSLo, RHSHi; |
| 279 | GetSplitOp(N->getOperand(1), RHSLo, RHSHi); |
| 280 | |
| 281 | Lo = DAG.getNode(N->getOpcode(), LHSLo.getValueType(), LHSLo, RHSLo); |
| 282 | Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi); |
| 283 | } |
| 284 | |
Chris Lattner | eeaad40 | 2007-12-08 23:58:27 +0000 | [diff] [blame] | 285 | void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { |
| 286 | // Get the dest types. This doesn't always match input types, e.g. int_to_fp. |
| 287 | MVT::ValueType LoVT, HiVT; |
| 288 | GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); |
| 289 | |
| 290 | GetSplitOp(N->getOperand(0), Lo, Hi); |
| 291 | Lo = DAG.getNode(N->getOpcode(), LoVT, Lo); |
| 292 | Hi = DAG.getNode(N->getOpcode(), HiVT, Hi); |
| 293 | } |
| 294 | |
| 295 | void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) { |
| 296 | GetSplitOp(N->getOperand(0), Lo, Hi); |
| 297 | Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1)); |
| 298 | Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1)); |
| 299 | } |
| 300 | |
| 301 | |
| 302 | void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){ |
| 303 | SDOperand LL, LH, RL, RH; |
| 304 | GetSplitOp(N->getOperand(1), LL, LH); |
| 305 | GetSplitOp(N->getOperand(2), RL, RH); |
| 306 | |
| 307 | SDOperand Cond = N->getOperand(0); |
| 308 | Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL); |
| 309 | Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH); |
| 310 | } |
| 311 | |
Chris Lattner | 13c6a17 | 2007-12-08 22:37:41 +0000 | [diff] [blame] | 312 | |
| 313 | //===----------------------------------------------------------------------===// |
| 314 | // Operand Vector Splitting |
| 315 | //===----------------------------------------------------------------------===// |
| 316 | |
| 317 | /// SplitOperand - This method is called when the specified operand of the |
| 318 | /// specified node is found to need vector splitting. At this point, all of the |
| 319 | /// result types of the node are known to be legal, but other operands of the |
| 320 | /// node may need legalization as well as the specified one. |
| 321 | bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { |
| 322 | DEBUG(cerr << "Split node operand: "; N->dump(&DAG); cerr << "\n"); |
| 323 | SDOperand Res(0, 0); |
| 324 | |
| 325 | #if 0 |
| 326 | if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == |
| 327 | TargetLowering::Custom) |
| 328 | Res = TLI.LowerOperation(SDOperand(N, 0), DAG); |
| 329 | #endif |
| 330 | |
| 331 | if (Res.Val == 0) { |
| 332 | switch (N->getOpcode()) { |
| 333 | default: |
| 334 | #ifndef NDEBUG |
| 335 | cerr << "SplitOperand Op #" << OpNo << ": "; |
| 336 | N->dump(&DAG); cerr << "\n"; |
| 337 | #endif |
| 338 | assert(0 && "Do not know how to split this operator's operand!"); |
| 339 | abort(); |
Chris Lattner | 0097555 | 2007-12-09 00:06:19 +0000 | [diff] [blame] | 340 | case ISD::STORE: Res = SplitOp_STORE(cast<StoreSDNode>(N), OpNo); break; |
| 341 | case ISD::RET: Res = SplitOp_RET(N, OpNo); break; |
Chris Lattner | 13c6a17 | 2007-12-08 22:37:41 +0000 | [diff] [blame] | 342 | } |
| 343 | } |
| 344 | |
| 345 | // If the result is null, the sub-method took care of registering results etc. |
| 346 | if (!Res.Val) return false; |
| 347 | |
| 348 | // If the result is N, the sub-method updated N in place. Check to see if any |
| 349 | // operands are new, and if so, mark them. |
| 350 | if (Res.Val == N) { |
| 351 | // Mark N as new and remark N and its operands. This allows us to correctly |
| 352 | // revisit N if it needs another step of promotion and allows us to visit |
| 353 | // any new operands to N. |
| 354 | N->setNodeId(NewNode); |
| 355 | MarkNewNodes(N); |
| 356 | return true; |
| 357 | } |
| 358 | |
| 359 | assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && |
| 360 | "Invalid operand expansion"); |
| 361 | |
| 362 | ReplaceValueWith(SDOperand(N, 0), Res); |
| 363 | return false; |
| 364 | } |
Chris Lattner | 5018786 | 2007-12-08 23:24:26 +0000 | [diff] [blame] | 365 | |
Chris Lattner | 0097555 | 2007-12-09 00:06:19 +0000 | [diff] [blame] | 366 | SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) { |
Chris Lattner | 5018786 | 2007-12-08 23:24:26 +0000 | [diff] [blame] | 367 | assert(OpNo == 1 && "Can only split the stored value"); |
| 368 | |
| 369 | SDOperand Ch = N->getChain(); |
| 370 | SDOperand Ptr = N->getBasePtr(); |
| 371 | int SVOffset = N->getSrcValueOffset(); |
| 372 | unsigned Alignment = N->getAlignment(); |
| 373 | bool isVol = N->isVolatile(); |
| 374 | SDOperand Lo, Hi; |
| 375 | GetSplitOp(N->getOperand(1), Lo, Hi); |
| 376 | |
| 377 | unsigned IncrementSize = MVT::getSizeInBits(Lo.getValueType())/8; |
| 378 | |
| 379 | Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment); |
| 380 | |
| 381 | // Increment the pointer to the other half. |
| 382 | Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, |
| 383 | getIntPtrConstant(IncrementSize)); |
| 384 | |
| 385 | Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, |
| 386 | isVol, MinAlign(Alignment, IncrementSize)); |
| 387 | return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); |
| 388 | } |
| 389 | |
Chris Lattner | 0097555 | 2007-12-09 00:06:19 +0000 | [diff] [blame] | 390 | SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) { |
| 391 | assert(N->getNumOperands() == 3 &&"Can only handle ret of one vector so far"); |
| 392 | // FIXME: Returns of gcc generic vectors larger than a legal vector |
| 393 | // type should be returned by reference! |
| 394 | SDOperand Lo, Hi; |
| 395 | GetSplitOp(N->getOperand(1), Lo, Hi); |
| 396 | |
| 397 | SDOperand Chain = N->getOperand(0); // The chain. |
| 398 | SDOperand Sign = N->getOperand(2); // Signness |
| 399 | |
| 400 | return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign); |
| 401 | } |