|
8 | 8 |
|
9 | 9 | #include "DXILLegalizePass.h"
|
10 | 10 | #include "DirectX.h"
|
| 11 | +#include "llvm/ADT/APInt.h" |
| 12 | +#include "llvm/IR/Constants.h" |
11 | 13 | #include "llvm/IR/Function.h"
|
12 | 14 | #include "llvm/IR/IRBuilder.h"
|
13 | 15 | #include "llvm/IR/InstIterator.h"
|
@@ -510,40 +512,105 @@ static void updateFnegToFsub(Instruction &I,
|
510 | 512 | ToRemove.push_back(&I);
|
511 | 513 | }
|
512 | 514 |
|
| 515 | +static void |
| 516 | +legalizeGetHighLowi64Bytes(Instruction &I, |
| 517 | + SmallVectorImpl<Instruction *> &ToRemove, |
| 518 | + DenseMap<Value *, Value *> &ReplacedValues) { |
| 519 | + if (auto *BitCast = dyn_cast<BitCastInst>(&I)) { |
| 520 | + if (BitCast->getDestTy() == |
| 521 | + FixedVectorType::get(Type::getInt32Ty(I.getContext()), 2) && |
| 522 | + BitCast->getSrcTy()->isIntegerTy(64)) { |
| 523 | + ToRemove.push_back(BitCast); |
| 524 | + ReplacedValues[BitCast] = BitCast->getOperand(0); |
| 525 | + return; |
| 526 | + } |
| 527 | + } |
| 528 | + |
| 529 | + if (auto *Extract = dyn_cast<ExtractElementInst>(&I)) { |
| 530 | + if (!dyn_cast<BitCastInst>(Extract->getVectorOperand())) |
| 531 | + return; |
| 532 | + auto *VecTy = dyn_cast<FixedVectorType>(Extract->getVectorOperandType()); |
| 533 | + if (VecTy && VecTy->getElementType()->isIntegerTy(32) && |
| 534 | + VecTy->getNumElements() == 2) { |
| 535 | + if (auto *Index = dyn_cast<ConstantInt>(Extract->getIndexOperand())) { |
| 536 | + unsigned Idx = Index->getZExtValue(); |
| 537 | + IRBuilder<> Builder(&I); |
| 538 | + |
| 539 | + auto *Replacement = ReplacedValues[Extract->getVectorOperand()]; |
| 540 | + assert(Replacement && "The BitCast replacement should have been set " |
| 541 | + "before working on ExtractElementInst."); |
| 542 | + if (Idx == 0) { |
| 543 | + Value *LowBytes = Builder.CreateTrunc( |
| 544 | + Replacement, Type::getInt32Ty(I.getContext())); |
| 545 | + ReplacedValues[Extract] = LowBytes; |
| 546 | + } else { |
| 547 | + assert(Idx == 1); |
| 548 | + Value *LogicalShiftRight = Builder.CreateLShr( |
| 549 | + Replacement, |
| 550 | + ConstantInt::get( |
| 551 | + Replacement->getType(), |
| 552 | + APInt(Replacement->getType()->getIntegerBitWidth(), 32))); |
| 553 | + Value *HighBytes = Builder.CreateTrunc( |
| 554 | + LogicalShiftRight, Type::getInt32Ty(I.getContext())); |
| 555 | + ReplacedValues[Extract] = HighBytes; |
| 556 | + } |
| 557 | + ToRemove.push_back(Extract); |
| 558 | + Extract->replaceAllUsesWith(ReplacedValues[Extract]); |
| 559 | + } |
| 560 | + } |
| 561 | + } |
| 562 | +} |
| 563 | + |
513 | 564 | namespace {
|
514 | 565 | class DXILLegalizationPipeline {
|
515 | 566 |
|
516 | 567 | public:
|
517 | 568 | DXILLegalizationPipeline() { initializeLegalizationPipeline(); }
|
518 | 569 |
|
519 | 570 | bool runLegalizationPipeline(Function &F) {
|
| 571 | + bool MadeChange = false; |
520 | 572 | SmallVector<Instruction *> ToRemove;
|
521 | 573 | DenseMap<Value *, Value *> ReplacedValues;
|
522 |
| - for (auto &I : instructions(F)) { |
523 |
| - for (auto &LegalizationFn : LegalizationPipeline) |
524 |
| - LegalizationFn(I, ToRemove, ReplacedValues); |
525 |
| - } |
| 574 | + for (int Stage = 0; Stage < NumStages; ++Stage) { |
| 575 | + ToRemove.clear(); |
| 576 | + ReplacedValues.clear(); |
| 577 | + for (auto &I : instructions(F)) { |
| 578 | + for (auto &LegalizationFn : LegalizationPipeline[Stage]) |
| 579 | + LegalizationFn(I, ToRemove, ReplacedValues); |
| 580 | + } |
526 | 581 |
|
527 |
| - for (auto *Inst : reverse(ToRemove)) |
528 |
| - Inst->eraseFromParent(); |
| 582 | + for (auto *Inst : reverse(ToRemove)) |
| 583 | + Inst->eraseFromParent(); |
529 | 584 |
|
530 |
| - return !ToRemove.empty(); |
| 585 | + MadeChange |= !ToRemove.empty(); |
| 586 | + } |
| 587 | + return MadeChange; |
531 | 588 | }
|
532 | 589 |
|
533 | 590 | private:
|
534 |
| - SmallVector< |
| 591 | + enum LegalizationStage { Stage1 = 0, Stage2 = 1, NumStages }; |
| 592 | + |
| 593 | + using LegalizationFnTy = |
535 | 594 | std::function<void(Instruction &, SmallVectorImpl<Instruction *> &,
|
536 |
| - DenseMap<Value *, Value *> &)>> |
537 |
| - LegalizationPipeline; |
| 595 | + DenseMap<Value *, Value *> &)>; |
| 596 | + |
| 597 | + SmallVector<LegalizationFnTy> LegalizationPipeline[NumStages]; |
538 | 598 |
|
539 | 599 | void initializeLegalizationPipeline() {
|
540 |
| - LegalizationPipeline.push_back(upcastI8AllocasAndUses); |
541 |
| - LegalizationPipeline.push_back(fixI8UseChain); |
542 |
| - LegalizationPipeline.push_back(downcastI64toI32InsertExtractElements); |
543 |
| - LegalizationPipeline.push_back(legalizeFreeze); |
544 |
| - LegalizationPipeline.push_back(legalizeMemCpy); |
545 |
| - LegalizationPipeline.push_back(removeMemSet); |
546 |
| - LegalizationPipeline.push_back(updateFnegToFsub); |
| 600 | + LegalizationPipeline[Stage1].push_back(upcastI8AllocasAndUses); |
| 601 | + LegalizationPipeline[Stage1].push_back(fixI8UseChain); |
| 602 | + LegalizationPipeline[Stage1].push_back(legalizeGetHighLowi64Bytes); |
| 603 | + LegalizationPipeline[Stage1].push_back(legalizeFreeze); |
| 604 | + LegalizationPipeline[Stage1].push_back(legalizeMemCpy); |
| 605 | + LegalizationPipeline[Stage1].push_back(removeMemSet); |
| 606 | + LegalizationPipeline[Stage1].push_back(updateFnegToFsub); |
| 607 | + // Note: legalizeGetHighLowi64Bytes and |
| 608 | + // downcastI64toI32InsertExtractElements both modify extractelement, so they |
| 609 | + // must run staggered stages. legalizeGetHighLowi64Bytes runs first b\c it |
| 610 | + // removes extractelements, reducing the number that |
| 611 | + // downcastI64toI32InsertExtractElements needs to handle. |
| 612 | + LegalizationPipeline[Stage2].push_back( |
| 613 | + downcastI64toI32InsertExtractElements); |
547 | 614 | }
|
548 | 615 | };
|
549 | 616 |
|
|
0 commit comments