LLVM: include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h Source File (original) (raw)

40

41 static bool isArtifactCast(unsigned Opc) {

42 switch (Opc) {

43 case TargetOpcode::G_TRUNC:

44 case TargetOpcode::G_SEXT:

45 case TargetOpcode::G_ZEXT:

46 case TargetOpcode::G_ANYEXT:

47 return true;

48 default:

49 return false;

50 }

51 }

52

53public:

57 : Builder(B), MRI(MRI), LI(LI), VT(VT) {}

58

64 assert(MI.getOpcode() == TargetOpcode::G_ANYEXT);

65

66 Builder.setInstrAndDebugLoc(MI);

67 Register DstReg = MI.getOperand(0).getReg();

68 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());

69

70

74 if (MRI.getType(DstReg) == MRI.getType(TruncSrc))

76 Observer);

77 else

78 Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);

80 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);

81 return true;

82 }

83

84

91 Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});

93 markInstAndDefDead(MI, *ExtMI, DeadInsts);

94 return true;

95 }

96

97

98 auto *SrcMI = MRI.getVRegDef(SrcReg);

99 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {

100 const LLT DstTy = MRI.getType(DstReg);

101 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {

102 auto &CstVal = SrcMI->getOperand(1);

103 auto MergedLocation =

105

106

107 Builder.setDebugLoc(MergedLocation);

108 Builder.buildConstant(

109 DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));

111 markInstAndDefDead(MI, *SrcMI, DeadInsts);

112 return true;

113 }

114 }

116 }

117

123 assert(MI.getOpcode() == TargetOpcode::G_ZEXT);

124

125 Builder.setInstrAndDebugLoc(MI);

126 Register DstReg = MI.getOperand(0).getReg();

127 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());

128

129

130

135 LLT DstTy = MRI.getType(DstReg);

136 if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||

137 isConstantUnsupported(DstTy))

138 return false;

140 LLT SrcTy = MRI.getType(SrcReg);

142 if (SextSrc && (DstTy != MRI.getType(SextSrc)))

143 SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);

144 if (TruncSrc && (DstTy != MRI.getType(TruncSrc)))

145 TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);

147 Register AndSrc = SextSrc ? SextSrc : TruncSrc;

148

149

150

151

152

153

154 if (VT && (VT->getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {

156 Observer);

157 } else {

158 auto Mask = Builder.buildConstant(DstTy, ExtMaskVal);

159 Builder.buildAnd(DstReg, AndSrc, Mask);

160 }

161 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);

162 return true;

163 }

164

165

170 MI.getOperand(1).setReg(ZextSrc);

173 markDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);

174 return true;

175 }

176

177

178 auto *SrcMI = MRI.getVRegDef(SrcReg);

179 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {

180 const LLT DstTy = MRI.getType(DstReg);

181 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {

182 auto &CstVal = SrcMI->getOperand(1);

183 Builder.buildConstant(

184 DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits()));

186 markInstAndDefDead(MI, *SrcMI, DeadInsts);

187 return true;

188 }

189 }

191 }

192

198 assert(MI.getOpcode() == TargetOpcode::G_SEXT);

199

200 Builder.setInstrAndDebugLoc(MI);

201 Register DstReg = MI.getOperand(0).getReg();

202 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());

203

204

207 LLT DstTy = MRI.getType(DstReg);

208 if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}}))

209 return false;

211 LLT SrcTy = MRI.getType(SrcReg);

212 uint64_t SizeInBits = SrcTy.getScalarSizeInBits();

213 if (DstTy != MRI.getType(TruncSrc))

214 TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);

215

216

217 if (VT && VT->computeNumSignBits(TruncSrc) >

220 Observer);

221 else

222 Builder.buildSExtInReg(DstReg, TruncSrc, SizeInBits);

223 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);

224 return true;

225 }

226

227

228

235 Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});

237 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);

238 return true;

239 }

240

241

242 auto *SrcMI = MRI.getVRegDef(SrcReg);

243 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {

244 const LLT DstTy = MRI.getType(DstReg);

245 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {

246 auto &CstVal = SrcMI->getOperand(1);

247 Builder.buildConstant(

248 DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));

250 markInstAndDefDead(MI, *SrcMI, DeadInsts);

251 return true;

252 }

253 }

254

256 }

257

263 assert(MI.getOpcode() == TargetOpcode::G_TRUNC);

264

265 Builder.setInstr(MI);

266 Register DstReg = MI.getOperand(0).getReg();

267 const LLT DstTy = MRI.getType(DstReg);

268 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());

269

270

271 auto *SrcMI = MRI.getVRegDef(SrcReg);

272 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {

273 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {

274 auto &CstVal = SrcMI->getOperand(1);

275 Builder.buildConstant(

276 DstReg, CstVal.getCImm()->getValue().trunc(DstTy.getSizeInBits()));

278 markInstAndDefDead(MI, *SrcMI, DeadInsts);

279 return true;

280 }

281 }

282

283

284

286 const Register MergeSrcReg = SrcMerge->getSourceReg(0);

287 const LLT MergeSrcTy = MRI.getType(MergeSrcReg);

288

289

291 const unsigned MergeSrcSize = MergeSrcTy.getSizeInBits();

293 return false;

294

295 if (DstSize < MergeSrcSize) {

296

297

298 if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))

299 return false;

300

301 LLVM_DEBUG(dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "

302 << MI);

303

304 Builder.buildTrunc(DstReg, MergeSrcReg);

306 } else if (DstSize == MergeSrcSize) {

307

309 dbgs() << "Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "

310 << MI);

312 Observer);

313 } else if (DstSize % MergeSrcSize == 0) {

314

315

316 if (isInstUnsupported(

317 {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))

318 return false;

319

321 dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "

322 << MI);

323

324 const unsigned NumSrcs = DstSize / MergeSrcSize;

325 assert(NumSrcs < SrcMI->getNumOperands() - 1 &&

326 "trunc(merge) should require less inputs than merge");

328 for (unsigned i = 0; i < NumSrcs; ++i)

329 SrcRegs[i] = SrcMerge->getSourceReg(i);

330

331 Builder.buildMergeValues(DstReg, SrcRegs);

333 } else {

334

335 return false;

336 }

337

338 markInstAndDefDead(MI, *SrcMerge, DeadInsts);

339 return true;

340 }

341

342

345

346

347

349

350 Builder.buildTrunc(DstReg, TruncSrc);

352 markInstAndDefDead(MI, *MRI.getVRegDef(TruncSrc), DeadInsts);

353 return true;

354 }

355

356

360 LLT FoundRegTy = MRI.getType(FoundReg);

361 if (DstTy == FoundRegTy) {

362 LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_[S,Z,ANY]EXT/G_TRUNC...): "

363 << MI);

364

366 Observer);

368 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);

369 return true;

370 }

371 }

372

373 return false;

374 }

375

376

381 unsigned Opcode = MI.getOpcode();

382 assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||

383 Opcode == TargetOpcode::G_SEXT);

384

386 MI.getOperand(1).getReg(), MRI)) {

387 Builder.setInstr(MI);

388 Register DstReg = MI.getOperand(0).getReg();

389 LLT DstTy = MRI.getType(DstReg);

390

391 if (Opcode == TargetOpcode::G_ANYEXT) {

392

393 if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))

394 return false;

395 LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI);

396 auto Impl = Builder.buildUndef(DstTy);

398 Observer);

400 } else {

401

402

403 if (isConstantUnsupported(DstTy))

404 return false;

405 LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI);

406 auto Cnst = Builder.buildConstant(DstTy, 0);

408 Observer);

410 }

411

412 markInstAndDefDead(MI, *DefMI, DeadInsts);

413 return true;

414 }

415 return false;

416 }

417

421

422 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);

423

424 const unsigned CastOpc = CastMI.getOpcode();

425

426 if (!isArtifactCast(CastOpc))

427 return false;

428

429 const unsigned NumDefs = MI.getNumOperands() - 1;

430

432 const LLT CastSrcTy = MRI.getType(CastSrcReg);

433 const LLT DestTy = MRI.getType(MI.getOperand(0).getReg());

434 const LLT SrcTy = MRI.getType(MI.getOperand(NumDefs).getReg());

435

436 const unsigned CastSrcSize = CastSrcTy.getSizeInBits();

437 const unsigned DestSize = DestTy.getSizeInBits();

438

439 if (CastOpc == TargetOpcode::G_TRUNC) {

440 if (SrcTy.isVector() && SrcTy.getScalarType() == DestTy.getScalarType()) {

441

442

443

444

445

446

447

448

449

450 unsigned UnmergeNumElts =

454 LLT SrcWideTy =

456

457 if (isInstUnsupported(

458 {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}) ||

459 LI.getAction({TargetOpcode::G_TRUNC, {SrcWideTy, UnmergeTy}})

461 return false;

462

463 Builder.setInstr(MI);

464 auto NewUnmerge = Builder.buildUnmerge(UnmergeTy, CastSrcReg);

465

466 for (unsigned I = 0; I != NumDefs; ++I) {

467 Register DefReg = MI.getOperand(I).getReg();

469 Builder.buildTrunc(DefReg, NewUnmerge.getReg(I));

470 }

471

472 markInstAndDefDead(MI, CastMI, DeadInsts);

473 return true;

474 }

475

476 if (CastSrcTy.isScalar() && SrcTy.isScalar() && !DestTy.isVector()) {

477

478

479

480

481

482

483

484 if (CastSrcSize % DestSize != 0)

485 return false;

486

487

488 if (isInstUnsupported(

489 {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))

490 return false;

491

492

493

494 const unsigned NewNumDefs = CastSrcSize / DestSize;

496 for (unsigned Idx = 0; Idx < NewNumDefs; ++Idx) {

497 if (Idx < NumDefs)

498 DstRegs[Idx] = MI.getOperand(Idx).getReg();

499 else

500 DstRegs[Idx] = MRI.createGenericVirtualRegister(DestTy);

501 }

502

503

504 Builder.setInstr(MI);

505 Builder.buildUnmerge(DstRegs, CastSrcReg);

506 UpdatedDefs.append(DstRegs.begin(), DstRegs.begin() + NewNumDefs);

507 markInstAndDefDead(MI, CastMI, DeadInsts);

508 return true;

509 }

510 }

511

512

513 return false;

514 }

515

517 LLT OpTy, LLT DestTy) {

518

519 switch (MergeOp) {

520 default:

521 return false;

522 case TargetOpcode::G_BUILD_VECTOR:

523 case TargetOpcode::G_MERGE_VALUES:

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546 if (ConvertOp == 0)

547 return true;

550 case TargetOpcode::G_CONCAT_VECTORS: {

551 if (ConvertOp == 0)

552 return true;

554 return false;

555

557

558

559

560

561 if (ConvertOp == TargetOpcode::G_TRUNC)

564 }

565 }

566 }

567

568

569

576 Builder.buildCopy(DstReg, SrcReg);

578 return;

579 }

581

582 for (auto &UseMI : MRI.use_instructions(DstReg)) {

585 }

586

587 MRI.replaceRegWith(DstReg, SrcReg);

589

590 for (auto *UseMI : UseMIs)

592 }

593

594

596 unsigned DefIdx = 0;

598 if (Def.getReg() == SearchDef)

599 break;

600 ++DefIdx;

601 }

602

603 return DefIdx;

604 }

605

606

607

608

609

614

615

617

618

619

620

621

622

624 unsigned Size) {

626

627

629 unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();

630

631

632 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;

633

634 unsigned InRegOffset = StartBit % SrcSize;

635

636

637

638 if (InRegOffset + Size > SrcSize)

639 return CurrentBest;

640

642 if (InRegOffset == 0 && Size == SrcSize) {

643 CurrentBest = SrcReg;

644 return findValueFromDefImpl(SrcReg, 0, Size, MRI.getType(SrcReg));

645 }

646

647 return findValueFromDefImpl(SrcReg, InRegOffset, Size,

648 MRI.getType(SrcReg));

649 }

650

651

652

653

654

655

657 unsigned Size) {

659

660

662 unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();

663

664

665 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;

666

667 unsigned InRegOffset = StartBit % SrcSize;

668

669 if (InRegOffset != 0)

670 return CurrentBest;

671 if (Size < SrcSize)

672 return CurrentBest;

673

674

675

676 if (Size > SrcSize) {

677 if (Size % SrcSize > 0)

678 return CurrentBest;

679

680 unsigned NumSrcsUsed = Size / SrcSize;

681

684

685 LLT SrcTy = MRI.getType(Src1Reg);

687

688

690 LI.getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});

692 return CurrentBest;

693

695 for (unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;

696 ++SrcIdx)

698 MIB.setInstrAndDebugLoc(BV);

699 return MIB.buildBuildVector(NewBVTy, NewSrcs).getReg(0);

700 }

701

702 return BV.getReg(StartSrcIdx);

703 }

704

705

706

707

708

709

711 unsigned Size) {

712 assert(MI.getOpcode() == TargetOpcode::G_INSERT);

714

715 Register ContainerSrcReg = MI.getOperand(1).getReg();

716 Register InsertedReg = MI.getOperand(2).getReg();

717 LLT InsertedRegTy = MRI.getType(InsertedReg);

718 unsigned InsertOffset = MI.getOperand(3).getImm();

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756 unsigned InsertedEndBit = InsertOffset + InsertedRegTy.getSizeInBits();

757 unsigned EndBit = StartBit + Size;

758 unsigned NewStartBit;

760 if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {

761 SrcRegToUse = ContainerSrcReg;

762 NewStartBit = StartBit;

763 return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size,

764 MRI.getType(SrcRegToUse));

765 }

766 if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {

767 SrcRegToUse = InsertedReg;

768 NewStartBit = StartBit - InsertOffset;

769 if (NewStartBit == 0 &&

770 Size == MRI.getType(SrcRegToUse).getSizeInBits())

771 CurrentBest = SrcRegToUse;

772 return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size,

773 MRI.getType(SrcRegToUse));

774 }

775

777 }

778

779

780

781

782

783

784

786 unsigned Size) {

787 assert(MI.getOpcode() == TargetOpcode::G_SEXT ||

788 MI.getOpcode() == TargetOpcode::G_ZEXT ||

789 MI.getOpcode() == TargetOpcode::G_ANYEXT);

791

792 Register SrcReg = MI.getOperand(1).getReg();

793 LLT SrcType = MRI.getType(SrcReg);

795

796

797 if (!SrcType.isScalar())

798 return CurrentBest;

799

800 if (StartBit + Size > SrcSize)

801 return CurrentBest;

802

803 if (StartBit == 0 && SrcType.getSizeInBits() == Size)

804 CurrentBest = SrcReg;

805 return findValueFromDefImpl(SrcReg, StartBit, Size, SrcType);

806 }

807

808

809

810

811

812

814 unsigned Size) {

815 assert(MI.getOpcode() == TargetOpcode::G_TRUNC);

817

818 Register SrcReg = MI.getOperand(1).getReg();

819 LLT SrcType = MRI.getType(SrcReg);

820

821

822 if (!SrcType.isScalar())

823 return CurrentBest;

824

825 return findValueFromDefImpl(SrcReg, StartBit, Size, SrcType);

826 }

827

828

829

830

831 Register findValueFromDefImpl(Register DefReg, unsigned StartBit,

832 unsigned Size, LLT DstTy) {

833 std::optional DefSrcReg =

836 DefReg = DefSrcReg->Reg;

837

838

839

840 switch (Def->getOpcode()) {

841 case TargetOpcode::G_CONCAT_VECTORS:

843 case TargetOpcode::G_UNMERGE_VALUES: {

844 unsigned DefStartBit = 0;

845 unsigned DefSize = MRI.getType(DefReg).getSizeInBits();

846 for (const auto &MO : Def->defs()) {

847 if (MO.getReg() == DefReg)

848 break;

849 DefStartBit += DefSize;

850 }

851 Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();

853 findValueFromDefImpl(SrcReg, StartBit + DefStartBit, Size, DstTy);

854 if (SrcOriginReg)

855 return SrcOriginReg;

856

857

858

859 if (StartBit == 0 && Size == DefSize)

860 return DefReg;

861 return CurrentBest;

862 }

863 case TargetOpcode::G_BUILD_VECTOR:

866 case TargetOpcode::G_INSERT:

867 return findValueFromInsert(*Def, StartBit, Size);

868 case TargetOpcode::G_TRUNC:

869 return findValueFromTrunc(*Def, StartBit, Size);

870 case TargetOpcode::G_SEXT:

871 case TargetOpcode::G_ZEXT:

872 case TargetOpcode::G_ANYEXT:

873 return findValueFromExt(*Def, StartBit, Size);

874 case TargetOpcode::G_IMPLICIT_DEF: {

875 if (MRI.getType(DefReg) == DstTy)

876 return DefReg;

877 MIB.setInstrAndDebugLoc(*Def);

878 return MIB.buildUndef(DstTy).getReg(0);

879 }

880 default:

881 return CurrentBest;

882 }

883 }

884

885 public:

888 : MRI(Mri), MIB(Builder), LI(Info) {}

889

890

891

892

893

895 LLT DstTy) {

897 Register FoundReg = findValueFromDefImpl(DefReg, StartBit, Size, DstTy);

898 return FoundReg != DefReg ? FoundReg : Register();

899 }

900

901

902

903

906 unsigned NumDefs = MI.getNumDefs();

907 LLT DestTy = MRI.getType(MI.getReg(0));

908

910 for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {

912 if (MRI.use_nodbg_empty(DefReg)) {

913 DeadDefs[DefIdx] = true;

914 continue;

915 }

918 if (!FoundVal)

919 continue;

920 if (MRI.getType(FoundVal) != DestTy)

921 continue;

922

924 Observer);

925

927 MI.getOperand(DefIdx).setReg(DefReg);

929 DeadDefs[DefIdx] = true;

930 }

931 return DeadDefs.all();

932 }

933

935 unsigned &DefOperandIdx) {

936 if (Register Def = findValueFromDefImpl(Reg, 0, Size, MRI.getType(Reg))) {

938 DefOperandIdx =

939 Unmerge->findRegisterDefOperandIdx(Def, nullptr);

940 return Unmerge;

941 }

942 }

943 return nullptr;

944 }

945

946

947

948

950 GUnmerge *Unmerge, unsigned UnmergeIdxStart,

951 unsigned NumElts, unsigned EltSize,

952 bool AllowUndef) {

953 assert(MergeStartIdx + NumElts <= MI.getNumSources());

954 for (unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {

955 unsigned EltUnmergeIdx;

957 MI.getSourceReg(i), EltSize, EltUnmergeIdx);

958

959 if (EltUnmerge == Unmerge) {

960

961 if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)

962 return false;

963 } else if (!AllowUndef ||

964 MRI.getVRegDef(MI.getSourceReg(i))->getOpcode() !=

965 TargetOpcode::G_IMPLICIT_DEF)

966 return false;

967 }

968 return true;

969 }

970

976 LLT EltTy = MRI.getType(Elt0);

978

979 unsigned Elt0UnmergeIdx;

980

982 if (!Unmerge)

983 return false;

984

985 unsigned NumMIElts = MI.getNumSources();

987 LLT DstTy = MRI.getType(Dst);

988 Register UnmergeSrc = Unmerge->getSourceReg();

989 LLT UnmergeSrcTy = MRI.getType(UnmergeSrc);

990

991

992

993

994

995

996

997

998 if ((DstTy == UnmergeSrcTy) && (Elt0UnmergeIdx == 0)) {

1000 DstTy.isVector()))

1001 return false;

1002

1005 return true;

1006 }

1007

1008

1009

1010

1011

1012

1013

1014

1015

1016

1017

1018

1022 (Elt0UnmergeIdx % NumMIElts == 0) &&

1023 getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {

1025 EltSize, false))

1026 return false;

1027 MIB.setInstrAndDebugLoc(MI);

1028 auto NewUnmerge = MIB.buildUnmerge(DstTy, Unmerge->getSourceReg());

1029 unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.getSizeInBits();

1031 UpdatedDefs, Observer);

1033 return true;

1034 }

1035

1036

1037

1038

1039

1040

1041

1042

1043

1044

1045

1047 getCoverTy(DstTy, UnmergeSrcTy) == DstTy) {

1049 unsigned NumElts = Unmerge->getNumDefs();

1050 for (unsigned i = 0; i < MI.getNumSources(); i += NumElts) {

1051 unsigned EltUnmergeIdx;

1053 EltSize, EltUnmergeIdx);

1054

1055 if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||

1056 (EltUnmergeIdx != 0))

1057 return false;

1059 false))

1060 return false;

1061 ConcatSources.push_back(UnmergeI->getSourceReg());

1062 }

1063

1064 MIB.setInstrAndDebugLoc(MI);

1065 MIB.buildMergeLikeInstr(Dst, ConcatSources);

1067 return true;

1068 }

1069

1070 return false;

1071 }

1072 };

1073

1078 unsigned NumDefs = MI.getNumDefs();

1079 Register SrcReg = MI.getSourceReg();

1080 std::optional DefSrcReg =

1082 if (!DefSrcReg)

1083 return false;

1085

1086 LLT OpTy = MRI.getType(SrcReg);

1087 LLT DestTy = MRI.getType(MI.getReg(0));

1088 unsigned SrcDefIdx = getDefIndex(*SrcDef, DefSrcReg->Reg);

1089

1090 Builder.setInstrAndDebugLoc(MI);

1091

1094 markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx);

1095 return true;

1096 }

1097

1099

1100

1101

1102

1103

1104 Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();

1105 LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc);

1106

1107

1108

1109

1111 {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});

1112 switch (ActionStep.Action) {

1114 if (!OpTy.isVector() || !LI.isLegal({TargetOpcode::G_UNMERGE_VALUES,

1115 {DestTy, SrcUnmergeSrcTy}}))

1116 return false;

1117 break;

1120 break;

1123 if (ActionStep.TypeIdx == 1)

1124 return false;

1125 break;

1126 default:

1127 return false;

1128 }

1129

1130 auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);

1131

1132

1133

1134

1135 for (unsigned I = 0; I != NumDefs; ++I) {

1138 MRI, Builder, UpdatedDefs, Observer);

1139 }

1140

1141 markInstAndDefDead(MI, *SrcUnmerge, DeadInsts, SrcDefIdx);

1142 return true;

1143 }

1144

1146 unsigned ConvertOp = 0;

1147

1148

1149 unsigned SrcOp = SrcDef->getOpcode();

1150 if (isArtifactCast(SrcOp)) {

1151 ConvertOp = SrcOp;

1153 }

1154

1156 ConvertOp, OpTy, DestTy)) {

1157

1158

1160 }

1161

1162 const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;

1163

1164 if (NumMergeRegs < NumDefs) {

1165 if (NumDefs % NumMergeRegs != 0)

1166 return false;

1167

1168 Builder.setInstr(MI);

1169

1170

1171

1172

1173

1174

1175

1176 const unsigned NewNumDefs = NumDefs / NumMergeRegs;

1177 for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {

1179 for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;

1180 ++j, ++DefIdx)

1182

1183 if (ConvertOp) {

1184 LLT MergeDstTy = MRI.getType(SrcDef->getOperand(0).getReg());

1185

1186

1187

1188

1189 LLT MergeEltTy = MergeDstTy.divide(NumMergeRegs);

1190

1191

1192

1193

1194

1195

1196

1197

1198

1199

1200

1201

1202

1203

1204 Register TmpReg = MRI.createGenericVirtualRegister(MergeEltTy);

1205 Builder.buildInstr(ConvertOp, {TmpReg},

1207 Builder.buildUnmerge(DstRegs, TmpReg);

1208 } else {

1209 Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());

1210 }

1211 UpdatedDefs.append(DstRegs.begin(), DstRegs.end());

1212 }

1213

1214 } else if (NumMergeRegs > NumDefs) {

1215 if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)

1216 return false;

1217

1218 Builder.setInstr(MI);

1219

1220

1221

1222

1223

1224

1225

1226 const unsigned NumRegs = NumMergeRegs / NumDefs;

1227 for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {

1229 for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;

1230 ++j, ++Idx)

1232

1233 Register DefReg = MI.getReg(DefIdx);

1234 Builder.buildMergeLikeInstr(DefReg, Regs);

1235 UpdatedDefs.push_back(DefReg);

1236 }

1237

1238 } else {

1239 LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());

1240

1241 if (!ConvertOp && DestTy != MergeSrcTy) {

1242 if (DestTy.isPointer())

1243 ConvertOp = TargetOpcode::G_INTTOPTR;

1244 else if (MergeSrcTy.isPointer())

1245 ConvertOp = TargetOpcode::G_PTRTOINT;

1246 else

1247 ConvertOp = TargetOpcode::G_BITCAST;

1248 }

1249

1250 if (ConvertOp) {

1251 Builder.setInstr(MI);

1252

1253 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {

1254 Register DefReg = MI.getOperand(Idx).getReg();

1256

1257 if (!MRI.use_empty(DefReg)) {

1258 Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});

1259 UpdatedDefs.push_back(DefReg);

1260 }

1261 }

1262

1263 markInstAndDefDead(MI, *MergeI, DeadInsts);

1264 return true;

1265 }

1266

1267 assert(DestTy == MergeSrcTy &&

1268 "Bitcast and the other kinds of conversions should "

1269 "have happened earlier");

1270

1271 Builder.setInstr(MI);

1272 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {

1273 Register DstReg = MI.getOperand(Idx).getReg();

1276 Observer);

1277 }

1278 }

1279

1280 markInstAndDefDead(MI, *MergeI, DeadInsts);

1281 return true;

1282 }

1283

1287 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);

1288

1289

1290

1291

1292

1293

1294

1295

1296

1297

1298

1299

1300

1301 Register DstReg = MI.getOperand(0).getReg();

1302 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());

1303 MachineInstr *MergeI = MRI.getVRegDef(SrcReg);

1304 if (MergeI && MergeI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) {

1305 Builder.setInstrAndDebugLoc(MI);

1306 Builder.buildUndef(DstReg);

1308 markInstAndDefDead(MI, *MergeI, DeadInsts);

1309 return true;

1310 }

1312 return false;

1313

1314 LLT DstTy = MRI.getType(DstReg);

1315 LLT SrcTy = MRI.getType(SrcReg);

1316

1317

1318 unsigned ExtractDstSize = DstTy.getSizeInBits();

1319 unsigned Offset = MI.getOperand(2).getImm();

1320 unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;

1321 unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;

1322 unsigned MergeSrcIdx = Offset / MergeSrcSize;

1323

1324

1325 unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;

1326

1327

1328 if (MergeSrcIdx != EndMergeSrcIdx)

1329 return false;

1330

1331

1332 Builder.setInstr(MI);

1333 Builder.buildExtract(DstReg, MergeI->getOperand(MergeSrcIdx + 1).getReg(),

1334 Offset - MergeSrcIdx * MergeSrcSize);

1336 markInstAndDefDead(MI, *MergeI, DeadInsts);

1337 return true;

1338 }

1339

1340

1341

1342

1343

1348

1349

1350

1351

1352 if (!DeadInsts.empty())

1353 deleteMarkedDeadInsts(DeadInsts, WrapperObserver);

1354

1355

1356

1357

1358

1361 switch (MI.getOpcode()) {

1362 default:

1363 return false;

1364 case TargetOpcode::G_ANYEXT:

1366 break;

1367 case TargetOpcode::G_ZEXT:

1369 break;

1370 case TargetOpcode::G_SEXT:

1372 break;

1373 case TargetOpcode::G_UNMERGE_VALUES:

1375 UpdatedDefs, WrapperObserver);

1376 break;

1377 case TargetOpcode::G_MERGE_VALUES:

1378 case TargetOpcode::G_BUILD_VECTOR:

1379 case TargetOpcode::G_CONCAT_VECTORS:

1380

1381

1382 for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) {

1383 if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||

1384 U.getOpcode() == TargetOpcode::G_TRUNC) {

1385 UpdatedDefs.push_back(MI.getOperand(0).getReg());

1386 break;

1387 }

1388 }

1390 UpdatedDefs, WrapperObserver);

1391 break;

1392 case TargetOpcode::G_EXTRACT:

1394 break;

1395 case TargetOpcode::G_TRUNC:

1398

1399

1400

1401

1402 UpdatedDefs.push_back(MI.getOperand(0).getReg());

1403 }

1404 break;

1405 }

1406

1407

1408

1409

1410 while (!UpdatedDefs.empty()) {

1412 assert(NewDef.isVirtual() && "Unexpected redefinition of a physreg");

1413 for (MachineInstr &Use : MRI.use_instructions(NewDef)) {

1414 switch (Use.getOpcode()) {

1415

1416 case TargetOpcode::G_ANYEXT:

1417 case TargetOpcode::G_ZEXT:

1418 case TargetOpcode::G_SEXT:

1419 case TargetOpcode::G_UNMERGE_VALUES:

1420 case TargetOpcode::G_EXTRACT:

1421 case TargetOpcode::G_TRUNC:

1422 case TargetOpcode::G_BUILD_VECTOR:

1423

1425 break;

1426 case TargetOpcode::G_ASSERT_SEXT:

1427 case TargetOpcode::G_ASSERT_ZEXT:

1428 case TargetOpcode::G_ASSERT_ALIGN:

1429 case TargetOpcode::COPY: {

1430 Register Copy = Use.getOperand(0).getReg();

1431 if (Copy.isVirtual())

1433 break;

1434 }

1435 default:

1436

1437

1438

1439 break;

1440 }

1441 }

1442 }

1444 }

1445

1446private:

1448 switch (MI.getOpcode()) {

1449 case TargetOpcode::COPY:

1450 case TargetOpcode::G_TRUNC:

1451 case TargetOpcode::G_ZEXT:

1452 case TargetOpcode::G_ANYEXT:

1453 case TargetOpcode::G_SEXT:

1454 case TargetOpcode::G_EXTRACT:

1455 case TargetOpcode::G_ASSERT_SEXT:

1456 case TargetOpcode::G_ASSERT_ZEXT:

1457 case TargetOpcode::G_ASSERT_ALIGN:

1458 return MI.getOperand(1).getReg();

1459 case TargetOpcode::G_UNMERGE_VALUES:

1460 return MI.getOperand(MI.getNumOperands() - 1).getReg();

1461 default:

1463 }

1464 }

1465

1466

1467

1468

1469

1470

1473 unsigned DefIdx = 0) {

1474

1475

1476

1477

1478

1479

1480

1481

1482

1484 while (PrevMI != &DefMI) {

1485 Register PrevRegSrc = getArtifactSrcReg(*PrevMI);

1486

1488 if (MRI.hasOneUse(PrevRegSrc)) {

1489 if (TmpDef != &DefMI) {

1491 isArtifactCast(TmpDef->getOpcode()) ||

1493 "Expecting copy or artifact cast here");

1494

1496 }

1497 } else

1498 break;

1499 PrevMI = TmpDef;

1500 }

1501

1502 if (PrevMI == &DefMI) {

1503 unsigned I = 0;

1506 if (I != DefIdx) {

1507 if (MRI.use_empty(Def.getReg())) {

1509 break;

1510 }

1511 } else {

1512 if (MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg()))

1513 break;

1514 }

1515

1516 ++I;

1517 }

1518

1521 }

1522 }

1523

1524

1525

1526

1527

1528

1531 unsigned DefIdx = 0) {

1533 markDefDead(MI, DefMI, DeadInsts, DefIdx);

1534 }

1535

1536

1537

1538

1539

1540

1541

1544 for (auto *DeadMI : DeadInsts) {

1545 LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n");

1547 DeadMI->eraseFromParent();

1548 }

1549 DeadInsts.clear();

1550 }

1551

1552

1553

1554 bool isInstUnsupported(const LegalityQuery &Query) const {

1556 auto Step = LI.getAction(Query);

1558 }

1559

1560 bool isInstLegal(const LegalityQuery &Query) const {

1562 }

1563

1564 bool isConstantUnsupported(LLT Ty) const {

1566 return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});

1567

1569 return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||

1570 isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});

1571 }

1572

1573

1574

1577 return TmpReg.isValid() ? TmpReg : Reg;

1578 }

1579};