Mercurial > hg > CbC > CbC_llvm
comparison lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @ 134:3a76565eade5 LLVM5.0.1
update 5.0.1
author | mir3636 |
---|---|
date | Sat, 17 Feb 2018 09:57:20 +0900 |
parents | 803732b1fca8 |
children | c2174574ed3a |
comparison
equal
deleted
inserted
replaced
133:c60214abe0e8 | 134:3a76565eade5 |
---|---|
33 #include "llvm/CodeGen/ISDOpcodes.h" | 33 #include "llvm/CodeGen/ISDOpcodes.h" |
34 #include "llvm/CodeGen/MachineMemOperand.h" | 34 #include "llvm/CodeGen/MachineMemOperand.h" |
35 #include "llvm/CodeGen/MachineValueType.h" | 35 #include "llvm/CodeGen/MachineValueType.h" |
36 #include "llvm/CodeGen/SelectionDAG.h" | 36 #include "llvm/CodeGen/SelectionDAG.h" |
37 #include "llvm/CodeGen/SelectionDAGNodes.h" | 37 #include "llvm/CodeGen/SelectionDAGNodes.h" |
38 #include "llvm/CodeGen/TargetLowering.h" | |
38 #include "llvm/CodeGen/ValueTypes.h" | 39 #include "llvm/CodeGen/ValueTypes.h" |
39 #include "llvm/IR/DataLayout.h" | 40 #include "llvm/IR/DataLayout.h" |
40 #include "llvm/Support/Casting.h" | 41 #include "llvm/Support/Casting.h" |
41 #include "llvm/Support/Compiler.h" | 42 #include "llvm/Support/Compiler.h" |
42 #include "llvm/Support/ErrorHandling.h" | 43 #include "llvm/Support/ErrorHandling.h" |
43 #include "llvm/Support/MathExtras.h" | 44 #include "llvm/Support/MathExtras.h" |
44 #include "llvm/Target/TargetLowering.h" | |
45 #include <cassert> | 45 #include <cassert> |
46 #include <cstdint> | 46 #include <cstdint> |
47 #include <iterator> | 47 #include <iterator> |
48 #include <utility> | 48 #include <utility> |
49 | 49 |
50 using namespace llvm; | 50 using namespace llvm; |
51 | |
52 #define DEBUG_TYPE "legalizevectorops" | |
51 | 53 |
52 namespace { | 54 namespace { |
53 | 55 |
54 class VectorLegalizer { | 56 class VectorLegalizer { |
55 SelectionDAG& DAG; | 57 SelectionDAG& DAG; |
135 /// bitcasting the result back to the original type. | 137 /// bitcasting the result back to the original type. |
136 SDValue Promote(SDValue Op); | 138 SDValue Promote(SDValue Op); |
137 | 139 |
138 /// \brief Implements [SU]INT_TO_FP vector promotion. | 140 /// \brief Implements [SU]INT_TO_FP vector promotion. |
139 /// | 141 /// |
140 /// This is a [zs]ext of the input operand to the next size up. | 142 /// This is a [zs]ext of the input operand to a larger integer type. |
141 SDValue PromoteINT_TO_FP(SDValue Op); | 143 SDValue PromoteINT_TO_FP(SDValue Op); |
142 | 144 |
143 /// \brief Implements FP_TO_[SU]INT vector promotion of the result type. | 145 /// \brief Implements FP_TO_[SU]INT vector promotion of the result type. |
144 /// | 146 /// |
145 /// It is promoted to the next size up integer type. The result is then | 147 /// It is promoted to a larger integer type. The result is then |
146 /// truncated back to the original type. | 148 /// truncated back to the original type. |
147 SDValue PromoteFP_TO_INT(SDValue Op, bool isSigned); | 149 SDValue PromoteFP_TO_INT(SDValue Op); |
148 | 150 |
149 public: | 151 public: |
150 VectorLegalizer(SelectionDAG& dag) : | 152 VectorLegalizer(SelectionDAG& dag) : |
151 DAG(dag), TLI(dag.getTargetLoweringInfo()) {} | 153 DAG(dag), TLI(dag.getTargetLoweringInfo()) {} |
152 | 154 |
224 | 226 |
225 bool HasVectorValue = false; | 227 bool HasVectorValue = false; |
226 if (Op.getOpcode() == ISD::LOAD) { | 228 if (Op.getOpcode() == ISD::LOAD) { |
227 LoadSDNode *LD = cast<LoadSDNode>(Op.getNode()); | 229 LoadSDNode *LD = cast<LoadSDNode>(Op.getNode()); |
228 ISD::LoadExtType ExtType = LD->getExtensionType(); | 230 ISD::LoadExtType ExtType = LD->getExtensionType(); |
229 if (LD->getMemoryVT().isVector() && ExtType != ISD::NON_EXTLOAD) | 231 if (LD->getMemoryVT().isVector() && ExtType != ISD::NON_EXTLOAD) { |
232 DEBUG(dbgs() << "\nLegalizing extending vector load: "; Node->dump(&DAG)); | |
230 switch (TLI.getLoadExtAction(LD->getExtensionType(), LD->getValueType(0), | 233 switch (TLI.getLoadExtAction(LD->getExtensionType(), LD->getValueType(0), |
231 LD->getMemoryVT())) { | 234 LD->getMemoryVT())) { |
232 default: llvm_unreachable("This action is not supported yet!"); | 235 default: llvm_unreachable("This action is not supported yet!"); |
233 case TargetLowering::Legal: | 236 case TargetLowering::Legal: |
234 return TranslateLegalizeResults(Op, Result); | 237 return TranslateLegalizeResults(Op, Result); |
250 LLVM_FALLTHROUGH; | 253 LLVM_FALLTHROUGH; |
251 case TargetLowering::Expand: | 254 case TargetLowering::Expand: |
252 Changed = true; | 255 Changed = true; |
253 return LegalizeOp(ExpandLoad(Op)); | 256 return LegalizeOp(ExpandLoad(Op)); |
254 } | 257 } |
258 } | |
255 } else if (Op.getOpcode() == ISD::STORE) { | 259 } else if (Op.getOpcode() == ISD::STORE) { |
256 StoreSDNode *ST = cast<StoreSDNode>(Op.getNode()); | 260 StoreSDNode *ST = cast<StoreSDNode>(Op.getNode()); |
257 EVT StVT = ST->getMemoryVT(); | 261 EVT StVT = ST->getMemoryVT(); |
258 MVT ValVT = ST->getValue().getSimpleValueType(); | 262 MVT ValVT = ST->getValue().getSimpleValueType(); |
259 if (StVT.isVector() && ST->isTruncatingStore()) | 263 if (StVT.isVector() && ST->isTruncatingStore()) { |
264 DEBUG(dbgs() << "\nLegalizing truncating vector store: "; | |
265 Node->dump(&DAG)); | |
260 switch (TLI.getTruncStoreAction(ValVT, StVT)) { | 266 switch (TLI.getTruncStoreAction(ValVT, StVT)) { |
261 default: llvm_unreachable("This action is not supported yet!"); | 267 default: llvm_unreachable("This action is not supported yet!"); |
262 case TargetLowering::Legal: | 268 case TargetLowering::Legal: |
263 return TranslateLegalizeResults(Op, Result); | 269 return TranslateLegalizeResults(Op, Result); |
264 case TargetLowering::Custom: { | 270 case TargetLowering::Custom: { |
268 } | 274 } |
269 case TargetLowering::Expand: | 275 case TargetLowering::Expand: |
270 Changed = true; | 276 Changed = true; |
271 return LegalizeOp(ExpandStore(Op)); | 277 return LegalizeOp(ExpandStore(Op)); |
272 } | 278 } |
279 } | |
273 } else if (Op.getOpcode() == ISD::MSCATTER || Op.getOpcode() == ISD::MSTORE) | 280 } else if (Op.getOpcode() == ISD::MSCATTER || Op.getOpcode() == ISD::MSTORE) |
274 HasVectorValue = true; | 281 HasVectorValue = true; |
275 | 282 |
276 for (SDNode::value_iterator J = Node->value_begin(), E = Node->value_end(); | 283 for (SDNode::value_iterator J = Node->value_begin(), E = Node->value_end(); |
277 J != E; | 284 J != E; |
374 case ISD::MSTORE: | 381 case ISD::MSTORE: |
375 QueryType = cast<MaskedStoreSDNode>(Node)->getValue().getValueType(); | 382 QueryType = cast<MaskedStoreSDNode>(Node)->getValue().getValueType(); |
376 break; | 383 break; |
377 } | 384 } |
378 | 385 |
386 DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG)); | |
387 | |
379 switch (TLI.getOperationAction(Node->getOpcode(), QueryType)) { | 388 switch (TLI.getOperationAction(Node->getOpcode(), QueryType)) { |
380 default: llvm_unreachable("This action is not supported yet!"); | 389 default: llvm_unreachable("This action is not supported yet!"); |
381 case TargetLowering::Promote: | 390 case TargetLowering::Promote: |
382 Result = Promote(Op); | 391 Result = Promote(Op); |
383 Changed = true; | 392 Changed = true; |
384 break; | 393 break; |
385 case TargetLowering::Legal: | 394 case TargetLowering::Legal: |
395 DEBUG(dbgs() << "Legal node: nothing to do\n"); | |
386 break; | 396 break; |
387 case TargetLowering::Custom: { | 397 case TargetLowering::Custom: { |
398 DEBUG(dbgs() << "Trying custom legalization\n"); | |
388 if (SDValue Tmp1 = TLI.LowerOperation(Op, DAG)) { | 399 if (SDValue Tmp1 = TLI.LowerOperation(Op, DAG)) { |
400 DEBUG(dbgs() << "Successfully custom legalized node\n"); | |
389 Result = Tmp1; | 401 Result = Tmp1; |
390 break; | 402 break; |
391 } | 403 } |
404 DEBUG(dbgs() << "Could not custom legalize node\n"); | |
392 LLVM_FALLTHROUGH; | 405 LLVM_FALLTHROUGH; |
393 } | 406 } |
394 case TargetLowering::Expand: | 407 case TargetLowering::Expand: |
395 Result = Expand(Op); | 408 Result = Expand(Op); |
396 } | 409 } |
416 // "Promote" the operation by extending the operand. | 429 // "Promote" the operation by extending the operand. |
417 return PromoteINT_TO_FP(Op); | 430 return PromoteINT_TO_FP(Op); |
418 case ISD::FP_TO_UINT: | 431 case ISD::FP_TO_UINT: |
419 case ISD::FP_TO_SINT: | 432 case ISD::FP_TO_SINT: |
420 // Promote the operation by extending the operand. | 433 // Promote the operation by extending the operand. |
421 return PromoteFP_TO_INT(Op, Op->getOpcode() == ISD::FP_TO_SINT); | 434 return PromoteFP_TO_INT(Op); |
422 } | 435 } |
423 | 436 |
424 // There are currently two cases of vector promotion: | 437 // There are currently two cases of vector promotion: |
425 // 1) Bitcasting a vector of integers to a different type to a vector of the | 438 // 1) Bitcasting a vector of integers to a different type to a vector of the |
426 // same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64. | 439 // same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64. |
457 } | 470 } |
458 | 471 |
459 SDValue VectorLegalizer::PromoteINT_TO_FP(SDValue Op) { | 472 SDValue VectorLegalizer::PromoteINT_TO_FP(SDValue Op) { |
460 // INT_TO_FP operations may require the input operand be promoted even | 473 // INT_TO_FP operations may require the input operand be promoted even |
461 // when the type is otherwise legal. | 474 // when the type is otherwise legal. |
462 EVT VT = Op.getOperand(0).getValueType(); | 475 MVT VT = Op.getOperand(0).getSimpleValueType(); |
463 assert(Op.getNode()->getNumValues() == 1 && | 476 MVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT); |
464 "Can't promote a vector with multiple results!"); | 477 assert(NVT.getVectorNumElements() == VT.getVectorNumElements() && |
465 | 478 "Vectors have different number of elements!"); |
466 // Normal getTypeToPromoteTo() doesn't work here, as that will promote | 479 |
467 // by widening the vector w/ the same element width and twice the number | |
468 // of elements. We want the other way around, the same number of elements, | |
469 // each twice the width. | |
470 // | |
471 // Increase the bitwidth of the element to the next pow-of-two | |
472 // (which is greater than 8 bits). | |
473 | |
474 EVT NVT = VT.widenIntegerVectorElementType(*DAG.getContext()); | |
475 assert(NVT.isSimple() && "Promoting to a non-simple vector type!"); | |
476 SDLoc dl(Op); | 480 SDLoc dl(Op); |
477 SmallVector<SDValue, 4> Operands(Op.getNumOperands()); | 481 SmallVector<SDValue, 4> Operands(Op.getNumOperands()); |
478 | 482 |
479 unsigned Opc = Op.getOpcode() == ISD::UINT_TO_FP ? ISD::ZERO_EXTEND : | 483 unsigned Opc = Op.getOpcode() == ISD::UINT_TO_FP ? ISD::ZERO_EXTEND : |
480 ISD::SIGN_EXTEND; | 484 ISD::SIGN_EXTEND; |
490 | 494 |
491 // For FP_TO_INT we promote the result type to a vector type with wider | 495 // For FP_TO_INT we promote the result type to a vector type with wider |
492 // elements and then truncate the result. This is different from the default | 496 // elements and then truncate the result. This is different from the default |
493 // PromoteVector which uses bitcast to promote thus assumning that the | 497 // PromoteVector which uses bitcast to promote thus assumning that the |
494 // promoted vector type has the same overall size. | 498 // promoted vector type has the same overall size. |
495 SDValue VectorLegalizer::PromoteFP_TO_INT(SDValue Op, bool isSigned) { | 499 SDValue VectorLegalizer::PromoteFP_TO_INT(SDValue Op) { |
496 assert(Op.getNode()->getNumValues() == 1 && | 500 MVT VT = Op.getSimpleValueType(); |
497 "Can't promote a vector with multiple results!"); | 501 MVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT); |
498 EVT VT = Op.getValueType(); | 502 assert(NVT.getVectorNumElements() == VT.getVectorNumElements() && |
499 | 503 "Vectors have different number of elements!"); |
500 EVT NewVT; | 504 |
501 unsigned NewOpc; | 505 unsigned NewOpc = Op->getOpcode(); |
502 while (true) { | 506 // Change FP_TO_UINT to FP_TO_SINT if possible. |
503 NewVT = VT.widenIntegerVectorElementType(*DAG.getContext()); | 507 // TODO: Should we only do this if FP_TO_UINT itself isn't legal? |
504 assert(NewVT.isSimple() && "Promoting to a non-simple vector type!"); | 508 if (NewOpc == ISD::FP_TO_UINT && |
505 if (TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NewVT)) { | 509 TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NVT)) |
506 NewOpc = ISD::FP_TO_SINT; | 510 NewOpc = ISD::FP_TO_SINT; |
507 break; | 511 |
508 } | 512 SDLoc dl(Op); |
509 if (!isSigned && TLI.isOperationLegalOrCustom(ISD::FP_TO_UINT, NewVT)) { | 513 SDValue Promoted = DAG.getNode(NewOpc, dl, NVT, Op.getOperand(0)); |
510 NewOpc = ISD::FP_TO_UINT; | 514 |
511 break; | 515 // Assert that the converted value fits in the original type. If it doesn't |
512 } | 516 // (eg: because the value being converted is too big), then the result of the |
513 } | 517 // original operation was undefined anyway, so the assert is still correct. |
514 | 518 Promoted = DAG.getNode(Op->getOpcode() == ISD::FP_TO_UINT ? ISD::AssertZext |
515 SDLoc loc(Op); | 519 : ISD::AssertSext, |
516 SDValue promoted = DAG.getNode(NewOpc, SDLoc(Op), NewVT, Op.getOperand(0)); | 520 dl, NVT, Promoted, |
517 return DAG.getNode(ISD::TRUNCATE, SDLoc(Op), VT, promoted); | 521 DAG.getValueType(VT.getScalarType())); |
522 return DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted); | |
518 } | 523 } |
519 | 524 |
520 SDValue VectorLegalizer::ExpandLoad(SDValue Op) { | 525 SDValue VectorLegalizer::ExpandLoad(SDValue Op) { |
521 LoadSDNode *LD = cast<LoadSDNode>(Op.getNode()); | 526 LoadSDNode *LD = cast<LoadSDNode>(Op.getNode()); |
522 | 527 |
552 | 557 |
553 unsigned WideBytes = WideVT.getStoreSize(); | 558 unsigned WideBytes = WideVT.getStoreSize(); |
554 unsigned Offset = 0; | 559 unsigned Offset = 0; |
555 unsigned RemainingBytes = SrcVT.getStoreSize(); | 560 unsigned RemainingBytes = SrcVT.getStoreSize(); |
556 SmallVector<SDValue, 8> LoadVals; | 561 SmallVector<SDValue, 8> LoadVals; |
557 | |
558 while (RemainingBytes > 0) { | 562 while (RemainingBytes > 0) { |
559 SDValue ScalarLoad; | 563 SDValue ScalarLoad; |
560 unsigned LoadBytes = WideBytes; | 564 unsigned LoadBytes = WideBytes; |
561 | 565 |
562 if (RemainingBytes >= LoadBytes) { | 566 if (RemainingBytes >= LoadBytes) { |
578 LD->getMemOperand()->getFlags(), LD->getAAInfo()); | 582 LD->getMemOperand()->getFlags(), LD->getAAInfo()); |
579 } | 583 } |
580 | 584 |
581 RemainingBytes -= LoadBytes; | 585 RemainingBytes -= LoadBytes; |
582 Offset += LoadBytes; | 586 Offset += LoadBytes; |
583 BasePTR = DAG.getNode(ISD::ADD, dl, BasePTR.getValueType(), BasePTR, | 587 |
584 DAG.getConstant(LoadBytes, dl, | 588 BasePTR = DAG.getObjectPtrOffset(dl, BasePTR, LoadBytes); |
585 BasePTR.getValueType())); | |
586 | 589 |
587 LoadVals.push_back(ScalarLoad.getValue(0)); | 590 LoadVals.push_back(ScalarLoad.getValue(0)); |
588 LoadChains.push_back(ScalarLoad.getValue(1)); | 591 LoadChains.push_back(ScalarLoad.getValue(1)); |
589 } | 592 } |
590 | 593 |
657 return (Op.getResNo() ? NewChain : Value); | 660 return (Op.getResNo() ? NewChain : Value); |
658 } | 661 } |
659 | 662 |
660 SDValue VectorLegalizer::ExpandStore(SDValue Op) { | 663 SDValue VectorLegalizer::ExpandStore(SDValue Op) { |
661 StoreSDNode *ST = cast<StoreSDNode>(Op.getNode()); | 664 StoreSDNode *ST = cast<StoreSDNode>(Op.getNode()); |
662 | |
663 EVT StVT = ST->getMemoryVT(); | |
664 EVT MemSclVT = StVT.getScalarType(); | |
665 unsigned ScalarSize = MemSclVT.getSizeInBits(); | |
666 | |
667 // Round odd types to the next pow of two. | |
668 if (!isPowerOf2_32(ScalarSize)) { | |
669 // FIXME: This is completely broken and inconsistent with ExpandLoad | |
670 // handling. | |
671 | |
672 // For sub-byte element sizes, this ends up with 0 stride between elements, | |
673 // so the same element just gets re-written to the same location. There seem | |
674 // to be tests explicitly testing for this broken behavior though. tests | |
675 // for this broken behavior. | |
676 | |
677 LLVMContext &Ctx = *DAG.getContext(); | |
678 | |
679 EVT NewMemVT | |
680 = EVT::getVectorVT(Ctx, | |
681 MemSclVT.getIntegerVT(Ctx, NextPowerOf2(ScalarSize)), | |
682 StVT.getVectorNumElements()); | |
683 | |
684 SDValue NewVectorStore = DAG.getTruncStore( | |
685 ST->getChain(), SDLoc(Op), ST->getValue(), ST->getBasePtr(), | |
686 ST->getPointerInfo(), NewMemVT, ST->getAlignment(), | |
687 ST->getMemOperand()->getFlags(), ST->getAAInfo()); | |
688 ST = cast<StoreSDNode>(NewVectorStore.getNode()); | |
689 } | |
690 | |
691 SDValue TF = TLI.scalarizeVectorStore(ST, DAG); | 665 SDValue TF = TLI.scalarizeVectorStore(ST, DAG); |
692 AddLegalizedOperand(Op, TF); | 666 AddLegalizedOperand(Op, TF); |
693 return TF; | 667 return TF; |
694 } | 668 } |
695 | 669 |