LLVM: lib/CodeGen/SelectionDAG/StatepointLowering.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

47#include

48#include

49#include

50#include

51#include

52#include

53

54using namespace llvm;

55

56#define DEBUG_TYPE "statepoint-lowering"

57

59 "Number of stack slots allocated for statepoints");

60STATISTIC(NumOfStatepoints, "Number of statepoint nodes encountered");

62 "Maximum number of stack slots required for a singe statepoint");

63

66 cl::desc("Allow using registers for non pointer deopt args"));

67

69 "use-registers-for-gc-values-in-landing-pad", cl::Hidden, cl::init(false),

70 cl::desc("Allow using registers for gc pointer in landing pad"));

71

74 cl::desc("Max number of VRegs allowed to pass GC pointer meta args in"));

75

77

80 SDLoc L = Builder.getCurSDLoc();

81 Ops.push_back(Builder.DAG.getTargetConstant(StackMaps::ConstantOp, L,

82 MVT::i64));

83 Ops.push_back(Builder.DAG.getTargetConstant(Value, L, MVT::i64));

84}

85

87

88 assert(PendingGCRelocateCalls.empty() &&

89 "Trying to visit statepoint before finished processing previous one");

90 Locations.clear();

91 NextSlotToAllocate = 0;

92

93

94

95 AllocatedStackSlots.clear();

96 AllocatedStackSlots.resize(Builder.FuncInfo.StatepointStackSlots.size());

97}

98

100 Locations.clear();

101 AllocatedStackSlots.clear();

102 assert(PendingGCRelocateCalls.empty() &&

103 "cleared before statepoint sequence completed");

104}

105

109 NumSlotsAllocatedForStatepoints++;

110 MachineFrameInfo &MFI = Builder.DAG.getMachineFunction().getFrameInfo();

111

112 unsigned SpillSize = ValueType.getStoreSize();

113 assert((SpillSize * 8) ==

114 (-8u & (7 + ValueType.getSizeInBits())) &&

115 "Size not in bytes?");

116

117

118

119

120

121 const size_t NumSlots = AllocatedStackSlots.size();

122 assert(NextSlotToAllocate <= NumSlots && "Broken invariant");

123

124 assert(AllocatedStackSlots.size() ==

125 Builder.FuncInfo.StatepointStackSlots.size() &&

126 "Broken invariant");

127

128 for (; NextSlotToAllocate < NumSlots; NextSlotToAllocate++) {

129 if (!AllocatedStackSlots.test(NextSlotToAllocate)) {

130 const int FI = Builder.FuncInfo.StatepointStackSlots[NextSlotToAllocate];

132 AllocatedStackSlots.set(NextSlotToAllocate);

133

134 return Builder.DAG.getFrameIndex(FI, ValueType);

135 }

136 }

137 }

138

139

140

141 SDValue SpillSlot = Builder.DAG.CreateStackTemporary(ValueType);

144

145 Builder.FuncInfo.StatepointStackSlots.push_back(FI);

146 AllocatedStackSlots.resize(AllocatedStackSlots.size()+1, true);

147 assert(AllocatedStackSlots.size() ==

148 Builder.FuncInfo.StatepointStackSlots.size() &&

149 "Broken invariant");

150

151 StatepointMaxSlotsRequired.updateMax(

152 Builder.FuncInfo.StatepointStackSlots.size());

153

154 return SpillSlot;

155}

156

157

158

159

162 int LookUpDepth) {

163

164 if (LookUpDepth <= 0)

165 return std::nullopt;

166

167

169 const Value *Statepoint = Relocate->getStatepoint();

171 "GetStatepoint must return one of two types");

173 return std::nullopt;

174

175 const auto &RelocationMap = Builder.FuncInfo.StatepointRelocationMaps

177

178 auto It = RelocationMap.find(Relocate);

179 if (It == RelocationMap.end())

180 return std::nullopt;

181

182 auto &Record = It->second;

184 return std::nullopt;

185

186 return Record.payload.FI;

187 }

188

189

192

193

194

195

197 std::optional MergedResult;

198

199 for (const auto &IncomingValue : Phi->incoming_values()) {

200 std::optional SpillSlot =

202 if (!SpillSlot)

203 return std::nullopt;

204

205 if (MergedResult && *MergedResult != *SpillSlot)

206 return std::nullopt;

207

208 MergedResult = SpillSlot;

209 }

210 return MergedResult;

211 }

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241 return std::nullopt;

242}

243

244

245

246

248

249

251 return true;

252

253

254

255

256

257 if (Incoming.getValueType().getSizeInBits() > 64)

258 return false;

259

261}

262

263

264

265

266

267

271

272

273

275 return;

276

277 SDValue OldLocation = Builder.StatepointLowering.getLocation(Incoming);

278 if (OldLocation.getNode())

279

280 return;

281

282 const int LookUpDepth = 6;

283 std::optional Index =

285 if (!Index)

286 return;

287

288 const auto &StatepointSlots = Builder.FuncInfo.StatepointStackSlots;

289

290 auto SlotIt = find(StatepointSlots, *Index);

291 assert(SlotIt != StatepointSlots.end() &&

292 "Value spilled to the unknown stack slot");

293

294

295 const int Offset = std::distance(StatepointSlots.begin(), SlotIt);

296 if (Builder.StatepointLowering.isStackSlotAllocated(Offset)) {

297

298

299

300

301

302

303 return;

304 }

305

306 Builder.StatepointLowering.reserveStackSlot(Offset);

307

308

309

311 Builder.DAG.getTargetFrameIndex(*Index, Builder.getFrameIndexTy());

312 Builder.StatepointLowering.setLocation(Incoming, Loc);

313}

314

315

316

317

321 SDValue ReturnValue, CallEndVal;

322 std::tie(ReturnValue, CallEndVal) =

323 Builder.lowerInvokable(SI.CLI, SI.EHPadBB);

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342 if (CallEnd->getOpcode() == ISD::EH_LABEL)

344

345 bool HasDef = SI.CLI.RetTy->isVoidTy();

346 if (HasDef) {

347 if (CallEnd->getOpcode() == ISD::LOAD)

349 else

352 }

353

354 assert(CallEnd->getOpcode() == ISD::CALLSEQ_END && "expected!");

355 return std::make_pair(ReturnValue, CallEnd->getOperand(0).getNode());

356}

357

365 MFI.getObjectSize(FI.getIndex()),

366 MFI.getObjectAlign(FI.getIndex()));

367}

368

369

370

371

372

373

374

375static std::tuple<SDValue, SDValue, MachineMemOperand*>

380

381

382 if (Loc.getNode()) {

383 Loc = Builder.StatepointLowering.allocateStackSlot(Incoming.getValueType(),

384 Builder);

386

387 Loc = Builder.DAG.getTargetFrameIndex(Index, Builder.getFrameIndexTy());

388

389

390

391

392

393

394 MachineFrameInfo &MFI = Builder.DAG.getMachineFunction().getFrameInfo();

396 (-8 & (7 +

397 (int64_t)Incoming.getValueSizeInBits())) &&

398 "Bad spill: stack slot does not match!");

399

400

401

402

403 auto &MF = Builder.DAG.getMachineFunction();

405 auto *StoreMMO = MF.getMachineMemOperand(

408 Chain = Builder.DAG.getStore(Chain, Builder.getCurSDLoc(), Incoming, Loc,

409 StoreMMO);

410

412

413 Builder.StatepointLowering.setLocation(Incoming, Loc);

414 }

415

417 return std::make_tuple(Loc, Chain, MMO);

418}

419

420

421

422

423static void

428

431

432

433

434 assert(Incoming.getValueType() == Builder.getFrameIndexTy() &&

435 "Incoming value is a frame index!");

436 Ops.push_back(Builder.DAG.getTargetFrameIndex(FI->getIndex(),

437 Builder.getFrameIndexTy()));

438

439 auto &MF = Builder.DAG.getMachineFunction();

442 return;

443 }

444

445 assert(Incoming.getValueType().getSizeInBits() <= 64);

446

448

449

450

451

453 return;

454 }

455

456

457

458

459

462 return;

465 C->getValueAPF().bitcastToAPInt().getZExtValue());

466 return;

467 }

468

470 }

471

472

473

474 if (!RequireSpillSlot) {

475

476

477

478

479

480

481

483 } else {

484

485

486

487

488

489 SDValue Chain = Builder.getRoot();

491 Ops.push_back(std::get<0>(Res));

492 if (auto *MMO = std::get<2>(Res))

494 Chain = std::get<1>(Res);

495 Builder.DAG.setRoot(Chain);

496 }

497

498}

499

500

501

503 auto *Ty = V->getType();

504 if (!Ty->isPtrOrPtrVectorTy())

505 return false;

506 if (auto *GFI = Builder.GFI)

507 if (auto IsManaged = GFI->getStrategy().isGCManagedPointer(Ty))

508 return *IsManaged;

509 return true;

510}

511

512

513

514

515

516

517

518

519static void

526

527

528

529

530

531

532

533

534

535

536

537

538

539 const bool LiveInDeopt =

541

542

544

545

546

549 if (const auto *StInvoke =

552 for (const auto *Relocate : SI.GCRelocates)

553 if (Relocate->getOperand(0) == LPI) {

554 LPadPointers.insert(Builder.getValue(Relocate->getBasePtr()));

555 LPadPointers.insert(Builder.getValue(Relocate->getDerivedPtr()));

556 }

557 }

558

559 LLVM_DEBUG(dbgs() << "Deciding how to lower GC Pointers:\n");

560

561

563

565

566 unsigned CurNumVRegs = 0;

567

568 auto canPassGCPtrOnVReg = [&](SDValue SD) {

569 if (SD.getValueType().isVector())

570 return false;

571 if (LPadPointers.count(SD))

572 return false;

574 };

575

576 auto processGCPtr = [&](const Value *V) {

578 if (!LoweredGCPtrs.insert(PtrSD))

579 return;

580 GCPtrIndexMap[PtrSD] = LoweredGCPtrs.size() - 1;

581

582 assert(!LowerAsVReg.count(PtrSD) && "must not have been seen");

583 if (LowerAsVReg.size() == MaxVRegPtrs)

584 return;

586 "IR and SD types disagree");

587 if (!canPassGCPtrOnVReg(PtrSD)) {

589 return;

590 }

592 LowerAsVReg[PtrSD] = CurNumVRegs++;

593 };

594

595

596 for (const Value *V : SI.Ptrs)

597 processGCPtr(V);

598 for (const Value *V : SI.Bases)

599 processGCPtr(V);

600

601 LLVM_DEBUG(dbgs() << LowerAsVReg.size() << " pointers will go in vregs\n");

602

603 auto requireSpillSlot = [&](const Value *V) {

604 if (!Builder.DAG.getTargetLoweringInfo().isTypeLegal(

605 Builder.getValue(V).getValueType()))

606 return true;

608 return !LowerAsVReg.count(Builder.getValue(V));

610 };

611

612

613

614

615

616

617 for (const Value *V : SI.DeoptState) {

618 if (requireSpillSlot(V))

620 }

621

622 for (const Value *V : SI.Ptrs) {

624 if (!LowerAsVReg.count(SDV))

626 }

627

628 for (const Value *V : SI.Bases) {

630 if (!LowerAsVReg.count(SDV))

632 }

633

634

635

636

637 const int NumVMSArgs = SI.DeoptState.size();

639

640

641

643 for (const Value *V : SI.DeoptState) {

645

646

648 int FI = Builder.FuncInfo.getArgumentFrameIndex(Arg);

649 if (FI != INT_MAX)

650 Incoming = Builder.DAG.getFrameIndex(FI, Builder.getFrameIndexTy());

651 }

653 Incoming = Builder.getValue(V);

655 << " requireSpillSlot = " << requireSpillSlot(V) << "\n");

657 Builder);

658 }

659

660

662 for (SDValue SDV : LoweredGCPtrs)

664 Builder);

665

666

668

669

670

671

672

673

675 for (Value *V : SI.GCLives) {

678

679 assert(Incoming.getValueType() == Builder.getFrameIndexTy() &&

680 "Incoming value is a frame index!");

681 Allocas.push_back(Builder.DAG.getTargetFrameIndex(

682 FI->getIndex(), Builder.getFrameIndexTy()));

683

684 auto &MF = Builder.DAG.getMachineFunction();

687 }

688 }

690 Ops.append(Allocas.begin(), Allocas.end());

691

692

694 SDLoc L = Builder.getCurSDLoc();

695 for (unsigned i = 0; i < SI.Ptrs.size(); ++i) {

697 assert(GCPtrIndexMap.count(Base) && "base not found in index map");

698 Ops.push_back(

699 Builder.DAG.getTargetConstant(GCPtrIndexMap[Base], L, MVT::i64));

701 assert(GCPtrIndexMap.count(Derived) && "derived not found in index map");

702 Ops.push_back(

703 Builder.DAG.getTargetConstant(GCPtrIndexMap[Derived], L, MVT::i64));

704 }

705}

706

709

710

711

712

713 NumOfStatepoints++;

714

716 assert(SI.Bases.size() == SI.Ptrs.size() && "Pointer without base!");

718 "No gc specified, so cannot relocate pointers!");

719

721 << "Lowering statepoint " << *SI.StatepointInstr << "\n");

722#ifndef NDEBUG

723 for (const auto *Reloc : SI.GCRelocates)

724 if (Reloc->getParent() == SI.StatepointInstr->getParent())

726#endif

727

728

729

730

732

735

738 SI, *this);

739

740

741

743

744

748

749

750

751

752

754

756 bool CallHasIncomingGlue = CallNode->getGluedNode();

757 if (CallHasIncomingGlue) {

758

760 }

761

762

763

764

765

766

767

768

769 const bool IsGCTransition =

772 if (IsGCTransition) {

774

775

777

778

779 for (const Value *V : SI.GCTransitionArgs) {

781 if (V->getType()->isPointerTy())

783 }

784

785

786 if (CallHasIncomingGlue)

788

789 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);

790

791 SDValue GCTransitionStart =

792 DAG.getNode(ISD::GC_TRANSITION_START, getCurSDLoc(), NodeTys, TSOps);

793

794 Chain = GCTransitionStart.getValue(0);

795 Glue = GCTransitionStart.getValue(1);

796 }

797

798

799

800

802

803

805 Ops.push_back(

806 DAG.getTargetConstant(SI.NumPatchBytes, getCurSDLoc(), MVT::i32));

807

808

809

810 unsigned NumCallRegArgs =

811 CallNode->getNumOperands() - (CallHasIncomingGlue ? 4 : 3);

812 Ops.push_back(DAG.getTargetConstant(NumCallRegArgs, getCurSDLoc(), MVT::i32));

813

814

816 Ops.push_back(CallTarget);

817

818

819

821 if (CallHasIncomingGlue)

822 RegMaskIt = CallNode->op_end() - 2;

823 else

824 RegMaskIt = CallNode->op_end() - 1;

825 Ops.insert(Ops.end(), CallNode->op_begin() + 2, RegMaskIt);

826

827

829

830

833 "Unknown flag used");

835

836

838

839

840 Ops.push_back(*RegMaskIt);

841

842

843 Ops.push_back(Chain);

844

845

847 Ops.push_back(Glue);

848

849

850

852 for (auto SD : LoweredGCArgs) {

853 if (!LowerAsVReg.count(SD))

854 continue;

855 NodeTys.push_back(SD.getValueType());

856 }

857 LLVM_DEBUG(dbgs() << "Statepoint has " << NodeTys.size() << " results\n");

858 assert(NodeTys.size() == LowerAsVReg.size() && "Inconsistent GC Ptr lowering");

861

862 unsigned NumResults = NodeTys.size();

864 DAG.getMachineNode(TargetOpcode::STATEPOINT, getCurSDLoc(), NodeTys, Ops);

865 DAG.setNodeMemRefs(StatepointMCNode, MemRefs);

866

867

868

869

871 for (const auto *Relocate : SI.GCRelocates) {

872 Value *Derived = Relocate->getDerivedPtr();

874 auto It = LowerAsVReg.find(SD);

875 if (It == LowerAsVReg.end())

876 continue;

877

878 SDValue Relocated = SDValue(StatepointMCNode, It->second);

879

880

881

882 if (SI.StatepointInstr->getParent() == Relocate->getParent()) {

884 if (Res)

885 assert(Res == Relocated);

886 else

888 continue;

889 }

890

891

892 auto [VRegIt, Inserted] = VirtRegs.try_emplace(SD);

893 if (!Inserted)

894 continue;

895

896 auto *RetTy = Relocate->getType();

899 DAG.getDataLayout(), Reg, RetTy, std::nullopt);

902 PendingExports.push_back(Chain);

903

904 VRegIt->second = Reg;

905 }

906

907

908

909 const Instruction *StatepointInstr = SI.StatepointInstr;

910 auto &RelocationMap = FuncInfo.StatepointRelocationMaps[StatepointInstr];

915

916 bool IsLocal = (Relocate->getParent() == StatepointInstr->getParent());

917

919 if (LowerAsVReg.count(SDV)) {

920 if (IsLocal) {

921

923 } else {

925 auto It = VirtRegs.find(SDV);

927 Record.payload.Reg = It->second;

928 }

929 } else if (Loc.getNode()) {

932 } else {

934

935

936

937

940 }

941 RelocationMap[Relocate] = Record;

942 }

943

944

945

946 SDNode *SinkNode = StatepointMCNode;

947

948

949

950

951

952 if (IsGCTransition) {

954

955

957

958

959 for (const Value *V : SI.GCTransitionArgs) {

961 if (V->getType()->isPointerTy())

963 }

964

965

967

968 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);

969

970 SDValue GCTransitionStart =

971 DAG.getNode(ISD::GC_TRANSITION_END, getCurSDLoc(), NodeTys, TEOps);

972

973 SinkNode = GCTransitionStart.getNode();

974 }

975

976

977

978

979 unsigned NumSinkValues = SinkNode->getNumValues();

980 SDValue StatepointValues[2] = {SDValue(SinkNode, NumSinkValues - 2),

981 SDValue(SinkNode, NumSinkValues - 1)};

982 DAG.ReplaceAllUsesWith(CallNode, StatepointValues);

983

984 DAG.DeleteNode(CallNode);

985

986

987

989

990

991

992

993

994

995

996 return ReturnVal;

997}

998

999

1000

1001

1002static std::pair<const GCResultInst*, const GCResultInst*>

1004 std::pair<const GCResultInst *, const GCResultInst*> Res(nullptr, nullptr);

1005 for (const auto *U : S.users()) {

1007 if (!GRI)

1008 continue;

1009 if (GRI->getParent() == S.getParent())

1010 Res.first = GRI;

1011 else

1012 Res.second = GRI;

1013 }

1014 return Res;

1015}

1016

1017void

1019 const BasicBlock *EHPadBB ) {

1021 "anyregcc is not supported on statepoints!");

1022

1023#ifndef NDEBUG

1024

1025 assert(GFI->getStrategy().useStatepoints() &&

1026 "GCStrategy does not expect to encounter statepoints");

1027#endif

1028

1031

1032 if (I.getNumPatchBytes() > 0) {

1033

1034

1035

1036

1037

1038 ActualCallee = DAG.getUNDEF(Callee.getValueType());

1039 } else {

1040 ActualCallee = Callee;

1041 }

1042

1045 if (GCResultLocality.first)

1046 retAttrs = GCResultLocality.first->getAttributes().getRetAttrs();

1047

1050 I.getNumCallArgs(), ActualCallee,

1051 I.getActualReturnType(), retAttrs,

1052 false);

1053

1054

1055

1056

1057

1058

1059

1060

1061

1062

1063

1064

1065

1066

1068 for (const GCRelocateInst *Relocate : I.getGCRelocates()) {

1069 SI.GCRelocates.push_back(Relocate);

1070

1071 SDValue DerivedSD = getValue(Relocate->getDerivedPtr());

1072 if (Seen.insert(DerivedSD).second) {

1073 SI.Bases.push_back(Relocate->getBasePtr());

1074 SI.Ptrs.push_back(Relocate->getDerivedPtr());

1075 }

1076 }

1077

1078

1079

1080

1081

1082

1083

1084 for (Value *V : I.deopt_operands()) {

1086 continue;

1088 SI.Bases.push_back(V);

1089 SI.Ptrs.push_back(V);

1090 }

1091 }

1092

1094 SI.StatepointInstr = &I;

1095 SI.ID = I.getID();

1096

1099 I.gc_transition_args_end());

1100

1101 SI.StatepointFlags = I.getFlags();

1102 SI.NumPatchBytes = I.getNumPatchBytes();

1103 SI.EHPadBB = EHPadBB;

1104

1106

1107

1108 if (!GCResultLocality.first && !GCResultLocality.second) {

1109

1110

1112 return;

1113 }

1114

1115 if (GCResultLocality.first) {

1116

1117

1118

1120 }

1121

1122 if (!GCResultLocality.second)

1123 return;

1124

1125

1126

1127

1128

1129

1130

1131

1132 Type *RetTy = GCResultLocality.second->getType();

1135 DAG.getDataLayout(), Reg, RetTy,

1136 I.getCallingConv());

1138

1140 PendingExports.push_back(Chain);

1142}

1143

1146 bool VarArgDisallowed, bool ForceVoidReturnTy) {

1148 unsigned ArgBeginIndex = Call->arg_begin() - Call->op_begin();

1150 SI.CLI, Call, ArgBeginIndex, Call->arg_size(), Callee,

1152 Call->getAttributes().getRetAttrs(), false);

1153 if (!VarArgDisallowed)

1154 SI.CLI.IsVarArg = Call->getFunctionType()->isVarArg();

1155

1157

1159

1161 SI.ID = SD.StatepointID.value_or(DefaultID);

1162 SI.NumPatchBytes = SD.NumPatchBytes.value_or(0);

1163

1164 SI.DeoptState =

1165 ArrayRef(DeoptBundle.Inputs.begin(), DeoptBundle.Inputs.end());

1167 SI.EHPadBB = EHPadBB;

1168

1169

1170

1171 LLVM_DEBUG(dbgs() << "Lowering call with deopt bundle " << *Call << "\n");

1175 }

1176}

1177

1181 false,

1182 false);

1183}

1184

1185void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) {

1186

1187

1190 "GetStatepoint must return one of two types");

1192 return;

1193

1196 return;

1197 }

1198

1199

1200

1201

1202

1203

1206

1207 assert(CopyFromReg.getNode());

1209}

1210

1211void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {

1212 const Value *Statepoint = Relocate.getStatepoint();

1213#ifndef NDEBUG

1214

1215

1216

1217

1219 "GetStatepoint must return one of two types");

1221 return;

1222

1225#endif

1226

1227 const Value *DerivedPtr = Relocate.getDerivedPtr();

1228 auto &RelocationMap =

1230 auto SlotIt = RelocationMap.find(&Relocate);

1231 assert(SlotIt != RelocationMap.end() && "Relocating not lowered gc value");

1232 const RecordType &Record = SlotIt->second;

1233

1234

1238 "Nonlocal gc.relocate mapped via SDValue");

1242 return;

1243 }

1246 RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(),

1247 DAG.getDataLayout(), InReg, Relocate.getType(),

1248 std::nullopt);

1249

1250

1251

1254 Chain, nullptr, nullptr);

1255 setValue(&Relocate, Relocation);

1256 return;

1257 }

1258

1262

1263

1264

1265

1266

1267

1268

1269

1270 const SDValue Chain = DAG.getRoot();

1271

1272 auto &MF = DAG.getMachineFunction();

1273 auto &MFI = MF.getFrameInfo();

1276 MFI.getObjectSize(Index),

1277 MFI.getObjectAlign(Index));

1278

1279 auto LoadVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),

1281

1283 DAG.getLoad(LoadVT, getCurSDLoc(), Chain, SpillSlot, LoadMMO);

1285

1287 setValue(&Relocate, SpillLoad);

1288 return;

1289 }

1290

1293

1295

1296

1297 setValue(&Relocate, DAG.getConstant(0xFEFEFEFE, SDLoc(SD), MVT::i64));

1298 return;

1299 }

1300

1301

1302

1304}

1305

1307 const auto &TLI = DAG.getTargetLoweringInfo();

1308 SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::DEOPTIMIZE),

1309 TLI.getPointerTy(DAG.getDataLayout()));

1310

1311

1312

1313

1315 true,

1316 true);

1317}

1318

1320

1321

1322

1323 if (DAG.getTarget().Options.TrapUnreachable)

1324 DAG.setRoot(

1325 DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, DAG.getRoot()));

1326}

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

static const Function * getParent(const Value *V)

const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]

Promote Memory to Register

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

This file implements the SmallBitVector class.

This file defines the SmallSet class.

This file defines the SmallVector class.

static cl::opt< bool > UseRegistersForGCPointersInLandingPad("use-registers-for-gc-values-in-landing-pad", cl::Hidden, cl::init(false), cl::desc("Allow using registers for gc pointer in landing pad"))

static void lowerIncomingStatepointValue(SDValue Incoming, bool RequireSpillSlot, SmallVectorImpl< SDValue > &Ops, SmallVectorImpl< MachineMemOperand * > &MemRefs, SelectionDAGBuilder &Builder)

Lower a single value incoming to a statepoint node.

Definition StatepointLowering.cpp:424

static std::optional< int > findPreviousSpillSlot(const Value *Val, SelectionDAGBuilder &Builder, int LookUpDepth)

Utility function for reservePreviousStackSlotForValue.

Definition StatepointLowering.cpp:160

static void pushStackMapConstant(SmallVectorImpl< SDValue > &Ops, SelectionDAGBuilder &Builder, uint64_t Value)

Definition StatepointLowering.cpp:78

static bool isGCValue(const Value *V, SelectionDAGBuilder &Builder)

Return true if value V represents the GC value.

Definition StatepointLowering.cpp:502

static bool willLowerDirectly(SDValue Incoming)

Return true if-and-only-if the given SDValue can be lowered as either a constant argument or a stack ...

Definition StatepointLowering.cpp:247

static void lowerStatepointMetaArgs(SmallVectorImpl< SDValue > &Ops, SmallVectorImpl< MachineMemOperand * > &MemRefs, SmallVectorImpl< SDValue > &GCPtrs, DenseMap< SDValue, int > &LowerAsVReg, SelectionDAGBuilder::StatepointLoweringInfo &SI, SelectionDAGBuilder &Builder)

Lower deopt state and gc pointer arguments of the statepoint.

Definition StatepointLowering.cpp:520

static std::pair< const GCResultInst *, const GCResultInst * > getGCResultLocality(const GCStatepointInst &S)

Return two gc.results if present.

Definition StatepointLowering.cpp:1003

static cl::opt< bool > UseRegistersForDeoptValues("use-registers-for-deopt-values", cl::Hidden, cl::init(false), cl::desc("Allow using registers for non pointer deopt args"))

static cl::opt< unsigned > MaxRegistersForGCPointers("max-registers-for-gc-values", cl::Hidden, cl::init(0), cl::desc("Max number of VRegs allowed to pass GC pointer meta args in"))

static void reservePreviousStackSlotForValue(const Value *IncomingValue, SelectionDAGBuilder &Builder)

Try to find existing copies of the incoming values in stack slots used for statepoint spilling.

Definition StatepointLowering.cpp:268

FunctionLoweringInfo::StatepointRelocationRecord RecordType

Definition StatepointLowering.cpp:76

static MachineMemOperand * getMachineMemOperand(MachineFunction &MF, FrameIndexSDNode &FI)

Definition StatepointLowering.cpp:358

static std::pair< SDValue, SDNode * > lowerCallFromStatepointLoweringInfo(SelectionDAGBuilder::StatepointLoweringInfo &SI, SelectionDAGBuilder &Builder)

Extract call from statepoint, lower it and return pointer to the call node.

Definition StatepointLowering.cpp:318

static std::tuple< SDValue, SDValue, MachineMemOperand * > spillIncomingStatepointValue(SDValue Incoming, SDValue Chain, SelectionDAGBuilder &Builder)

Spill a value incoming to the statepoint.

Definition StatepointLowering.cpp:376

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

This file describes how to lower LLVM code to machine code.

This class represents an incoming formal argument to a Function.

This class holds the attributes for a particular argument, parameter, function, or return value.

LLVM Basic Block Representation.

This class represents a no-op cast from one type to another.

Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...

This class represents a function call, abstracting a target machine's calling convention.

iterator find(const_arg_type_t< KeyT > Val)

std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)

size_type count(const_arg_type_t< KeyT > Val) const

Return 1 if the specified key is in the map, 0 otherwise.

LLVM_ABI const Value * getStatepoint() const

The statepoint with which this gc.relocate is associated.

Represents calls to the gc.relocate intrinsic.

LLVM_ABI Value * getDerivedPtr() const

Represents calls to the gc.result intrinsic.

Represents a gc.statepoint intrinsic call.

The landingpad instruction holds all of the information necessary to generate correct exception handl...

The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.

void markAsStatepointSpillSlotObjectIndex(int ObjectIdx)

Align getObjectAlign(int ObjectIdx) const

Return the alignment of the specified stack object.

int64_t getObjectSize(int ObjectIdx) const

Return the size of the specified object.

MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)

getMachineMemOperand - Allocate a new MachineMemOperand.

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

A description of a memory reference used in the backend.

@ MOVolatile

The memory access is volatile.

@ MOLoad

The memory access reads data.

@ MOStore

The memory access writes data.

An SDNode that represents everything that will be needed to construct a MachineInstr.

Wrapper class representing virtual and physical registers.

Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...

Represents one node in the SelectionDAG.

unsigned getOpcode() const

Return the SelectionDAG opcode value for this node.

unsigned getNumValues() const

Return the number of values defined/returned by this operator.

unsigned getNumOperands() const

Return the number of values used by this operation.

const SDValue & getOperand(unsigned Num) const

SDNode * getGluedNode() const

If this node has a glue operand, return the node to which the glue operand points.

op_iterator op_end() const

op_iterator op_begin() const

Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.

SDNode * getNode() const

get the SDNode which holds the desired result

SDValue getValue(unsigned R) const

EVT getValueType() const

Return the ValueType of the referenced return value.

SelectionDAGBuilder - This is the common target-independent lowering implementation that is parameter...

SDValue getValue(const Value *V)

getValue - Return an SDValue for the given Value.

MVT getFrameIndexTy()

Returns the type of FrameIndex and TargetFrameIndex nodes.

void LowerStatepoint(const GCStatepointInst &I, const BasicBlock *EHPadBB=nullptr)

Definition StatepointLowering.cpp:1018

SDValue lowerRangeToAssertZExt(SelectionDAG &DAG, const Instruction &I, SDValue Op)

void LowerDeoptimizeCall(const CallInst *CI)

Definition StatepointLowering.cpp:1306

void LowerCallSiteWithDeoptBundle(const CallBase *Call, SDValue Callee, const BasicBlock *EHPadBB)

Definition StatepointLowering.cpp:1178

void LowerCallSiteWithDeoptBundleImpl(const CallBase *Call, SDValue Callee, const BasicBlock *EHPadBB, bool VarArgDisallowed, bool ForceVoidReturnTy)

Definition StatepointLowering.cpp:1144

StatepointLoweringState StatepointLowering

State used while lowering a statepoint sequence (gc_statepoint, gc_relocate, and gc_result).

void populateCallLoweringInfo(TargetLowering::CallLoweringInfo &CLI, const CallBase *Call, unsigned ArgIdx, unsigned NumArgs, SDValue Callee, Type *ReturnTy, AttributeSet RetAttrs, bool IsPatchPoint)

Populate a CallLowerinInfo (into CLI) based on the properties of the call being lowered.

SmallVector< SDValue, 8 > PendingLoads

Loads are not emitted to the program immediately.

GCFunctionInfo * GFI

Garbage collection metadata for the function.

SDValue getRoot()

Similar to getMemoryRoot, but also flushes PendingConstrainedFP(Strict) items.

void ExportFromCurrentBlock(const Value *V)

ExportFromCurrentBlock - If this condition isn't known to be exported from the current basic block,...

SDLoc getCurSDLoc() const

SDValue getCopyFromRegs(const Value *V, Type *Ty)

If there was virtual register allocated for the value V emit CopyFromReg of the specified type Ty.

void LowerDeoptimizingReturn()

Definition StatepointLowering.cpp:1319

FunctionLoweringInfo & FuncInfo

Information about the function as a whole.

void setValue(const Value *V, SDValue NewN)

SDValue getControlRoot()

Similar to getRoot, but instead of flushing all the PendingLoad items, flush all the PendingExports (...

SDValue LowerAsSTATEPOINT(StatepointLoweringInfo &SI)

Lower SLI into a STATEPOINT instruction.

Definition StatepointLowering.cpp:707

size_type size() const

Determine the number of elements in the SetVector.

Vector takeVector()

Clear the SetVector and return the underlying vector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

A SetVector that performs no allocations if smaller than a certain size.

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

size_type count(const T &V) const

count - Return 1 if the element is in the set, 0 otherwise.

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

void clear()

Clear the memory usage of this object.

Definition StatepointLowering.cpp:99

SDValue allocateStackSlot(EVT ValueType, SelectionDAGBuilder &Builder)

Get a stack slot we can use to store an value of type ValueType.

Definition StatepointLowering.cpp:107

void startNewStatepoint(SelectionDAGBuilder &Builder)

Reset all state tracking for a newly encountered safepoint.

Definition StatepointLowering.cpp:86

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI Type * getVoidTy(LLVMContext &C)

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

iterator_range< user_iterator > users()

const ParentTy * getParent() const

#define llvm_unreachable(msg)

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

@ AnyReg

OBSOLETED - Used for stack based JavaScript calls.

@ C

The default llvm calling convention, compatible with C.

@ CopyFromReg

CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

auto find(R &&Range, const T &Val)

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

decltype(auto) dyn_cast(const From &Val)

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

bool isIntOrFPConstant(SDValue V)

Return true if V is either a integer or FP constant.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

auto dyn_cast_or_null(const Y &Val)

LLVM_ABI raw_ostream & dbgs()

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

StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS)

Parse out statepoint directives from the function attributes present in AS.

bool isa(const From &Val)

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

ArrayRef(const T &OneElt) -> ArrayRef< T >

@ MaskAll

A bitmask that includes all valid flags.

@ DeoptLiveIn

Mark the deopt arguments associated with the statepoint as only being "live-in".

@ GCTransition

Indicates that this statepoint is a transition from GC-aware code to code that is not GC-aware.

decltype(auto) cast(const From &Val)

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

PointerUnion< const Value *, const PseudoSourceValue * > ValueType

TypeSize getSizeInBits() const

Return the size of the specified value type in bits.

bool isVector() const

Return true if this is a vector value type.

Helper object to track which of three possible relocation mechanisms are used for a particular value ...

union llvm::FunctionLoweringInfo::StatepointRelocationRecord::payload_t payload

enum llvm::FunctionLoweringInfo::StatepointRelocationRecord::RelocType type

Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...

static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)

Return a MachinePointerInfo record that refers to the specified FrameIndex.

This struct represents the registers (physical or virtual) that a particular set of values is assigne...

void getCopyToRegs(SDValue Val, SelectionDAG &DAG, const SDLoc &dl, SDValue &Chain, SDValue *Glue, const Value *V=nullptr, ISD::NodeType PreferredExtendType=ISD::ANY_EXTEND) const

Emit a series of CopyToReg nodes that copies the specified value into the registers specified by this...

This represents a list of ValueType's that has been intern'd by a SelectionDAG.

Describes a gc.statepoint or a gc.statepoint like thing for the purposes of lowering into a STATEPOIN...

static const uint64_t DeoptBundleStatepointID