Auto merge of rust-lang/rust#143167 - Mark-Simulacrum:inline-mark-nou… · rust-lang/rust@209ede6 (original) (raw)

`@@ -115,6 +115,7 @@ trait Inliner<'tcx> {

`

115

115

``

116

116

`/// Has the caller body been changed?

`

117

117

`fn changed(self) -> bool;

`

``

118

`+

fn set_changed(&mut self);

`

118

119

``

119

120

`/// Should inlining happen for a given callee?

`

120

121

`fn should_inline_for_callee(&self, def_id: DefId) -> bool;

`

`@@ -187,6 +188,10 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {

`

187

188

`self.changed

`

188

189

`}

`

189

190

``

``

191

`+

fn set_changed(&mut self) {

`

``

192

`+

self.changed = true;

`

``

193

`+

}

`

``

194

+

190

195

`fn should_inline_for_callee(&self, def_id: DefId) -> bool {

`

191

196

`ForceInline::should_run_pass_for_callee(self.tcx(), def_id)

`

192

197

`}

`

`@@ -334,6 +339,10 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {

`

334

339

`self.changed

`

335

340

`}

`

336

341

``

``

342

`+

fn set_changed(&mut self) {

`

``

343

`+

self.changed = true;

`

``

344

`+

}

`

``

345

+

337

346

`fn should_inline_for_callee(&self, _: DefId) -> bool {

`

338

347

`true

`

339

348

`}

`

`@@ -529,10 +538,35 @@ fn process_blocks<'tcx, I: Inliner<'tcx>>(

`

529

538

`let span = trace_span!("process_blocks", %callsite.callee, ?bb);

`

530

539

`let _guard = span.enter();

`

531

540

``

532

``

`-

match try_inlining(inliner, caller_body, &callsite) {

`

``

541

`+

let mut unwind_unreachable = Err("did not reach analysis");

`

``

542

`+

match try_inlining(inliner, caller_body, &callsite, &mut unwind_unreachable) {

`

533

543

`Err(reason) => {

`

534

544

`debug!("not-inlined {} [{}]", callsite.callee, reason);

`

535

545

` inliner.on_inline_failure(&callsite, reason);

`

``

546

+

``

547

`+

match unwind_unreachable {

`

``

548

`+

Ok(()) => {

`

``

549

`+

if let Some(TerminatorKind::Call { unwind, .. }) =

`

``

550

`+

caller_body[callsite.block].terminator.as_mut().map(|v| &mut v.kind)

`

``

551

`+

{

`

``

552

`+

inliner.set_changed();

`

``

553

`+

tracing::info!("marked {} unwind unreachable", callsite.callee);

`

``

554

`+

*unwind = UnwindAction::Unreachable;

`

``

555

`+

} else {

`

``

556

`+

bug!(

`

``

557

`+

"unexpected terminator: {:?}",

`

``

558

`+

caller_body[callsite.block].terminator

`

``

559

`+

);

`

``

560

`+

}

`

``

561

`+

}

`

``

562

`+

Err(reason) => {

`

``

563

`+

tracing::info!(

`

``

564

`+

"not marking unwind unreachable {}: {}",

`

``

565

`+

callsite.callee,

`

``

566

`+

reason

`

``

567

`+

);

`

``

568

`+

}

`

``

569

`+

}

`

536

570

`}

`

537

571

`Ok(new_blocks) => {

`

538

572

`debug!("inlined {}", callsite.callee);

`

`@@ -595,17 +629,69 @@ fn resolve_callsite<'tcx, I: Inliner<'tcx>>(

`

595

629

`None

`

596

630

`}

`

597

631

``

``

632

`+

/// Ok indicates yes, Err(reason) otherwise.

`

``

633

`+

fn should_mark_nounwind<'tcx>(_tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> Result<(), &'static str> {

`

``

634

`+

// Unwinds can only start at certain terminators.

`

``

635

`+

for block in body.basic_blocks.iter() {

`

``

636

`+

let unwind = match block.terminator().kind {

`

``

637

`+

// These never unwind.

`

``

638

`+

TerminatorKind::Goto { .. }

`

``

639

`+

| TerminatorKind::SwitchInt { .. }

`

``

640

`+

| TerminatorKind::UnwindTerminate(_)

`

``

641

`+

| TerminatorKind::Return

`

``

642

`+

| TerminatorKind::Unreachable

`

``

643

`+

| TerminatorKind::CoroutineDrop

`

``

644

`+

| TerminatorKind::FalseEdge { .. }

`

``

645

`+

| TerminatorKind::FalseUnwind { .. } => continue,

`

``

646

+

``

647

`+

// Resume will continue unwinding, but if there's no other unwinding terminator it

`

``

648

`+

// will never be reached.

`

``

649

`+

TerminatorKind::UnwindResume => continue,

`

``

650

+

``

651

`+

TerminatorKind::Yield { .. } => {

`

``

652

`+

return Err("impl limitation: yield");

`

``

653

`+

}

`

``

654

+

``

655

`+

TerminatorKind::Drop { unwind, .. }

`

``

656

`+

| TerminatorKind::Call { unwind, .. }

`

``

657

`+

| TerminatorKind::Assert { unwind, .. } => unwind,

`

``

658

+

``

659

`+

TerminatorKind::InlineAsm { .. } => return Err("inlineasm"),

`

``

660

+

``

661

`+

TerminatorKind::TailCall { .. } => {

`

``

662

`+

return Err("impl limitation: tail call");

`

``

663

`+

}

`

``

664

`+

};

`

``

665

+

``

666

`+

match unwind {

`

``

667

`+

UnwindAction::Continue => return Err("unwind: continue"),

`

``

668

`+

// cannot unwind

`

``

669

`+

UnwindAction::Unreachable => {}

`

``

670

`+

// cannot unwind either -- will terminate instead

`

``

671

`+

UnwindAction::Terminate(_) => {}

`

``

672

`+

UnwindAction::Cleanup(_) => return Err("unwind: cleanup"),

`

``

673

`+

}

`

``

674

`+

}

`

``

675

+

``

676

`+

// If we didn't find an unwinding terminator, the function cannot unwind.

`

``

677

`+

Ok(())

`

``

678

`+

}

`

``

679

+

598

680

`/// Attempts to inline a callsite into the caller body. When successful returns basic blocks

`

599

681

`/// containing the inlined body. Otherwise returns an error describing why inlining didn't take

`

600

682

`/// place.

`

601

683

`fn try_inlining<'tcx, I: Inliner<'tcx>>(

`

602

684

`inliner: &I,

`

603

685

`caller_body: &mut Body<'tcx>,

`

604

686

`callsite: &CallSite<'tcx>,

`

``

687

`+

unwind: &mut Result<(), &'static str>,

`

605

688

`) -> Result<std::ops::Range, &'static str> {

`

606

689

`let tcx = inliner.tcx();

`

607

690

`check_mir_is_available(inliner, caller_body, callsite.callee)?;

`

608

691

``

``

692

`+

let callee_body = try_instance_mir(tcx, callsite.callee.def)?;

`

``

693

`+

*unwind = should_mark_nounwind(tcx, callee_body);

`

``

694

+

609

695

`let callee_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());

`

610

696

` check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?;

`

611

697

`check_codegen_attributes(inliner, callsite, callee_attrs)?;

`

`@@ -622,7 +708,6 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(

`

622

708

`}

`

623

709

`}

`

624

710

``

625

``

`-

let callee_body = try_instance_mir(tcx, callsite.callee.def)?;

`

626

711

` check_inline::is_inline_valid_on_body(tcx, callee_body)?;

`

627

712

` inliner.check_callee_mir_body(callsite, callee_body, callee_attrs)?;

`

628

713

``