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