LLVM: lib/Target/Hexagon/HexagonConstPropagation.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

36#include

37#include

38#include

39#include

40#include

41#include

42#include

43#include

44#include

45

46#define DEBUG_TYPE "hcp"

47

48using namespace llvm;

49

50namespace {

51

52

53

54

55

56

57

58 class ConstantProperties {

59 public:

60 enum {

62 Zero = 0x0001,

63 NonZero = 0x0002,

64 Finite = 0x0004,

65 Infinity = 0x0008,

66 NaN = 0x0010,

67 SignedZero = 0x0020,

68 NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero),

69 PosOrZero = 0x0100,

70 NegOrZero = 0x0200,

71 SignProperties = (PosOrZero|NegOrZero),

72 Everything = (NumericProperties|SignProperties)

73 };

74

75

76

78 };

79

81

82

83

84

85

86

87

88

89 class LatticeCell {

90 private:

91 enum { Normal, Top, Bottom };

92

93 static const unsigned MaxCellSize = 4;

94

95 unsigned Kind:2;

96 unsigned Size:3;

97 unsigned IsSpecial:1;

99

100 public:

101 union {

104 const Constant *Values[MaxCellSize];

105 };

106

107 LatticeCell() : Kind(Top), Size(0), IsSpecial(false) {

109 }

110

111 bool meet(const LatticeCell &L);

115 unsigned size() const { return Size; }

116

117 LatticeCell(const LatticeCell &L) {

118

120 L.IsSpecial ? sizeof L.Properties : L.Size * sizeof(const Constant *);

121 memcpy(Values, L.Values, N);

122 Kind = L.Kind;

123 Size = L.Size;

124 IsSpecial = L.IsSpecial;

125 }

126

127 LatticeCell &operator=(const LatticeCell &L) {

128 if (this != &L) {

129

130 uint32_t N = L.IsSpecial ? sizeof L.Properties

131 : L.Size * sizeof(const Constant *);

132 memcpy(Values, L.Values, N);

133 Kind = L.Kind;

134 Size = L.Size;

135 IsSpecial = L.IsSpecial;

136 }

137 return *this;

138 }

139

140 bool isSingle() const { return size() == 1; }

141 bool isProperty() const { return IsSpecial; }

142 bool isTop() const { return Kind == Top; }

143 bool isBottom() const { return Kind == Bottom; }

144

145 bool setBottom() {

146 bool Changed = (Kind != Bottom);

147 Kind = Bottom;

149 IsSpecial = false;

151 }

152

154

155 private:

156 void setProperty() {

157 IsSpecial = true;

160 }

161

162 bool convertToProperty();

163 };

164

165#ifndef NDEBUG

167 L.print(os);

168 return os;

169 }

170#endif

171

172 class MachineConstEvaluator;

173

174 class MachineConstPropagator {

175 public:

176 MachineConstPropagator(MachineConstEvaluator &E) : MCE(E) {

177 Bottom.setBottom();

178 }

179

180

181

182

183

184

185

186

187

188

189

190 class CellMap {

191 public:

192 CellMap() {

194 Bottom.setBottom();

195 }

196

197 void clear() { Map.clear(); }

198

200

201 if (!R.isVirtual())

202 return true;

203 MapType::const_iterator F = Map.find(R);

204 return F != Map.end();

205 }

206

207 const LatticeCell &get(Register R) const {

208 if (!R.isVirtual())

209 return Bottom;

210 MapType::const_iterator F = Map.find(R);

211 if (F != Map.end())

212 return F->second;

213 return Top;

214 }

215

216

217 void update(Register R, const LatticeCell &L) { Map[R] = L; }

218

220

221 private:

222 using MapType = std::map<Register, LatticeCell>;

223

224 MapType Map;

225

226

227

228 LatticeCell Top, Bottom;

229

230 public:

232

235 };

236

238

239 private:

242 void visitBranchesFrom(const MachineInstr &BrI);

243 void visitUsesOf(unsigned R);

247

250

252 MachineConstEvaluator &MCE;

253

254 using CFGEdge = std::pair<unsigned, unsigned>;

255 using SetOfCFGEdge = std::set;

256 using SetOfInstr = std::set<const MachineInstr *>;

257 using QueueOfCFGEdge = std::queue;

258

259 LatticeCell Bottom;

260 CellMap Cells;

261 SetOfCFGEdge EdgeExec;

262 SetOfInstr InstrExec;

263 QueueOfCFGEdge FlowQ;

264 };

265

266

267

268

269 class MachineConstEvaluator {

270 public:

274 virtual ~MachineConstEvaluator() = default;

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291 using CellMap = MachineConstPropagator::CellMap;

293 CellMap &Outputs) = 0;

295 LatticeCell &Result) = 0;

298 bool &CanFallThru) = 0;

299 virtual bool rewrite(MachineInstr &MI, const CellMap &Inputs) = 0;

300

302

303 protected:

306

307 struct Comparison {

308 enum {

309 Unk = 0x00,

310 EQ = 0x01,

311 NE = 0x02,

312 L = 0x04,

313 G = 0x08,

314 U = 0x40,

315 LTs = L,

316 LEs = L | EQ,

317 GTs = G,

318 GEs = G | EQ,

319 LTu = L | U,

320 LEu = L | EQ | U,

321 GTu = G | U,

322 GEu = G | EQ | U

323 };

324

326 if (Cmp == EQ)

327 return NE;

328 if (Cmp == NE)

329 return EQ;

330 assert((Cmp & (L|G)) != (L|G));

331 return Cmp ^ (L|G);

332 }

333 };

334

335

336

337 bool getCell(const RegSubRegPair &R, const CellMap &Inputs,

338 LatticeCell &RC);

339 bool constToInt(const Constant *C, APInt &Val) const;

341

342

345 bool &Result);

347 const CellMap &Inputs, bool &Result);

349 const CellMap &Inputs, bool &Result);

351 bool &Result);

353 bool &Result);

355 bool &Result);

356

357 bool evaluateCOPY(const RegSubRegPair &R1, const CellMap &Inputs,

358 LatticeCell &Result);

359

360

362 const CellMap &Inputs, LatticeCell &Result);

364 const CellMap &Inputs, LatticeCell &Result);

365 bool evaluateANDii(const APInt &A1, const APInt &A2, APInt &Result);

367 const CellMap &Inputs, LatticeCell &Result);

369 const CellMap &Inputs, LatticeCell &Result);

370 bool evaluateORii(const APInt &A1, const APInt &A2, APInt &Result);

372 const CellMap &Inputs, LatticeCell &Result);

374 const CellMap &Inputs, LatticeCell &Result);

375 bool evaluateXORii(const APInt &A1, const APInt &A2, APInt &Result);

376

377

378 bool evaluateZEXTr(const RegSubRegPair &R1, unsigned Width, unsigned Bits,

379 const CellMap &Inputs, LatticeCell &Result);

380 bool evaluateZEXTi(const APInt &A1, unsigned Width, unsigned Bits,

382 bool evaluateSEXTr(const RegSubRegPair &R1, unsigned Width, unsigned Bits,

383 const CellMap &Inputs, LatticeCell &Result);

384 bool evaluateSEXTi(const APInt &A1, unsigned Width, unsigned Bits,

386

387

388 bool evaluateCLBr(const RegSubRegPair &R1, bool Zeros, bool Ones,

389 const CellMap &Inputs, LatticeCell &Result);

390 bool evaluateCLBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result);

391 bool evaluateCTBr(const RegSubRegPair &R1, bool Zeros, bool Ones,

392 const CellMap &Inputs, LatticeCell &Result);

393 bool evaluateCTBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result);

394

395

396 bool evaluateEXTRACTr(const RegSubRegPair &R1, unsigned Width,

398 const CellMap &Inputs, LatticeCell &Result);

399 bool evaluateEXTRACTi(const APInt &A1, unsigned Bits, unsigned Offset,

401

402 bool evaluateSplatr(const RegSubRegPair &R1, unsigned Bits, unsigned Count,

403 const CellMap &Inputs, LatticeCell &Result);

404 bool evaluateSplati(const APInt &A1, unsigned Bits, unsigned Count,

406 };

407

408}

409

414 return Zero | PosOrZero | NegOrZero | Finite;

415 uint32_t Props = (NonZero | Finite);

417 return Props | NegOrZero;

418 return Props | PosOrZero;

419 }

420

423 uint32_t Props = CF->isNegative() ? (NegOrZero|NonZero)

424 : PosOrZero;

426 return (Props & ~NumericProperties) | (Zero|Finite);

427 Props = (Props & ~NumericProperties) | NonZero;

429 return (Props & ~NumericProperties) | NaN;

432 return (Props & ~NumericProperties) | Infinity;

433 Props |= Finite;

434 return Props;

435 }

436

438}

439

440

441

442bool LatticeCell::convertToProperty() {

443 if (isProperty())

444 return false;

445

446

447 uint32_t Everything = ConstantProperties::Everything;

448 uint32_t Ps = !isTop() ? properties()

449 : Everything;

450 if (Ps != ConstantProperties::Unknown) {

451 Properties = Ps;

452 setProperty();

453 } else {

454 setBottom();

455 }

456 return true;

457}

458

459#ifndef NDEBUG

460void LatticeCell::print(raw_ostream &os) const {

461 if (isProperty()) {

462 os << "{ ";

463 uint32_t Ps = properties();

464 if (Ps & ConstantProperties::Zero)

465 os << "zero ";

466 if (Ps & ConstantProperties::NonZero)

467 os << "nonzero ";

468 if (Ps & ConstantProperties::Finite)

469 os << "finite ";

470 if (Ps & ConstantProperties::Infinity)

471 os << "infinity ";

472 if (Ps & ConstantProperties::NaN)

473 os << "nan ";

474 if (Ps & ConstantProperties::PosOrZero)

475 os << "poz ";

476 if (Ps & ConstantProperties::NegOrZero)

477 os << "nez ";

478 os << '}';

479 return;

480 }

481

482 os << "{ ";

483 if (isBottom()) {

484 os << "bottom";

485 } else if (isTop()) {

486 os << "top";

487 } else {

488 for (unsigned i = 0; i < size(); ++i) {

490 if (i != 0)

491 os << ", ";

492 C->print(os);

493 }

494 }

495 os << " }";

496}

497#endif

498

499

500

501bool LatticeCell::meet(const LatticeCell &L) {

503 if (L.isBottom())

505 if (isBottom() || L.isTop())

507 if (isTop()) {

508 *this = L;

509

510 return true;

511 }

512

513

514 if (L.isProperty())

515 return add(L.properties());

516 for (unsigned i = 0; i < L.size(); ++i) {

517 const Constant *LC = L.Values[i];

519 }

521}

522

523

524

525

526

527

528bool LatticeCell::add(const Constant *LC) {

530 if (isBottom())

531 return false;

532

533 if (!isProperty()) {

534

535

536 unsigned Index = 0;

537 while (Index < Size) {

539

540 if (C == LC)

541 return false;

543 }

544 if (Index < MaxCellSize) {

545 Values[Index] = LC;

548 return true;

549 }

550 }

551

553

554

555

556 Changed = convertToProperty();

557 uint32_t Ps = properties();

558 uint32_t NewPs = Ps & ConstantProperties::deduce(LC);

559 if (NewPs == ConstantProperties::Unknown) {

560 setBottom();

561 return true;

562 }

563 if (Ps != NewPs) {

564 Properties = NewPs;

566 }

568}

569

570

571

572bool LatticeCell::add(uint32_t Property) {

573 bool Changed = convertToProperty();

574 uint32_t Ps = properties();

575 if (Ps == (Ps & Property))

578 return true;

579}

580

581

582

583uint32_t LatticeCell::properties() const {

584 if (isProperty())

585 return Properties;

586 assert(!isTop() && "Should not call this for a top cell");

587 if (isBottom())

588 return ConstantProperties::Unknown;

589

591 uint32_t Ps = ConstantProperties::deduce(Values[0]);

592 for (unsigned i = 1; i < size(); ++i) {

593 if (Ps == ConstantProperties::Unknown)

594 break;

595 Ps &= ConstantProperties::deduce(Values[i]);

596 }

597 return Ps;

598}

599

600#ifndef NDEBUG

601void MachineConstPropagator::CellMap::print(raw_ostream &os,

602 const TargetRegisterInfo &TRI) const {

603 for (auto &I : Map)

604 dbgs() << " " << printReg(I.first, &TRI) << " -> " << I.second << '\n';

605}

606#endif

607

608void MachineConstPropagator::visitPHI(const MachineInstr &PN) {

609 const MachineBasicBlock *MB = PN.getParent();

612

613 const MachineOperand &MD = PN.getOperand(0);

615 assert(DefR.Reg.isVirtual());

616

618

619

620 if (DefR.SubReg) {

621Bottomize:

622 const LatticeCell &T = Cells.get(DefR.Reg);

624 Cells.update(DefR.Reg, Bottom);

626 visitUsesOf(DefR.Reg);

627 return;

628 }

629

630 LatticeCell DefC = Cells.get(DefR.Reg);

631

632 for (unsigned i = 1, n = PN.getNumOperands(); i < n; i += 2) {

634 unsigned PBN = PB->getNumber();

635 if (!EdgeExec.count(CFGEdge(PBN, MBN))) {

638 continue;

639 }

640 const MachineOperand &SO = PN.getOperand(i);

642

643

644 if (!UseR.Reg.isVirtual())

645 goto Bottomize;

646

647 if (!Cells.has(UseR.Reg))

648 continue;

649

650 LatticeCell SrcC;

651 bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);

653 << printReg(UseR.Reg, &MCE.TRI, UseR.SubReg) << SrcC

654 << '\n');

655 Changed |= Eval ? DefC.meet(SrcC)

656 : DefC.setBottom();

657 Cells.update(DefR.Reg, DefC);

658 if (DefC.isBottom())

659 break;

660 }

662 visitUsesOf(DefR.Reg);

663}

664

665void MachineConstPropagator::visitNonBranch(const MachineInstr &MI) {

667 << "): " << MI);

668 CellMap Outputs;

669 bool Eval = MCE.evaluate(MI, Cells, Outputs);

671 if (Eval) {

672 dbgs() << " outputs:";

673 for (auto &I : Outputs)

674 dbgs() << ' ' << I.second;

675 dbgs() << '\n';

676 }

677 });

678

679

680

681 for (const MachineOperand &MO : MI.operands()) {

682 if (!MO.isReg() || !MO.isDef())

683 continue;

685

686 if (!DefR.Reg.isVirtual())

687 continue;

689

690 if (!Eval) {

691 const LatticeCell &T = Cells.get(DefR.Reg);

693 Cells.update(DefR.Reg, Bottom);

694 } else {

695

696

697 if (!Outputs.has(DefR.Reg))

698 continue;

699 LatticeCell RC = Cells.get(DefR.Reg);

700 Changed = RC.meet(Outputs.get(DefR.Reg));

701 Cells.update(DefR.Reg, RC);

702 }

704 visitUsesOf(DefR.Reg);

705 }

706}

707

708

709

710

711

712void MachineConstPropagator::visitBranchesFrom(const MachineInstr &BrI) {

713 const MachineBasicBlock &B = *BrI.getParent();

714 unsigned MBN = B.getNumber();

717

718 SetVector<const MachineBasicBlock*> Targets;

719 bool EvalOk = true, FallsThru = true;

720 while (It != End) {

721 const MachineInstr &MI = *It;

722 InstrExec.insert(&MI);

723 LLVM_DEBUG(dbgs() << "Visiting " << (EvalOk ? "BR" : "br") << "("

725

726

727

728 EvalOk = EvalOk && MCE.evaluate(MI, Cells, Targets, FallsThru);

729 if (!EvalOk)

730 FallsThru = true;

731 if (!FallsThru)

732 break;

733 ++It;

734 }

735

736 if (B.mayHaveInlineAsmBr())

737 EvalOk = false;

738

739 if (EvalOk) {

740

741

742

743 for (const MachineBasicBlock *SB : B.successors()) {

744 if (SB->isEHPad())

746 }

747 if (FallsThru) {

748 const MachineFunction &MF = *B.getParent();

753 }

754 } else {

755

756

757

758

759

761 LLVM_DEBUG(dbgs() << " failed to evaluate a branch...adding all CFG "

762 "successors\n");

764 }

765

766 for (const MachineBasicBlock *TB : Targets) {

767 unsigned TBN = TB->getNumber();

770 FlowQ.push(CFGEdge(MBN, TBN));

771 }

772}

773

774void MachineConstPropagator::visitUsesOf(unsigned Reg) {

776 << Cells.get(Reg) << '\n');

777 for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {

778

779

780

781 if (!InstrExec.count(&MI))

782 continue;

783 if (MI.isPHI())

784 visitPHI(MI);

785 else if (MI.isBranch())

786 visitNonBranch(MI);

787 else

788 visitBranchesFrom(MI);

789 }

790}

791

792bool MachineConstPropagator::computeBlockSuccessors(const MachineBasicBlock *MB,

793 SetVector<const MachineBasicBlock*> &Targets) {

795

797 for (const MachineInstr &MI : *MB) {

798 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)

799 return false;

800 if (MI.isDebugInstr())

801 continue;

802 if (MI.isBranch()) {

803 FirstBr = MI.getIterator();

804 break;

805 }

806 }

807

809

810 bool DoNext = true;

812 const MachineInstr &MI = *I;

813

814 if (MI.isDebugInstr())

815 continue;

816 if (!InstrExec.count(&MI))

817 continue;

818 bool Eval = MCE.evaluate(MI, Cells, Targets, DoNext);

819 if (!Eval)

820 return false;

821 if (!DoNext)

822 break;

823 }

824

825 if (DoNext) {

828 if (NextI != MB->getParent()->end())

829 Targets.insert(&*NextI);

830 }

831

832

833 for (const MachineBasicBlock *SB : MB->successors())

834 if (SB->isEHPad())

836

837 return true;

838}

839

840void MachineConstPropagator::removeCFGEdge(MachineBasicBlock *From,

841 MachineBasicBlock *To) {

842

844

845 for (MachineInstr &PN : To->phis()) {

846

848 while (N > 0) {

852 }

853 N -= 2;

854 }

855 }

856}

857

858void MachineConstPropagator::propagate(MachineFunction &MF) {

860 unsigned EntryNum = Entry->getNumber();

861

862

863 FlowQ.push(CFGEdge(EntryNum, EntryNum));

864

865 while (!FlowQ.empty()) {

866 CFGEdge Edge = FlowQ.front();

867 FlowQ.pop();

868

870 dbgs() << "Picked edge "

873 if (Edge.first != EntryNum)

874 if (EdgeExec.count(Edge))

875 continue;

876 EdgeExec.insert(Edge);

878

879

880

881

882

884

885

886 while (It != End && It->isPHI()) {

887 InstrExec.insert(&*It);

888 visitPHI(*It);

889 ++It;

890 }

891

892

893

894

895 while (It != End && It->isDebugInstr())

896 ++It;

897 assert(It == End || !It->isPHI());

898

899 if (It != End && InstrExec.count(&*It))

900 continue;

901

902

903 while (It != End && !It->isBranch()) {

904 if (!It->isDebugInstr()) {

905 InstrExec.insert(&*It);

906 visitNonBranch(*It);

907 }

908 ++It;

909 }

910

911

912

913

914

915 if (It != End) {

916 visitBranchesFrom(*It);

917 } else {

918

919

921 for (const MachineBasicBlock *SSB : SB->successors())

922 FlowQ.push(CFGEdge(SBN, SSB->getNumber()));

923 }

924 }

925

927 dbgs() << "Cells after propagation:\n";

928 Cells.print(dbgs(), MCE.TRI);

929 dbgs() << "Dead CFG edges:\n";

930 for (const MachineBasicBlock &B : MF) {

931 unsigned BN = B.getNumber();

932 for (const MachineBasicBlock *SB : B.successors()) {

934 if (!EdgeExec.count(CFGEdge(BN, SN)))

937 }

938 }

939 });

940}

941

942bool MachineConstPropagator::rewrite(MachineFunction &MF) {

944

945

946

947

948

949

950

951

952

953

954

955

956

957

958

959

960 std::vector<MachineBasicBlock*> POT;

961 for (MachineBasicBlock *B : post_order(&MF))

962 if (B->empty())

963 POT.push_back(B);

964

965 for (MachineBasicBlock *B : POT) {

966

967

968

969

970

971

972

973 SetVector<const MachineBasicBlock*> Targets;

974 bool HaveTargets = computeBlockSuccessors(B, Targets);

975

976

978 if (InstrExec.count(&MI)) {

979 if (MI.isBranch() && !HaveTargets)

980 continue;

981 Changed |= MCE.rewrite(MI, Cells);

982 }

983 }

984

985

986

987 for (auto I = B->begin(), E = B->end(); I != E; ++I) {

988 if (I->isPHI())

989 continue;

990

991 auto P = I;

992 while (++P != E)

993 if (P->isPHI())

994 break;

995

996 if (P == E)

997 break;

998

999 B->splice(I, B, P);

1000

1001 --I;

1002 }

1003

1004 if (HaveTargets) {

1006 for (MachineBasicBlock *SB : B->successors()) {

1007 if (!Targets.count(SB))

1010 }

1012 removeCFGEdge(B, MBB);

1013

1014

1015

1016

1017

1018 }

1019 }

1020

1021

1022

1023

1024

1025 for (MachineBasicBlock &B : MF) {

1027 if (MI.isBranch() && !InstrExec.count(&MI))

1028 B.erase(&MI);

1029 }

1031}

1032

1033

1034

1035bool MachineConstPropagator::run(MachineFunction &MF) {

1036 LLVM_DEBUG(MF.print(dbgs() << "Starting MachineConstPropagator\n", nullptr));

1037

1039

1040 Cells.clear();

1041 EdgeExec.clear();

1042 InstrExec.clear();

1043 assert(FlowQ.empty());

1044

1045 propagate(MF);

1046 bool Changed = rewrite(MF);

1047

1049 dbgs() << "End of MachineConstPropagator (Changed=" << Changed << ")\n";

1052 });

1054}

1055

1056

1057

1058

1059bool MachineConstEvaluator::getCell(const RegSubRegPair &R,

1060 const CellMap &Inputs, LatticeCell &RC) {

1061 if (R.Reg.isVirtual())

1062 return false;

1063 const LatticeCell &L = Inputs.get(R.Reg);

1064 if (R.SubReg) {

1065 RC = L;

1066 return !RC.isBottom();

1067 }

1068 bool Eval = evaluate(R, L, RC);

1069 return Eval && !RC.isBottom();

1070}

1071

1072bool MachineConstEvaluator::constToInt(const Constant *C,

1073 APInt &Val) const {

1075 if (!CI)

1076 return false;

1078 return true;

1079}

1080

1081const ConstantInt *MachineConstEvaluator::intToConst(const APInt &Val) const {

1082 return ConstantInt::get(CX, Val);

1083}

1084

1085bool MachineConstEvaluator::evaluateCMPrr(uint32_t Cmp, const RegSubRegPair &R1,

1087 const CellMap &Inputs, bool &Result) {

1088 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));

1089 LatticeCell LS1, LS2;

1090 if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))

1091 return false;

1092

1093 bool IsProp1 = LS1.isProperty();

1094 bool IsProp2 = LS2.isProperty();

1095 if (IsProp1) {

1096 uint32_t Prop1 = LS1.properties();

1097 if (IsProp2)

1098 return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result);

1099 uint32_t NegCmp = Comparison::negate(Cmp);

1100 return evaluateCMPrp(NegCmp, R2, Prop1, Inputs, Result);

1101 }

1102 if (IsProp2) {

1103 uint32_t Prop2 = LS2.properties();

1104 return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);

1105 }

1106

1107 APInt A;

1108 bool IsTrue = true, IsFalse = true;

1109 for (unsigned i = 0; i < LS2.size(); ++i) {

1110 bool Res;

1111 bool Computed = constToInt(LS2.Values[i], A) &&

1112 evaluateCMPri(Cmp, R1, A, Inputs, Res);

1113 if (!Computed)

1114 return false;

1115 IsTrue &= Res;

1116 IsFalse &= !Res;

1117 }

1118 assert(!IsTrue || !IsFalse);

1119

1121

1122 return IsTrue || IsFalse;

1123}

1124

1125bool MachineConstEvaluator::evaluateCMPri(uint32_t Cmp, const RegSubRegPair &R1,

1126 const APInt &A2,

1127 const CellMap &Inputs, bool &Result) {

1129 LatticeCell LS;

1130 if (!getCell(R1, Inputs, LS))

1131 return false;

1132 if (LS.isProperty())

1133 return evaluateCMPpi(Cmp, LS.properties(), A2, Result);

1134

1135 APInt A;

1136 bool IsTrue = true, IsFalse = true;

1137 for (unsigned i = 0; i < LS.size(); ++i) {

1138 bool Res;

1139 bool Computed = constToInt(LS.Values[i], A) &&

1140 evaluateCMPii(Cmp, A, A2, Res);

1141 if (!Computed)

1142 return false;

1143 IsTrue &= Res;

1144 IsFalse &= !Res;

1145 }

1146 assert(!IsTrue || !IsFalse);

1147

1149

1150 return IsTrue || IsFalse;

1151}

1152

1153bool MachineConstEvaluator::evaluateCMPrp(uint32_t Cmp, const RegSubRegPair &R1,

1154 uint64_t Props2,

1155 const CellMap &Inputs, bool &Result) {

1157 LatticeCell LS;

1158 if (!getCell(R1, Inputs, LS))

1159 return false;

1160 if (LS.isProperty())

1161 return evaluateCMPpp(Cmp, LS.properties(), Props2, Result);

1162

1163 APInt A;

1164 uint32_t NegCmp = Comparison::negate(Cmp);

1165 bool IsTrue = true, IsFalse = true;

1166 for (unsigned i = 0; i < LS.size(); ++i) {

1167 bool Res;

1168 bool Computed = constToInt(LS.Values[i], A) &&

1169 evaluateCMPpi(NegCmp, Props2, A, Res);

1170 if (!Computed)

1171 return false;

1172 IsTrue &= Res;

1173 IsFalse &= !Res;

1174 }

1175 assert(!IsTrue || !IsFalse);

1177 return IsTrue || IsFalse;

1178}

1179

1180bool MachineConstEvaluator::evaluateCMPii(uint32_t Cmp, const APInt &A1,

1181 const APInt &A2, bool &Result) {

1182

1183 if (Cmp == Comparison::NE) {

1185 return true;

1186 }

1187 if (Cmp == Comparison::EQ) {

1189 return true;

1190 }

1191 if (Cmp & Comparison::EQ) {

1193 return (Result = true);

1194 }

1195 assert((Cmp & (Comparison::L | Comparison::G)) && "Malformed comparison");

1197

1200 unsigned MaxW = (W1 >= W2) ? W1 : W2;

1201 if (Cmp & Comparison::U) {

1202 APInt Zx1 = A1.zext(MaxW);

1203 APInt Zx2 = A2.zext(MaxW);

1204 if (Cmp & Comparison::L)

1206 else if (Cmp & Comparison::G)

1208 return true;

1209 }

1210

1211

1212 APInt Sx1 = A1.sext(MaxW);

1213 APInt Sx2 = A2.sext(MaxW);

1214 if (Cmp & Comparison::L)

1216 else if (Cmp & Comparison::G)

1218 return true;

1219}

1220

1221bool MachineConstEvaluator::evaluateCMPpi(uint32_t Cmp, uint32_t Props,

1222 const APInt &A2, bool &Result) {

1223 if (Props == ConstantProperties::Unknown)

1224 return false;

1225

1226

1227 if (Props & ConstantProperties::NaN)

1228 return false;

1229

1230

1231

1232 if (!(Props & ConstantProperties::Finite))

1233 return false;

1234

1235

1236

1237 if (Cmp & Comparison::U) {

1238

1239 if (A2 == 0) {

1240

1241 if (Props & ConstantProperties::Zero)

1242 Result = (Cmp & Comparison::EQ);

1243 else if (Props & ConstantProperties::NonZero)

1244 Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);

1245 else

1246 return false;

1247 return true;

1248 }

1249

1250 if (Props & ConstantProperties::Zero) {

1251 Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);

1252 return true;

1253 }

1254 return false;

1255 }

1256

1257

1258 if (Props & ConstantProperties::Zero) {

1259 if (A2 == 0)

1260 Result = (Cmp & Comparison::EQ);

1261 else

1262 Result = (Cmp == Comparison::NE) ||

1263 ((Cmp & Comparison::L) && !A2.isNegative()) ||

1265 return true;

1266 }

1267 if (Props & ConstantProperties::PosOrZero) {

1268

1270 return false;

1271

1272 Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);

1273 return true;

1274 }

1275 if (Props & ConstantProperties::NegOrZero) {

1276

1278 return false;

1279

1280 Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);

1281 return true;

1282 }

1283

1284 return false;

1285}

1286

1287bool MachineConstEvaluator::evaluateCMPpp(uint32_t Cmp, uint32_t Props1,

1288 uint32_t Props2, bool &Result) {

1289 using P = ConstantProperties;

1290

1291 if ((Props1 & P::NaN) && (Props2 & P::NaN))

1292 return false;

1293 if (!(Props1 & P::Finite) || !(Props2 & P::Finite))

1294 return false;

1295

1296 bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero);

1297 bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);

1298 if (Zero1 && Zero2) {

1299 Result = (Cmp & Comparison::EQ);

1300 return true;

1301 }

1302 if (Cmp == Comparison::NE) {

1303 if ((Zero1 && NonZero2) || (NonZero1 && Zero2))

1304 return (Result = true);

1305 return false;

1306 }

1307

1308 if (Cmp & Comparison::U) {

1309

1310

1311 if (Zero1 && NonZero2) {

1313 return true;

1314 }

1315 if (NonZero1 && Zero2) {

1317 return true;

1318 }

1319 return false;

1320 }

1321

1322

1323 bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);

1324 bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);

1325 if (Nez1 && Poz2) {

1326 if (NonZero1 || NonZero2) {

1328 return true;

1329 }

1330

1331 if ((Cmp & Comparison::EQ) && (Cmp & Comparison::L))

1332 return (Result = true);

1333 }

1334 if (Poz1 && Nez2) {

1335 if (NonZero1 || NonZero2) {

1337 return true;

1338 }

1339

1340 if ((Cmp & Comparison::EQ) && (Cmp & Comparison::G))

1341 return (Result = true);

1342 }

1343

1344 return false;

1345}

1346

1347bool MachineConstEvaluator::evaluateCOPY(const RegSubRegPair &R1,

1348 const CellMap &Inputs,

1349 LatticeCell &Result) {

1350 return getCell(R1, Inputs, Result);

1351}

1352

1353bool MachineConstEvaluator::evaluateANDrr(const RegSubRegPair &R1,

1355 const CellMap &Inputs,

1356 LatticeCell &Result) {

1357 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));

1358 const LatticeCell &L1 = Inputs.get(R2.Reg);

1359 const LatticeCell &L2 = Inputs.get(R2.Reg);

1360

1361

1362

1363 if (L2.isBottom()) {

1364 if (L1.isBottom())

1365 return false;

1366 return evaluateANDrr(R2, R1, Inputs, Result);

1367 }

1368 LatticeCell LS2;

1370 return false;

1371 if (LS2.isBottom() || LS2.isProperty())

1372 return false;

1373

1374 APInt A;

1375 for (unsigned i = 0; i < LS2.size(); ++i) {

1376 LatticeCell RC;

1377 bool Eval = constToInt(LS2.Values[i], A) &&

1378 evaluateANDri(R1, A, Inputs, RC);

1379 if (!Eval)

1380 return false;

1382 }

1383 return Result.isBottom();

1384}

1385

1386bool MachineConstEvaluator::evaluateANDri(const RegSubRegPair &R1,

1387 const APInt &A2,

1388 const CellMap &Inputs,

1389 LatticeCell &Result) {

1391 if (A2 == -1)

1392 return getCell(R1, Inputs, Result);

1393 if (A2 == 0) {

1394 LatticeCell RC;

1395 RC.add(intToConst(A2));

1396

1398 return true;

1399 }

1400 LatticeCell LS1;

1401 if (!getCell(R1, Inputs, LS1))

1402 return false;

1403 if (LS1.isBottom() || LS1.isProperty())

1404 return false;

1405

1406 APInt A, ResA;

1407 for (unsigned i = 0; i < LS1.size(); ++i) {

1408 bool Eval = constToInt(LS1.Values[i], A) &&

1409 evaluateANDii(A, A2, ResA);

1410 if (!Eval)

1411 return false;

1412 const Constant *C = intToConst(ResA);

1414 }

1415 return Result.isBottom();

1416}

1417

1418bool MachineConstEvaluator::evaluateANDii(const APInt &A1,

1419 const APInt &A2, APInt &Result) {

1421 return true;

1422}

1423

1424bool MachineConstEvaluator::evaluateORrr(const RegSubRegPair &R1,

1426 const CellMap &Inputs,

1427 LatticeCell &Result) {

1428 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));

1429 const LatticeCell &L1 = Inputs.get(R2.Reg);

1430 const LatticeCell &L2 = Inputs.get(R2.Reg);

1431

1432

1433

1434 if (L2.isBottom()) {

1435 if (L1.isBottom())

1436 return false;

1437 return evaluateORrr(R2, R1, Inputs, Result);

1438 }

1439 LatticeCell LS2;

1441 return false;

1442 if (LS2.isBottom() || LS2.isProperty())

1443 return false;

1444

1445 APInt A;

1446 for (unsigned i = 0; i < LS2.size(); ++i) {

1447 LatticeCell RC;

1448 bool Eval = constToInt(LS2.Values[i], A) &&

1449 evaluateORri(R1, A, Inputs, RC);

1450 if (!Eval)

1451 return false;

1453 }

1454 return Result.isBottom();

1455}

1456

1457bool MachineConstEvaluator::evaluateORri(const RegSubRegPair &R1,

1458 const APInt &A2, const CellMap &Inputs,

1459 LatticeCell &Result) {

1461 if (A2 == 0)

1462 return getCell(R1, Inputs, Result);

1463 if (A2 == -1) {

1464 LatticeCell RC;

1465 RC.add(intToConst(A2));

1466

1468 return true;

1469 }

1470 LatticeCell LS1;

1471 if (!getCell(R1, Inputs, LS1))

1472 return false;

1473 if (LS1.isBottom() || LS1.isProperty())

1474 return false;

1475

1476 APInt A, ResA;

1477 for (unsigned i = 0; i < LS1.size(); ++i) {

1478 bool Eval = constToInt(LS1.Values[i], A) &&

1479 evaluateORii(A, A2, ResA);

1480 if (!Eval)

1481 return false;

1482 const Constant *C = intToConst(ResA);

1484 }

1485 return Result.isBottom();

1486}

1487

1488bool MachineConstEvaluator::evaluateORii(const APInt &A1,

1489 const APInt &A2, APInt &Result) {

1491 return true;

1492}

1493

1494bool MachineConstEvaluator::evaluateXORrr(const RegSubRegPair &R1,

1496 const CellMap &Inputs,

1497 LatticeCell &Result) {

1498 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));

1499 LatticeCell LS1, LS2;

1500 if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))

1501 return false;

1502 if (LS1.isProperty()) {

1503 if (LS1.properties() & ConstantProperties::Zero)

1504 return !(Result = LS2).isBottom();

1505 return false;

1506 }

1507 if (LS2.isProperty()) {

1508 if (LS2.properties() & ConstantProperties::Zero)

1509 return !(Result = LS1).isBottom();

1510 return false;

1511 }

1512

1513 APInt A;

1514 for (unsigned i = 0; i < LS2.size(); ++i) {

1515 LatticeCell RC;

1516 bool Eval = constToInt(LS2.Values[i], A) &&

1517 evaluateXORri(R1, A, Inputs, RC);

1518 if (!Eval)

1519 return false;

1521 }

1522 return Result.isBottom();

1523}

1524

1525bool MachineConstEvaluator::evaluateXORri(const RegSubRegPair &R1,

1526 const APInt &A2,

1527 const CellMap &Inputs,

1528 LatticeCell &Result) {

1530 LatticeCell LS1;

1531 if (!getCell(R1, Inputs, LS1))

1532 return false;

1533 if (LS1.isProperty()) {

1534 if (LS1.properties() & ConstantProperties::Zero) {

1535 const Constant *C = intToConst(A2);

1537 return Result.isBottom();

1538 }

1539 return false;

1540 }

1541

1542 APInt A, XA;

1543 for (unsigned i = 0; i < LS1.size(); ++i) {

1544 bool Eval = constToInt(LS1.Values[i], A) &&

1545 evaluateXORii(A, A2, XA);

1546 if (!Eval)

1547 return false;

1548 const Constant *C = intToConst(XA);

1550 }

1551 return Result.isBottom();

1552}

1553

1554bool MachineConstEvaluator::evaluateXORii(const APInt &A1,

1555 const APInt &A2, APInt &Result) {

1557 return true;

1558}

1559

1560bool MachineConstEvaluator::evaluateZEXTr(const RegSubRegPair &R1,

1561 unsigned Width, unsigned Bits,

1562 const CellMap &Inputs,

1563 LatticeCell &Result) {

1565 LatticeCell LS1;

1566 if (!getCell(R1, Inputs, LS1))

1567 return false;

1568 if (LS1.isProperty())

1569 return false;

1570

1571 APInt A, XA;

1572 for (unsigned i = 0; i < LS1.size(); ++i) {

1573 bool Eval = constToInt(LS1.Values[i], A) &&

1574 evaluateZEXTi(A, Width, Bits, XA);

1575 if (!Eval)

1576 return false;

1577 const Constant *C = intToConst(XA);

1579 }

1580 return true;

1581}

1582

1583bool MachineConstEvaluator::evaluateZEXTi(const APInt &A1, unsigned Width,

1584 unsigned Bits, APInt &Result) {

1586 (void)BW;

1587 assert(Width >= Bits && BW >= Bits);

1590 return true;

1591}

1592

1593bool MachineConstEvaluator::evaluateSEXTr(const RegSubRegPair &R1,

1594 unsigned Width, unsigned Bits,

1595 const CellMap &Inputs,

1596 LatticeCell &Result) {

1598 LatticeCell LS1;

1599 if (!getCell(R1, Inputs, LS1))

1600 return false;

1601 if (LS1.isBottom() || LS1.isProperty())

1602 return false;

1603

1604 APInt A, XA;

1605 for (unsigned i = 0; i < LS1.size(); ++i) {

1606 bool Eval = constToInt(LS1.Values[i], A) &&

1607 evaluateSEXTi(A, Width, Bits, XA);

1608 if (!Eval)

1609 return false;

1610 const Constant *C = intToConst(XA);

1612 }

1613 return true;

1614}

1615

1616bool MachineConstEvaluator::evaluateSEXTi(const APInt &A1, unsigned Width,

1617 unsigned Bits, APInt &Result) {

1619 assert(Width >= Bits && BW >= Bits);

1620

1621

1622

1623 if (Bits == 0) {

1624 Result = APInt(Width, 0);

1625 return true;

1626 }

1627

1628 if (BW <= 64 && Bits != 0) {

1630 switch (Bits) {

1631 case 8:

1632 V = static_cast<int8_t>(V);

1633 break;

1634 case 16:

1635 V = static_cast<int16_t>(V);

1636 break;

1637 case 32:

1638 V = static_cast<int32_t>(V);

1639 break;

1640 default:

1641

1642

1643

1644 V = (V << (64-Bits)) >> (64-Bits);

1645 break;

1646 }

1647

1648

1649 Result = APInt(Width, V, true);

1650 return true;

1651 }

1652

1653 if (Bits < BW)

1655 else

1657 return true;

1658}

1659

1660bool MachineConstEvaluator::evaluateCLBr(const RegSubRegPair &R1, bool Zeros,

1661 bool Ones, const CellMap &Inputs,

1662 LatticeCell &Result) {

1664 LatticeCell LS1;

1665 if (!getCell(R1, Inputs, LS1))

1666 return false;

1667 if (LS1.isBottom() || LS1.isProperty())

1668 return false;

1669

1670 APInt A, CA;

1671 for (unsigned i = 0; i < LS1.size(); ++i) {

1672 bool Eval = constToInt(LS1.Values[i], A) &&

1673 evaluateCLBi(A, Zeros, Ones, CA);

1674 if (!Eval)

1675 return false;

1676 const Constant *C = intToConst(CA);

1678 }

1679 return true;

1680}

1681

1682bool MachineConstEvaluator::evaluateCLBi(const APInt &A1, bool Zeros,

1683 bool Ones, APInt &Result) {

1685 if (!Zeros && !Ones)

1686 return false;

1687 unsigned Count = 0;

1688 if (Zeros && (Count == 0))

1690 if (Ones && (Count == 0))

1692 Result = APInt(BW, static_cast<uint64_t>(Count), false);

1693 return true;

1694}

1695

1696bool MachineConstEvaluator::evaluateCTBr(const RegSubRegPair &R1, bool Zeros,

1697 bool Ones, const CellMap &Inputs,

1698 LatticeCell &Result) {

1700 LatticeCell LS1;

1701 if (!getCell(R1, Inputs, LS1))

1702 return false;

1703 if (LS1.isBottom() || LS1.isProperty())

1704 return false;

1705

1706 APInt A, CA;

1707 for (unsigned i = 0; i < LS1.size(); ++i) {

1708 bool Eval = constToInt(LS1.Values[i], A) &&

1709 evaluateCTBi(A, Zeros, Ones, CA);

1710 if (!Eval)

1711 return false;

1712 const Constant *C = intToConst(CA);

1714 }

1715 return true;

1716}

1717

1718bool MachineConstEvaluator::evaluateCTBi(const APInt &A1, bool Zeros,

1719 bool Ones, APInt &Result) {

1721 if (!Zeros && !Ones)

1722 return false;

1723 unsigned Count = 0;

1724 if (Zeros && (Count == 0))

1726 if (Ones && (Count == 0))

1728 Result = APInt(BW, static_cast<uint64_t>(Count), false);

1729 return true;

1730}

1731

1732bool MachineConstEvaluator::evaluateEXTRACTr(const RegSubRegPair &R1,

1733 unsigned Width, unsigned Bits,

1735 const CellMap &Inputs,

1736 LatticeCell &Result) {

1739 LatticeCell LS1;

1740 if (!getCell(R1, Inputs, LS1))

1741 return false;

1742 if (LS1.isBottom())

1743 return false;

1744 if (LS1.isProperty()) {

1745 uint32_t Ps = LS1.properties();

1746 if (Ps & ConstantProperties::Zero) {

1747 const Constant *C = intToConst(APInt(Width, 0, false));

1749 return true;

1750 }

1751 return false;

1752 }

1753

1754 APInt A, CA;

1755 for (unsigned i = 0; i < LS1.size(); ++i) {

1756 bool Eval = constToInt(LS1.Values[i], A) &&

1758 if (!Eval)

1759 return false;

1760 const Constant *C = intToConst(CA);

1762 }

1763 return true;

1764}

1765

1766bool MachineConstEvaluator::evaluateEXTRACTi(const APInt &A1, unsigned Bits,

1767 unsigned Offset, bool Signed, APInt &Result) {

1770

1771 if (Bits == 0) {

1772 Result = APInt(BW, 0);

1773 return true;

1774 }

1775 if (BW <= 64) {

1779 V >>= (64-Bits);

1780 else

1781 V = static_cast<uint64_t>(V) >> (64-Bits);

1783 return true;

1784 }

1787 else

1789 return true;

1790}

1791

1792bool MachineConstEvaluator::evaluateSplatr(const RegSubRegPair &R1,

1793 unsigned Bits, unsigned Count,

1794 const CellMap &Inputs,

1795 LatticeCell &Result) {

1797 LatticeCell LS1;

1798 if (!getCell(R1, Inputs, LS1))

1799 return false;

1800 if (LS1.isBottom() || LS1.isProperty())

1801 return false;

1802

1803 APInt A, SA;

1804 for (unsigned i = 0; i < LS1.size(); ++i) {

1805 bool Eval = constToInt(LS1.Values[i], A) &&

1806 evaluateSplati(A, Bits, Count, SA);

1807 if (!Eval)

1808 return false;

1809 const Constant *C = intToConst(SA);

1811 }

1812 return true;

1813}

1814

1815bool MachineConstEvaluator::evaluateSplati(const APInt &A1, unsigned Bits,

1816 unsigned Count, APInt &Result) {

1819 APInt LoBits = (Bits < BW) ? A1.trunc(Bits) : A1.zext(Bits);

1821 LoBits = LoBits.zext(SW);

1822

1823 APInt Res(SW, 0, false);

1824 for (unsigned i = 0; i < Count; ++i) {

1825 Res <<= Bits;

1826 Res |= LoBits;

1827 }

1829 return true;

1830}

1831

1832

1833

1834

1835namespace {

1836

1837 class HexagonConstEvaluator : public MachineConstEvaluator {

1838 public:

1839 HexagonConstEvaluator(MachineFunction &Fn);

1840

1841 bool evaluate(const MachineInstr &MI, const CellMap &Inputs,

1842 CellMap &Outputs) override;

1844 LatticeCell &Result) override;

1845 bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,

1846 SetVector<const MachineBasicBlock*> &Targets, bool &FallsThru)

1847 override;

1848 bool rewrite(MachineInstr &MI, const CellMap &Inputs) override;

1849

1850 private:

1852

1853 static uint32_t getCmp(unsigned Opc);

1854 static APInt getCmpImm(unsigned Opc, unsigned OpX,

1855 const MachineOperand &MO);

1856 void replaceWithNop(MachineInstr &MI);

1857

1859 const CellMap &Inputs, LatticeCell &Result);

1860 bool evaluateHexCompare(const MachineInstr &MI, const CellMap &Inputs,

1861 CellMap &Outputs);

1862

1863 bool evaluateHexCompare2(uint32_t Cmp, const MachineOperand &Src1,

1864 const MachineOperand &Src2, const CellMap &Inputs, bool &Result);

1865 bool evaluateHexLogical(const MachineInstr &MI, const CellMap &Inputs,

1866 CellMap &Outputs);

1867 bool evaluateHexCondMove(const MachineInstr &MI, const CellMap &Inputs,

1868 CellMap &Outputs);

1869 bool evaluateHexExt(const MachineInstr &MI, const CellMap &Inputs,

1870 CellMap &Outputs);

1871 bool evaluateHexVector1(const MachineInstr &MI, const CellMap &Inputs,

1872 CellMap &Outputs);

1873 bool evaluateHexVector2(const MachineInstr &MI, const CellMap &Inputs,

1874 CellMap &Outputs);

1875

1876 void replaceAllRegUsesWith(Register FromReg, Register ToReg);

1877 bool rewriteHexBranch(MachineInstr &BrI, const CellMap &Inputs);

1878 bool rewriteHexConstDefs(MachineInstr &MI, const CellMap &Inputs,

1879 bool &AllDefs);

1880 bool rewriteHexConstUses(MachineInstr &MI, const CellMap &Inputs);

1881

1882 MachineRegisterInfo *MRI;

1883 const HexagonInstrInfo &HII;

1884 const HexagonRegisterInfo &HRI;

1885 };

1886

1887 class HexagonConstPropagation : public MachineFunctionPass {

1888 public:

1889 static char ID;

1890

1891 HexagonConstPropagation() : MachineFunctionPass(ID) {}

1892

1893 StringRef getPassName() const override {

1894 return "Hexagon Constant Propagation";

1895 }

1896

1897 bool runOnMachineFunction(MachineFunction &MF) override {

1899 if (skipFunction(F))

1900 return false;

1901

1902 HexagonConstEvaluator HCE(MF);

1903 return MachineConstPropagator(HCE).run(MF);

1904 }

1905 };

1906

1907}

1908

1909char HexagonConstPropagation::ID = 0;

1910

1912 "Hexagon Constant Propagation", false, false)

1913

1914HexagonConstEvaluator::HexagonConstEvaluator(MachineFunction &Fn)

1915 : MachineConstEvaluator(Fn),

1917 HRI(*Fn.getSubtarget<HexagonSubtarget>().getRegisterInfo()) {

1918 MRI = &Fn.getRegInfo();

1919}

1920

1921bool HexagonConstEvaluator::evaluate(const MachineInstr &MI,

1922 const CellMap &Inputs, CellMap &Outputs) {

1923 if (MI.isCall())

1924 return false;

1925 if (MI.getNumOperands() == 0 || MI.getOperand(0).isReg())

1926 return false;

1927 const MachineOperand &MD = MI.getOperand(0);

1928 if (!MD.isDef())

1929 return false;

1930

1931 unsigned Opc = MI.getOpcode();

1933 assert(!DefR.SubReg);

1934 if (!DefR.Reg.isVirtual())

1935 return false;

1936

1937 if (MI.isCopy()) {

1938 LatticeCell RC;

1940 bool Eval = evaluateCOPY(SrcR, Inputs, RC);

1941 if (!Eval)

1942 return false;

1943 Outputs.update(DefR.Reg, RC);

1944 return true;

1945 }

1946 if (MI.isRegSequence()) {

1947 unsigned Sub1 = MI.getOperand(2).getImm();

1948 unsigned Sub2 = MI.getOperand(4).getImm();

1949 const TargetRegisterClass &DefRC = *MRI->getRegClass(DefR.Reg);

1950 unsigned SubLo = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_lo);

1951 unsigned SubHi = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_hi);

1952 if (Sub1 != SubLo && Sub1 != SubHi)

1953 return false;

1954 if (Sub2 != SubLo && Sub2 != SubHi)

1955 return false;

1956 assert(Sub1 != Sub2);

1957 bool LoIs1 = (Sub1 == SubLo);

1958 const MachineOperand &OpLo = LoIs1 ? MI.getOperand(1) : MI.getOperand(3);

1959 const MachineOperand &OpHi = LoIs1 ? MI.getOperand(3) : MI.getOperand(1);

1960 LatticeCell RC;

1962 bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);

1963 if (!Eval)

1964 return false;

1965 Outputs.update(DefR.Reg, RC);

1966 return true;

1967 }

1968 if (MI.isCompare()) {

1969 bool Eval = evaluateHexCompare(MI, Inputs, Outputs);

1970 return Eval;

1971 }

1972

1973 switch (Opc) {

1974 default:

1975 return false;

1976 case Hexagon::A2_tfrsi:

1977 case Hexagon::A2_tfrpi:

1978 case Hexagon::CONST32:

1979 case Hexagon::CONST64:

1980 {

1981 const MachineOperand &VO = MI.getOperand(1);

1982

1983

1984

1985 if (!VO.isImm())

1986 return false;

1987 int64_t V = MI.getOperand(1).getImm();

1989 if (W != 32 && W != 64)

1990 return false;

1991 IntegerType *Ty = (W == 32) ? Type::getInt32Ty(CX)

1992 : Type::getInt64Ty(CX);

1993 const ConstantInt *CI = ConstantInt::get(Ty, V, true);

1994 LatticeCell RC = Outputs.get(DefR.Reg);

1995 RC.add(CI);

1996 Outputs.update(DefR.Reg, RC);

1997 break;

1998 }

1999

2000 case Hexagon::PS_true:

2001 case Hexagon::PS_false:

2002 {

2003 LatticeCell RC = Outputs.get(DefR.Reg);

2004 bool NonZero = (Opc == Hexagon::PS_true);

2005 uint32_t P = NonZero ? ConstantProperties::NonZero

2006 : ConstantProperties::Zero;

2007 RC.add(P);

2008 Outputs.update(DefR.Reg, RC);

2009 break;

2010 }

2011

2012 case Hexagon::A2_and:

2013 case Hexagon::A2_andir:

2014 case Hexagon::A2_andp:

2015 case Hexagon::A2_or:

2016 case Hexagon::A2_orir:

2017 case Hexagon::A2_orp:

2018 case Hexagon::A2_xor:

2019 case Hexagon::A2_xorp:

2020 {

2021 bool Eval = evaluateHexLogical(MI, Inputs, Outputs);

2022 if (!Eval)

2023 return false;

2024 break;

2025 }

2026

2027 case Hexagon::A2_combineii:

2028 case Hexagon::A4_combineii:

2029 {

2030 if (MI.getOperand(1).isImm() || MI.getOperand(2).isImm())

2031 return false;

2032 uint64_t Hi = MI.getOperand(1).getImm();

2033 uint64_t Lo = MI.getOperand(2).getImm();

2034 uint64_t Res = (Hi << 32) | (Lo & 0xFFFFFFFF);

2035 IntegerType *Ty = Type::getInt64Ty(CX);

2036 const ConstantInt *CI = ConstantInt::get(Ty, Res, false);

2037 LatticeCell RC = Outputs.get(DefR.Reg);

2038 RC.add(CI);

2039 Outputs.update(DefR.Reg, RC);

2040 break;

2041 }

2042

2043 case Hexagon::S2_setbit_i:

2044 {

2045 int64_t B = MI.getOperand(2).getImm();

2047 APInt A(32, (1ull << B), false);

2049 LatticeCell RC = Outputs.get(DefR.Reg);

2050 bool Eval = evaluateORri(R, A, Inputs, RC);

2051 if (!Eval)

2052 return false;

2053 Outputs.update(DefR.Reg, RC);

2054 break;

2055 }

2056

2057 case Hexagon::C2_mux:

2058 case Hexagon::C2_muxir:

2059 case Hexagon::C2_muxri:

2060 case Hexagon::C2_muxii:

2061 {

2062 bool Eval = evaluateHexCondMove(MI, Inputs, Outputs);

2063 if (!Eval)

2064 return false;

2065 break;

2066 }

2067

2068 case Hexagon::A2_sxtb:

2069 case Hexagon::A2_sxth:

2070 case Hexagon::A2_sxtw:

2071 case Hexagon::A2_zxtb:

2072 case Hexagon::A2_zxth:

2073 {

2074 bool Eval = evaluateHexExt(MI, Inputs, Outputs);

2075 if (!Eval)

2076 return false;

2077 break;

2078 }

2079

2080 case Hexagon::S2_ct0:

2081 case Hexagon::S2_ct0p:

2082 case Hexagon::S2_ct1:

2083 case Hexagon::S2_ct1p:

2084 {

2085 using namespace Hexagon;

2086

2087 bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p);

2090 LatticeCell T;

2091 bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs, T);

2092 if (!Eval)

2093 return false;

2094

2095

2096

2097 APInt C;

2098 LatticeCell RC = Outputs.get(DefR.Reg);

2099 for (unsigned i = 0; i < T.size(); ++i) {

2100 const Constant *CI = T.Values[i];

2101 if (constToInt(CI, C) && C.getBitWidth() > 32)

2102 CI = intToConst(C.trunc(32));

2103 RC.add(CI);

2104 }

2105 Outputs.update(DefR.Reg, RC);

2106 break;

2107 }

2108

2109 case Hexagon::S2_cl0:

2110 case Hexagon::S2_cl0p:

2111 case Hexagon::S2_cl1:

2112 case Hexagon::S2_cl1p:

2113 case Hexagon::S2_clb:

2114 case Hexagon::S2_clbp:

2115 {

2116 using namespace Hexagon;

2117

2118 bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p);

2119 bool OnlyOnes = (Opc == S2_cl1) || (Opc == S2_cl1p);

2122 LatticeCell T;

2123 bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs, T);

2124 if (!Eval)

2125 return false;

2126

2127

2128

2129 APInt C;

2130 LatticeCell RC = Outputs.get(DefR.Reg);

2131 for (unsigned i = 0; i < T.size(); ++i) {

2132 const Constant *CI = T.Values[i];

2133 if (constToInt(CI, C) && C.getBitWidth() > 32)

2134 CI = intToConst(C.trunc(32));

2135 RC.add(CI);

2136 }

2137 Outputs.update(DefR.Reg, RC);

2138 break;

2139 }

2140

2141 case Hexagon::S4_extract:

2142 case Hexagon::S4_extractp:

2143 case Hexagon::S2_extractu:

2144 case Hexagon::S2_extractup:

2145 {

2146 bool Signed = (Opc == Hexagon::S4_extract) ||

2147 (Opc == Hexagon::S4_extractp);

2150 unsigned Bits = MI.getOperand(2).getImm();

2151 unsigned Offset = MI.getOperand(3).getImm();

2152 LatticeCell RC = Outputs.get(DefR.Reg);

2154 APInt Zero(BW, 0, false);

2155 RC.add(intToConst(Zero));

2156 break;

2157 }

2158 if (Offset+Bits > BW) {

2159

2160

2161

2164 }

2165 bool Eval = evaluateEXTRACTr(R1, BW, Bits, Offset, Signed, Inputs, RC);

2166 if (!Eval)

2167 return false;

2168 Outputs.update(DefR.Reg, RC);

2169 break;

2170 }

2171

2172 case Hexagon::S2_vsplatrb:

2173 case Hexagon::S2_vsplatrh:

2174

2175

2176

2177

2178

2179

2180

2181

2182 {

2183 bool Eval = evaluateHexVector1(MI, Inputs, Outputs);

2184 if (!Eval)

2185 return false;

2186 break;

2187 }

2188

2189

2190

2191

2192

2193

2194 }

2195

2196 return true;

2197}

2198

2199bool HexagonConstEvaluator::evaluate(const RegSubRegPair &R,

2200 const LatticeCell &Input,

2201 LatticeCell &Result) {

2202 if (R.SubReg) {

2204 return true;

2205 }

2206 const TargetRegisterClass *RC = MRI->getRegClass(R.Reg);

2207 if (RC != &Hexagon::DoubleRegsRegClass)

2208 return false;

2209 if (R.SubReg != Hexagon::isub_lo && R.SubReg != Hexagon::isub_hi)

2210 return false;

2211

2212 assert(!Input.isTop());

2213 if (Input.isBottom())

2214 return false;

2215

2216 using P = ConstantProperties;

2217

2218 if (Input.isProperty()) {

2219 uint32_t Ps = Input.properties();

2220 if (Ps & (P::Zero|P::NaN)) {

2221 uint32_t Ns = (Ps & (P::Zero|P::NaN|P::SignProperties));

2223 return true;

2224 }

2225 if (R.SubReg == Hexagon::isub_hi) {

2226 uint32_t Ns = (Ps & P::SignProperties);

2228 return true;

2229 }

2230 return false;

2231 }

2232

2233

2234

2235 APInt A;

2236 for (unsigned i = 0; i < Input.size(); ++i) {

2237 const Constant *C = Input.Values[i];

2238 if (!constToInt(C, A))

2239 return false;

2240 if (A.isIntN(64))

2241 return false;

2242 uint64_t U = A.getZExtValue();

2243 if (R.SubReg == Hexagon::isub_hi)

2244 U >>= 32;

2245 U &= 0xFFFFFFFFULL;

2247 int32_t V32;

2248 memcpy(&V32, &U32, sizeof V32);

2249 IntegerType *Ty = Type::getInt32Ty(CX);

2250 const ConstantInt *C32 = ConstantInt::get(Ty, static_cast<int64_t>(V32));

2252 }

2253 return true;

2254}

2255

2256bool HexagonConstEvaluator::evaluate(const MachineInstr &BrI,

2257 const CellMap &Inputs, SetVector<const MachineBasicBlock*> &Targets,

2258 bool &FallsThru) {

2259

2260

2262 bool SimpleBranch = false;

2263 bool Negated = false;

2264 switch (Opc) {

2265 case Hexagon::J2_jumpf:

2266 case Hexagon::J2_jumpfnew:

2267 case Hexagon::J2_jumpfnewpt:

2268 Negated = true;

2269 [[fallthrough]];

2270 case Hexagon::J2_jumpt:

2271 case Hexagon::J2_jumptnew:

2272 case Hexagon::J2_jumptnewpt:

2273

2274

2275 SimpleBranch = true;

2276 break;

2277 case Hexagon::J2_jump:

2279 FallsThru = false;

2280 return true;

2281 default:

2283

2284

2286 return false;

2287 }

2288

2289 if (SimpleBranch) {

2290 const MachineOperand &MD = BrI.getOperand(0);

2292

2293

2294 if (PR.SubReg)

2296 assert(Inputs.has(PR.Reg));

2297 const LatticeCell &PredC = Inputs.get(PR.Reg);

2298 if (PredC.isBottom())

2300

2301 uint32_t Props = PredC.properties();

2302 bool CTrue = false, CFalse = false;

2303 if (Props & ConstantProperties::Zero)

2304 CFalse = true;

2305 else if (Props & ConstantProperties::NonZero)

2306 CTrue = true;

2307

2308 if (!CTrue && !CFalse)

2310

2312

2313 FallsThru = false;

2314 if ((!Negated && CTrue) || (Negated && CFalse))

2315 Targets.insert(BranchTarget);

2316 else if ((!Negated && CFalse) || (Negated && CTrue))

2317 FallsThru = true;

2318 else

2320 }

2321

2322 return true;

2323}

2324

2325bool HexagonConstEvaluator::rewrite(MachineInstr &MI, const CellMap &Inputs) {

2326 if (MI.isBranch())

2327 return rewriteHexBranch(MI, Inputs);

2328

2329 unsigned Opc = MI.getOpcode();

2330 switch (Opc) {

2331 default:

2332 break;

2333 case Hexagon::A2_tfrsi:

2334 case Hexagon::A2_tfrpi:

2335 case Hexagon::CONST32:

2336 case Hexagon::CONST64:

2337 case Hexagon::PS_true:

2338 case Hexagon::PS_false:

2339 return false;

2340 }

2341

2342 unsigned NumOp = MI.getNumOperands();

2343 if (NumOp == 0)

2344 return false;

2345

2347 Changed = rewriteHexConstDefs(MI, Inputs, AllDefs);

2348

2349

2350

2351 if (!AllDefs)

2352 Changed |= rewriteHexConstUses(MI, Inputs);

2353

2355}

2356

2357unsigned HexagonConstEvaluator::getRegBitWidth(unsigned Reg) const {

2358 const TargetRegisterClass *RC = MRI->getRegClass(Reg);

2359 if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))

2360 return 32;

2361 if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC))

2362 return 64;

2363 if (Hexagon::PredRegsRegClass.hasSubClassEq(RC))

2364 return 8;

2366 return 0;

2367}

2368

2369uint32_t HexagonConstEvaluator::getCmp(unsigned Opc) {

2370 switch (Opc) {

2371 case Hexagon::C2_cmpeq:

2372 case Hexagon::C2_cmpeqp:

2373 case Hexagon::A4_cmpbeq:

2374 case Hexagon::A4_cmpheq:

2375 case Hexagon::A4_cmpbeqi:

2376 case Hexagon::A4_cmpheqi:

2377 case Hexagon::C2_cmpeqi:

2378 case Hexagon::J4_cmpeqn1_t_jumpnv_nt:

2379 case Hexagon::J4_cmpeqn1_t_jumpnv_t:

2380 case Hexagon::J4_cmpeqi_t_jumpnv_nt:

2381 case Hexagon::J4_cmpeqi_t_jumpnv_t:

2382 case Hexagon::J4_cmpeq_t_jumpnv_nt:

2383 case Hexagon::J4_cmpeq_t_jumpnv_t:

2384 return Comparison::EQ;

2385

2386 case Hexagon::C4_cmpneq:

2387 case Hexagon::C4_cmpneqi:

2388 case Hexagon::J4_cmpeqn1_f_jumpnv_nt:

2389 case Hexagon::J4_cmpeqn1_f_jumpnv_t:

2390 case Hexagon::J4_cmpeqi_f_jumpnv_nt:

2391 case Hexagon::J4_cmpeqi_f_jumpnv_t:

2392 case Hexagon::J4_cmpeq_f_jumpnv_nt:

2393 case Hexagon::J4_cmpeq_f_jumpnv_t:

2394 return Comparison::NE;

2395

2396 case Hexagon::C2_cmpgt:

2397 case Hexagon::C2_cmpgtp:

2398 case Hexagon::A4_cmpbgt:

2399 case Hexagon::A4_cmphgt:

2400 case Hexagon::A4_cmpbgti:

2401 case Hexagon::A4_cmphgti:

2402 case Hexagon::C2_cmpgti:

2403 case Hexagon::J4_cmpgtn1_t_jumpnv_nt:

2404 case Hexagon::J4_cmpgtn1_t_jumpnv_t:

2405 case Hexagon::J4_cmpgti_t_jumpnv_nt:

2406 case Hexagon::J4_cmpgti_t_jumpnv_t:

2407 case Hexagon::J4_cmpgt_t_jumpnv_nt:

2408 case Hexagon::J4_cmpgt_t_jumpnv_t:

2409 return Comparison::GTs;

2410

2411 case Hexagon::C4_cmplte:

2412 case Hexagon::C4_cmpltei:

2413 case Hexagon::J4_cmpgtn1_f_jumpnv_nt:

2414 case Hexagon::J4_cmpgtn1_f_jumpnv_t:

2415 case Hexagon::J4_cmpgti_f_jumpnv_nt:

2416 case Hexagon::J4_cmpgti_f_jumpnv_t:

2417 case Hexagon::J4_cmpgt_f_jumpnv_nt:

2418 case Hexagon::J4_cmpgt_f_jumpnv_t:

2419 return Comparison::LEs;

2420

2421 case Hexagon::C2_cmpgtu:

2422 case Hexagon::C2_cmpgtup:

2423 case Hexagon::A4_cmpbgtu:

2424 case Hexagon::A4_cmpbgtui:

2425 case Hexagon::A4_cmphgtu:

2426 case Hexagon::A4_cmphgtui:

2427 case Hexagon::C2_cmpgtui:

2428 case Hexagon::J4_cmpgtui_t_jumpnv_nt:

2429 case Hexagon::J4_cmpgtui_t_jumpnv_t:

2430 case Hexagon::J4_cmpgtu_t_jumpnv_nt:

2431 case Hexagon::J4_cmpgtu_t_jumpnv_t:

2432 return Comparison::GTu;

2433

2434 case Hexagon::J4_cmpltu_f_jumpnv_nt:

2435 case Hexagon::J4_cmpltu_f_jumpnv_t:

2436 return Comparison::GEu;

2437

2438 case Hexagon::J4_cmpltu_t_jumpnv_nt:

2439 case Hexagon::J4_cmpltu_t_jumpnv_t:

2440 return Comparison::LTu;

2441

2442 case Hexagon::J4_cmplt_f_jumpnv_nt:

2443 case Hexagon::J4_cmplt_f_jumpnv_t:

2444 return Comparison::GEs;

2445

2446 case Hexagon::C4_cmplteu:

2447 case Hexagon::C4_cmplteui:

2448 case Hexagon::J4_cmpgtui_f_jumpnv_nt:

2449 case Hexagon::J4_cmpgtui_f_jumpnv_t:

2450 case Hexagon::J4_cmpgtu_f_jumpnv_nt:

2451 case Hexagon::J4_cmpgtu_f_jumpnv_t:

2452 return Comparison::LEu;

2453

2454 case Hexagon::J4_cmplt_t_jumpnv_nt:

2455 case Hexagon::J4_cmplt_t_jumpnv_t:

2456 return Comparison::LTs;

2457

2458 default:

2459 break;

2460 }

2461 return Comparison::Unk;

2462}

2463

2464APInt HexagonConstEvaluator::getCmpImm(unsigned Opc, unsigned OpX,

2465 const MachineOperand &MO) {

2466 bool Signed = false;

2467 switch (Opc) {

2468 case Hexagon::A4_cmpbgtui:

2469 case Hexagon::A4_cmphgtui:

2470 break;

2471 case Hexagon::A4_cmpheqi:

2472 case Hexagon::C4_cmpneqi:

2474 break;

2475 case Hexagon::A4_cmpbeqi:

2476 break;

2477 case Hexagon::C2_cmpgtui:

2478 case Hexagon::C4_cmplteui:

2479 break;

2480 case Hexagon::C2_cmpeqi:

2481 case Hexagon::C2_cmpgti:

2482 case Hexagon::C4_cmpltei:

2484 break;

2485 case Hexagon::J4_cmpeqi_f_jumpnv_nt:

2486 case Hexagon::J4_cmpeqi_f_jumpnv_t:

2487 case Hexagon::J4_cmpeqi_t_jumpnv_nt:

2488 case Hexagon::J4_cmpeqi_t_jumpnv_t:

2489 case Hexagon::J4_cmpgti_f_jumpnv_nt:

2490 case Hexagon::J4_cmpgti_f_jumpnv_t:

2491 case Hexagon::J4_cmpgti_t_jumpnv_nt:

2492 case Hexagon::J4_cmpgti_t_jumpnv_t:

2493 case Hexagon::J4_cmpgtui_f_jumpnv_nt:

2494 case Hexagon::J4_cmpgtui_f_jumpnv_t:

2495 case Hexagon::J4_cmpgtui_t_jumpnv_nt:

2496 case Hexagon::J4_cmpgtui_t_jumpnv_t:

2497 break;

2498 default:

2500 break;

2501 }

2502

2503 uint64_t Val = MO.getImm();

2504

2505 return APInt(32, Val, Signed, true);

2506}

2507

2508void HexagonConstEvaluator::replaceWithNop(MachineInstr &MI) {

2509 MI.setDesc(HII.get(Hexagon::A2_nop));

2510 while (MI.getNumOperands() > 0)

2511 MI.removeOperand(0);

2512}

2513

2514bool HexagonConstEvaluator::evaluateHexRSEQ32(RegSubRegPair RL,

2516 const CellMap &Inputs,

2517 LatticeCell &Result) {

2518 assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg));

2519 LatticeCell LSL, LSH;

2520 if (!getCell(RL, Inputs, LSL) || !getCell(RH, Inputs, LSH))

2521 return false;

2522 if (LSL.isProperty() || LSH.isProperty())

2523 return false;

2524

2525 unsigned LN = LSL.size(), HN = LSH.size();

2527 for (unsigned i = 0; i < LN; ++i) {

2528 bool Eval = constToInt(LSL.Values[i], LoVs[i]);

2529 if (!Eval)

2530 return false;

2532 }

2533 for (unsigned i = 0; i < HN; ++i) {

2534 bool Eval = constToInt(LSH.Values[i], HiVs[i]);

2535 if (!Eval)

2536 return false;

2538 }

2539

2540 for (unsigned i = 0; i < HiVs.size(); ++i) {

2541 APInt HV = HiVs[i].zext(64) << 32;

2542 for (unsigned j = 0; j < LoVs.size(); ++j) {

2543 APInt LV = LoVs[j].zext(64);

2544 const Constant *C = intToConst(HV | LV);

2546 if (Result.isBottom())

2547 return false;

2548 }

2549 }

2550 return Result.isBottom();

2551}

2552

2553bool HexagonConstEvaluator::evaluateHexCompare(const MachineInstr &MI,

2554 const CellMap &Inputs, CellMap &Outputs) {

2555 unsigned Opc = MI.getOpcode();

2556 bool Classic = false;

2557 switch (Opc) {

2558 case Hexagon::C2_cmpeq:

2559 case Hexagon::C2_cmpeqp:

2560 case Hexagon::C2_cmpgt:

2561 case Hexagon::C2_cmpgtp:

2562 case Hexagon::C2_cmpgtu:

2563 case Hexagon::C2_cmpgtup:

2564 case Hexagon::C2_cmpeqi:

2565 case Hexagon::C2_cmpgti:

2566 case Hexagon::C2_cmpgtui:

2567

2568 Classic = true;

2569 break;

2570 default:

2571

2572 return false;

2573 }

2574

2575 if (Classic) {

2576 const MachineOperand &Src1 = MI.getOperand(1);

2577 const MachineOperand &Src2 = MI.getOperand(2);

2578

2580 unsigned Opc = MI.getOpcode();

2581 bool Computed = evaluateHexCompare2(Opc, Src1, Src2, Inputs, Result);

2582 if (Computed) {

2583

2584

2586 LatticeCell L = Outputs.get(DefR.Reg);

2587 uint32_t P = Result ? ConstantProperties::NonZero

2588 : ConstantProperties::Zero;

2589 L.add(P);

2590 Outputs.update(DefR.Reg, L);

2591 return true;

2592 }

2593 }

2594

2595 return false;

2596}

2597

2598bool HexagonConstEvaluator::evaluateHexCompare2(unsigned Opc,

2599 const MachineOperand &Src1, const MachineOperand &Src2,

2600 const CellMap &Inputs, bool &Result) {

2602 bool Reg1 = Src1.isReg(), Reg2 = Src2.isReg();

2603 bool Imm1 = Src1.isImm(), Imm2 = Src2.isImm();

2604 if (Reg1) {

2606 if (Reg2) {

2608 return evaluateCMPrr(Cmp, R1, R2, Inputs, Result);

2609 } else if (Imm2) {

2610 APInt A2 = getCmpImm(Opc, 2, Src2);

2611 return evaluateCMPri(Cmp, R1, A2, Inputs, Result);

2612 }

2613 } else if (Imm1) {

2614 APInt A1 = getCmpImm(Opc, 1, Src1);

2615 if (Reg2) {

2617 uint32_t NegCmp = Comparison::negate(Cmp);

2618 return evaluateCMPri(NegCmp, R2, A1, Inputs, Result);

2619 } else if (Imm2) {

2620 APInt A2 = getCmpImm(Opc, 2, Src2);

2621 return evaluateCMPii(Cmp, A1, A2, Result);

2622 }

2623 }

2624

2625 return false;

2626}

2627

2628bool HexagonConstEvaluator::evaluateHexLogical(const MachineInstr &MI,

2629 const CellMap &Inputs, CellMap &Outputs) {

2630 unsigned Opc = MI.getOpcode();

2631 if (MI.getNumOperands() != 3)

2632 return false;

2633 const MachineOperand &Src1 = MI.getOperand(1);

2634 const MachineOperand &Src2 = MI.getOperand(2);

2636 bool Eval = false;

2637 LatticeCell RC;

2638 switch (Opc) {

2639 default:

2640 return false;

2641 case Hexagon::A2_and:

2642 case Hexagon::A2_andp:

2643 Eval =

2645 break;

2646 case Hexagon::A2_andir: {

2647 if (!Src2.isImm())

2648 return false;

2649 APInt A(32, Src2.getImm(), true);

2650 Eval = evaluateANDri(R1, A, Inputs, RC);

2651 break;

2652 }

2653 case Hexagon::A2_or:

2654 case Hexagon::A2_orp:

2655 Eval =

2657 break;

2658 case Hexagon::A2_orir: {

2659 if (!Src2.isImm())

2660 return false;

2661 APInt A(32, Src2.getImm(), true);

2662 Eval = evaluateORri(R1, A, Inputs, RC);

2663 break;

2664 }

2665 case Hexagon::A2_xor:

2666 case Hexagon::A2_xorp:

2667 Eval =

2669 break;

2670 }

2671 if (Eval) {

2673 Outputs.update(DefR.Reg, RC);

2674 }

2675 return Eval;

2676}

2677

2678bool HexagonConstEvaluator::evaluateHexCondMove(const MachineInstr &MI,

2679 const CellMap &Inputs, CellMap &Outputs) {

2680

2682 assert(Inputs.has(CR.Reg));

2683 LatticeCell LS;

2684 if (!getCell(CR, Inputs, LS))

2685 return false;

2686 uint32_t Ps = LS.properties();

2687 unsigned TakeOp;

2688 if (Ps & ConstantProperties::Zero)

2689 TakeOp = 3;

2690 else if (Ps & ConstantProperties::NonZero)

2691 TakeOp = 2;

2692 else

2693 return false;

2694

2695 const MachineOperand &ValOp = MI.getOperand(TakeOp);

2697 LatticeCell RC = Outputs.get(DefR.Reg);

2698

2699 if (ValOp.isImm()) {

2700 int64_t V = ValOp.getImm();

2702 APInt A(W, V, true);

2704 RC.add(C);

2705 Outputs.update(DefR.Reg, RC);

2706 return true;

2707 }

2708 if (ValOp.isReg()) {

2710 const LatticeCell &LR = Inputs.get(R.Reg);

2711 LatticeCell LSR;

2713 return false;

2714 RC.meet(LSR);

2715 Outputs.update(DefR.Reg, RC);

2716 return true;

2717 }

2718 return false;

2719}

2720

2721bool HexagonConstEvaluator::evaluateHexExt(const MachineInstr &MI,

2722 const CellMap &Inputs, CellMap &Outputs) {

2723

2726

2727 unsigned Opc = MI.getOpcode();

2728 unsigned Bits;

2729 switch (Opc) {

2730 case Hexagon::A2_sxtb:

2731 case Hexagon::A2_zxtb:

2733 break;

2734 case Hexagon::A2_sxth:

2735 case Hexagon::A2_zxth:

2737 break;

2738 case Hexagon::A2_sxtw:

2740 break;

2741 default:

2743 }

2744

2745 bool Signed = false;

2746 switch (Opc) {

2747 case Hexagon::A2_sxtb:

2748 case Hexagon::A2_sxth:

2749 case Hexagon::A2_sxtw:

2751 break;

2752 }

2753

2756 LatticeCell RC = Outputs.get(DefR.Reg);

2757 bool Eval = Signed ? evaluateSEXTr(R1, BW, Bits, Inputs, RC)

2758 : evaluateZEXTr(R1, BW, Bits, Inputs, RC);

2759 if (!Eval)

2760 return false;

2761 Outputs.update(DefR.Reg, RC);

2762 return true;

2763}

2764

2765bool HexagonConstEvaluator::evaluateHexVector1(const MachineInstr &MI,

2766 const CellMap &Inputs, CellMap &Outputs) {

2767

2771 LatticeCell RC = Outputs.get(DefR.Reg);

2772 bool Eval;

2773

2774 unsigned Opc = MI.getOpcode();

2775 switch (Opc) {

2776 case Hexagon::S2_vsplatrb:

2777

2778 Eval = evaluateSplatr(R1, 8, 4, Inputs, RC);

2779 break;

2780 case Hexagon::S2_vsplatrh:

2781

2782 Eval = evaluateSplatr(R1, 16, 4, Inputs, RC);

2783 break;

2784 default:

2785 return false;

2786 }

2787

2788 if (!Eval)

2789 return false;

2790 Outputs.update(DefR.Reg, RC);

2791 return true;

2792}

2793

2794bool HexagonConstEvaluator::rewriteHexConstDefs(MachineInstr &MI,

2795 const CellMap &Inputs, bool &AllDefs) {

2796 AllDefs = false;

2797

2798

2799

2800#ifndef NDEBUG

2802 if (Debugging) {

2803 bool Const = true, HasUse = false;

2804 for (const MachineOperand &MO : MI.operands()) {

2806 continue;

2808 if (R.Reg.isVirtual())

2809 continue;

2810 HasUse = true;

2811

2812 if (MI.isPHI() && !Inputs.has(R.Reg)) {

2814 << " in MI: " << MI;

2815 continue;

2816 }

2817 const LatticeCell &L = Inputs.get(R.Reg);

2818 Const &= L.isSingle();

2819 if (!Const)

2820 break;

2821 }

2822 if (HasUse && Const) {

2823 if (MI.isCopy()) {

2824 dbgs() << "CONST: " << MI;

2825 for (const MachineOperand &MO : MI.operands()) {

2827 continue;

2829 dbgs() << printReg(R, &TRI) << ": " << Inputs.get(R) << "\n";

2830 }

2831 }

2832 }

2833 }

2834#endif

2835

2836

2837

2838 if (MI.isCopy())

2839 return false;

2840

2841 MachineFunction *MF = MI.getParent()->getParent();

2842 auto &HST = MF->getSubtarget();

2843

2844

2845 SmallVector<unsigned,2> DefRegs;

2846 for (const MachineOperand &MO : MI.operands()) {

2848 continue;

2850 if (R.isVirtual())

2851 continue;

2853 assert(Inputs.has(R));

2854 DefRegs.push_back(R);

2855 }

2856

2857 MachineBasicBlock &B = *MI.getParent();

2859 unsigned ChangedNum = 0;

2860#ifndef NDEBUG

2862#endif

2863

2864

2865

2866

2867 for (unsigned R : DefRegs) {

2868 const LatticeCell &L = Inputs.get(R);

2869 if (L.isBottom())

2870 continue;

2871 const TargetRegisterClass *RC = MRI->getRegClass(R);

2873

2874 if (L.isSingle()) {

2875

2876

2877 using P = ConstantProperties;

2878

2879 uint64_t Ps = L.properties();

2880 if (!(Ps & (P::Zero|P::NonZero)))

2881 continue;

2882 const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;

2883 if (RC != PredRC)

2884 continue;

2885 const MCInstrDesc *NewD = (Ps & P::Zero) ?

2886 &HII.get(Hexagon::PS_false) :

2887 &HII.get(Hexagon::PS_true);

2888 Register NewR = MRI->createVirtualRegister(PredRC);

2889 const MachineInstrBuilder &MIB = BuildMI(B, At, DL, *NewD, NewR);

2890 (void)MIB;

2891#ifndef NDEBUG

2893#endif

2894 replaceAllRegUsesWith(R, NewR);

2895 } else {

2896

2897 APInt A;

2898 if (!constToInt(L.Value, A) || A.isSignedIntN(64))

2899 continue;

2900 const TargetRegisterClass *NewRC;

2901 const MCInstrDesc *NewD;

2902

2904 int64_t V = A.getSExtValue();

2905 assert(W == 32 || W == 64);

2906 if (W == 32)

2907 NewRC = &Hexagon::IntRegsRegClass;

2908 else

2909 NewRC = &Hexagon::DoubleRegsRegClass;

2910 Register NewR = MRI->createVirtualRegister(NewRC);

2911 const MachineInstr *NewMI;

2912

2913 if (W == 32) {

2914 NewD = &HII.get(Hexagon::A2_tfrsi);

2915 NewMI = BuildMI(B, At, DL, *NewD, NewR)

2917 } else {

2918 if (A.isSignedIntN(8)) {

2919 NewD = &HII.get(Hexagon::A2_tfrpi);

2920 NewMI = BuildMI(B, At, DL, *NewD, NewR)

2922 } else {

2923 int32_t Hi = V >> 32;

2924 int32_t Lo = V & 0xFFFFFFFFLL;

2926 NewD = &HII.get(Hexagon::A2_combineii);

2927 NewMI = BuildMI(B, At, DL, *NewD, NewR)

2931

2932 NewD = &HII.get(Hexagon::CONST64);

2933 NewMI = BuildMI(B, At, DL, *NewD, NewR)

2935 } else

2936 return false;

2937 }

2938 }

2939 (void)NewMI;

2940#ifndef NDEBUG

2942#endif

2943 replaceAllRegUsesWith(R, NewR);

2944 }

2945 ChangedNum++;

2946 }

2947

2949 if (!NewInstrs.empty()) {

2950 MachineFunction &MF = *MI.getParent()->getParent();

2951 dbgs() << "In function: " << MF.getName() << "\n";

2952 dbgs() << "Rewrite: for " << MI << " created " << *NewInstrs[0];

2953 for (unsigned i = 1; i < NewInstrs.size(); ++i)

2954 dbgs() << " " << *NewInstrs[i];

2955 }

2956 });

2957

2958 AllDefs = (ChangedNum == DefRegs.size());

2959 return ChangedNum > 0;

2960}

2961

2962bool HexagonConstEvaluator::rewriteHexConstUses(MachineInstr &MI,

2963 const CellMap &Inputs) {

2965 unsigned Opc = MI.getOpcode();

2966 MachineBasicBlock &B = *MI.getParent();

2969 MachineInstr *NewMI = nullptr;

2970

2971 switch (Opc) {

2972 case Hexagon::M2_maci:

2973

2974

2975

2976 {

2978 assert(!DefR.SubReg);

2981 assert(Inputs.has(R2.Reg) && Inputs.has(R3.Reg));

2982 LatticeCell LS2, LS3;

2983

2984

2985 bool HasC2 = getCell(R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3);

2986 if (!HasC2 && !HasC3)

2987 return false;

2988 bool Zero = ((HasC2 && (LS2.properties() & ConstantProperties::Zero)) ||

2989 (HasC3 && (LS3.properties() & ConstantProperties::Zero)));

2990

2991 if (Zero) {

2992

2993 MachineOperand &Acc = MI.getOperand(1);

2995 unsigned NewR = R1.Reg;

2997

2998 const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);

2999 NewR = MRI->createVirtualRegister(RC);

3000 NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)

3002 }

3003 replaceAllRegUsesWith(DefR.Reg, NewR);

3004 MRI->clearKillFlags(NewR);

3006 break;

3007 }

3008

3009 bool Swap = false;

3010 if (!LS3.isSingle()) {

3011 if (!LS2.isSingle())

3012 return false;

3013 Swap = true;

3014 }

3015 const LatticeCell &LI = Swap ? LS2 : LS3;

3016 const MachineOperand &OpR2 = Swap ? MI.getOperand(3)

3017 : MI.getOperand(2);

3018

3019 APInt A;

3020 if (!constToInt(LI.Value, A) || A.isSignedIntN(8))

3021 return false;

3022 int64_t V = A.getSExtValue();

3023 const MCInstrDesc &D = (V >= 0) ? HII.get(Hexagon::M2_macsip)

3024 : HII.get(Hexagon::M2_macsin);

3025 if (V < 0)

3026 V = -V;

3027 const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);

3028 Register NewR = MRI->createVirtualRegister(RC);

3029 const MachineOperand &Src1 = MI.getOperand(1);

3034 replaceAllRegUsesWith(DefR.Reg, NewR);

3036 break;

3037 }

3038

3039 case Hexagon::A2_and:

3040 {

3043 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));

3044 LatticeCell LS1, LS2;

3045 unsigned CopyOf = 0;

3046

3047 if (getCell(R1, Inputs, LS1) && LS1.isSingle()) {

3048 APInt M1;

3049 if (constToInt(LS1.Value, M1) && !~M1)

3050 CopyOf = 2;

3051 }

3052 else if (getCell(R2, Inputs, LS2) && LS2.isSingle()) {

3053 APInt M1;

3054 if (constToInt(LS2.Value, M1) && !~M1)

3055 CopyOf = 1;

3056 }

3057 if (!CopyOf)

3058 return false;

3059 MachineOperand &SO = MI.getOperand(CopyOf);

3062 unsigned NewR = SR.Reg;

3063 if (SR.SubReg) {

3064 const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);

3065 NewR = MRI->createVirtualRegister(RC);

3066 NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)

3068 }

3069 replaceAllRegUsesWith(DefR.Reg, NewR);

3070 MRI->clearKillFlags(NewR);

3072 }

3073 break;

3074

3075 case Hexagon::A2_or:

3076 {

3079 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));

3080 LatticeCell LS1, LS2;

3081 unsigned CopyOf = 0;

3082

3083 using P = ConstantProperties;

3084

3085 if (getCell(R1, Inputs, LS1) && (LS1.properties() & P::Zero))

3086 CopyOf = 2;

3087 else if (getCell(R2, Inputs, LS2) && (LS2.properties() & P::Zero))

3088 CopyOf = 1;

3089 if (!CopyOf)

3090 return false;

3091 MachineOperand &SO = MI.getOperand(CopyOf);

3094 unsigned NewR = SR.Reg;

3095 if (SR.SubReg) {

3096 const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);

3097 NewR = MRI->createVirtualRegister(RC);

3098 NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)

3100 }

3101 replaceAllRegUsesWith(DefR.Reg, NewR);

3102 MRI->clearKillFlags(NewR);

3104 }

3105 break;

3106 }

3107

3108 if (NewMI) {

3109

3110 for (MachineOperand &MO : NewMI->operands())

3113 }

3114

3116 if (NewMI) {

3117 dbgs() << "Rewrite: for " << MI;

3118 if (NewMI != &MI)

3119 dbgs() << " created " << *NewMI;

3120 else

3121 dbgs() << " modified the instruction itself and created:" << *NewMI;

3122 }

3123 });

3124

3126}

3127

3128void HexagonConstEvaluator::replaceAllRegUsesWith(Register FromReg,

3132 for (MachineOperand &O :

3134 O.setReg(ToReg);

3135}

3136

3137bool HexagonConstEvaluator::rewriteHexBranch(MachineInstr &BrI,

3138 const CellMap &Inputs) {

3139 MachineBasicBlock &B = *BrI.getParent();

3141 if (!NumOp)

3142 return false;

3143

3144 bool FallsThru;

3145 SetVector<const MachineBasicBlock*> Targets;

3146 bool Eval = evaluate(BrI, Inputs, Targets, FallsThru);

3147 unsigned NumTargets = Targets.size();

3148 if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru))

3149 return false;

3150 if (BrI.getOpcode() == Hexagon::J2_jump)

3151 return false;

3152

3154 bool Rewritten = false;

3155 if (NumTargets > 0) {

3156 assert(!FallsThru && "This should have been checked before");

3157

3158 MachineBasicBlock *TargetB = const_cast<MachineBasicBlock*>(Targets[0]);

3159 bool Moot = B.isLayoutSuccessor(TargetB);

3160 if (!Moot) {

3161

3162

3163

3164

3165 const MCInstrDesc &JD = HII.get(Hexagon::J2_jump);

3171

3172

3173 for (auto &Op : NI->operands())

3175 NI->eraseFromParent();

3176 Rewritten = true;

3177 }

3178 }

3179

3180

3181

3182

3183 if (!Rewritten)

3184 replaceWithNop(BrI);

3185 return true;

3186}

3187

3189 return new HexagonConstPropagation();

3190}

unsigned const MachineRegisterInfo * MRI

static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm)

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

This file declares a class to represent arbitrary precision floating point values and provide a varie...

This file implements a class to represent arbitrary precision integral constant values and operations...

ReachingDefInfo InstSet & ToRemove

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

This file contains the declarations for the subclasses of Constant, which represent the different fla...

TargetInstrInfo::RegSubRegPair RegSubRegPair

Register const TargetRegisterInfo * TRI

Promote Memory to Register

PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.

std::pair< BasicBlock *, BasicBlock * > Edge

This file implements a set that has insertion order iteration characteristics.

This file defines the SmallVector class.

static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, ISD::CondCode Cond, const SDLoc &DL, SDValue Chain=SDValue(), bool IsSignaling=false)

static unsigned getBitWidth(Type *Ty, const DataLayout &DL)

Returns the bitwidth of the given scalar or pointer type.

Class for arbitrary precision integers.

LLVM_ABI APInt zext(unsigned width) const

Zero extend to a new width.

uint64_t getZExtValue() const

Get zero extended value.

LLVM_ABI APInt zextOrTrunc(unsigned width) const

Zero extend or truncate to width.

LLVM_ABI APInt trunc(unsigned width) const

Truncate to new width.

unsigned getBitWidth() const

Return the number of bits in the APInt.

bool ult(const APInt &RHS) const

Unsigned less than comparison.

bool isNegative() const

Determine sign of this APInt.

unsigned countr_zero() const

Count the number of trailing zero bits.

unsigned countl_zero() const

The APInt version of std::countl_zero.

unsigned countl_one() const

Count the number of leading one bits.

APInt ashr(unsigned ShiftAmt) const

Arithmetic right-shift function.

LLVM_ABI APInt sext(unsigned width) const

Sign extend to a new width.

APInt shl(unsigned shiftAmt) const

Left-shift function.

static bool isSameValue(const APInt &I1, const APInt &I2)

Determine if two APInts have the same value, after zero-extending one of them (if needed!...

static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)

Constructs an APInt value that has the bottom loBitsSet bits set.

bool slt(const APInt &RHS) const

Signed less than comparison.

int64_t getSExtValue() const

Get sign extended value.

APInt lshr(unsigned shiftAmt) const

Logical right-shift function.

unsigned countr_one() const

Count the number of trailing one bits.

const APFloat & getValueAPF() const

bool isNegative() const

Return true if the sign bit is set.

bool isNaN() const

Return true if the value is a NaN.

bool isZero() const

Return true if the value is positive or negative zero.

This is the shared class of boolean and integer constants.

bool isZero() const

This is just a convenience method to make client code smaller for a common code.

const APInt & getValue() const

Return the constant as an APInt value reference.

This is an important base class in LLVM.

FunctionPass class - This class is used to implement most global optimizations.

bool hasOptSize() const

Optimize this function for size (-Os) or minimum size (-Oz).

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

This is an important class for using LLVM in a threaded context.

MachineInstrBundleIterator< const MachineInstr > const_iterator

iterator_range< iterator > phis()

Returns a range that iterates over the phis in the basic block.

int getNumber() const

MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...

LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)

Remove successor from the successors list of this MachineBasicBlock.

iterator_range< succ_iterator > successors()

MachineInstrBundleIterator< MachineInstr > iterator

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

MachineBasicBlock * getBlockNumbered(unsigned N) const

getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...

Function & getFunction()

Return the LLVM function that this machine code represents.

void print(raw_ostream &OS, const SlotIndexes *=nullptr) const

print - Print out the MachineFunction in a format suitable for debugging to the specified stream.

BasicBlockListType::const_iterator const_iterator

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MachineBasicBlock * getParent() const

unsigned getNumOperands() const

Retuns the total number of operands.

LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)

Add the specified operand to the instruction.

LLVM_ABI void setDesc(const MCInstrDesc &TID)

Replace the instruction descriptor (thus opcode) of the current instruction with a new one.

bool isUnconditionalBranch(QueryType Type=AnyInBundle) const

Return true if this is a branch which always transfers control flow to some other block.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

LLVM_ABI void removeOperand(unsigned OpNo)

Erase an operand from an instruction, leaving it with one fewer operand than it started with.

const MachineOperand & getOperand(unsigned i) const

unsigned getSubReg() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

MachineBasicBlock * getMBB() const

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

void setIsKill(bool Val=true)

Register getReg() const

getReg - Returns the register number.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

Wrapper class representing virtual and physical registers.

constexpr bool isVirtual() const

Return true if the specified register number is in the virtual register namespace.

A vector that has set insertion semantics.

bool remove(const value_type &X)

Remove an item from the set vector.

size_type size() const

Determine the number of elements in the SetVector.

void insert_range(Range &&R)

size_type count(const_arg_type key) const

Count the number of elements of a given key in the SetVector.

void clear()

Completely clear the SetVector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

void push_back(const T &Elt)

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

LLVM Value Representation.

self_iterator getIterator()

This class implements an extremely fast bulk output stream that can only output to a stream.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned getRegBitWidth(const TargetRegisterClass &RC)

Get the size in bits of a register from the register class RC.

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

@ TB

TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...

@ Undetermined

It is up to the client to interpret diagnostics as error, warning, info or hint.

This is an optimization pass for GlobalISel generic memory operations.

TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)

Create RegSubRegPair from a register MachineOperand.

void fill(R &&Range, T &&Value)

Provide wrappers to std::fill which take ranges instead of having to pass begin/end explicitly.

Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

LLVM_ABI bool isCurrentDebugType(const char *Type, int Level=0)

isCurrentDebugType - Return true if the specified string is the debug type specified on the command l...

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

iterator_range< po_iterator< T > > post_order(const T &G)

FunctionPass * createHexagonConstPropagationPass()

Definition HexagonConstPropagation.cpp:3188

unsigned M1(unsigned Val)

LLVM_ABI bool DebugFlag

This boolean is set to true if the '-debug' command line option is specified.

auto reverse(ContainerTy &&C)

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

FunctionAddr VTableAddr Count

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

constexpr uint32_t Lo_32(uint64_t Value)

Return the low 32 bits of a 64 bit value.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

unsigned getRegState(const MachineOperand &RegOp)

Get all register state flags from machine operand RegOp.

FunctionAddr VTableAddr Next

DWARFExpression::Operation Op

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)

Prints virtual and physical registers with or without a TRI instance.

LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)

Prints a machine basic block reference.

static NodeRef getEntryNode(MachineFunction *F)

A pair composed of a register and a sub-register index.