MCPcopy Create free account
hub / github.com/Rust-GPU/rust-gpu / should_inline

Function should_inline

crates/rustc_codegen_spirv/src/linker/inline.rs:382–458  ·  view source on GitHub ↗

Returns `Ok(true)`/`Err(MustInlineToLegalize)` if `callee` should/must be inlined (either in general, or specifically from `call_site`, if provided). The distinction made is that `Err(MustInlineToLegalize)` is not a heuristic, and inlining is *mandatory* due to an illegal signature/arguments.

(
    legal_globals: &FxHashMap<Word, LegalGlobal>,
    functions_that_may_abort: &FxHashSet<Word>,
    callee: &Function,
    call_site: Option<CallSite<'_>>,
)

Source from the content-addressed store, hash-verified

380/// The distinction made is that `Err(MustInlineToLegalize)` is not a heuristic,
381/// and inlining is *mandatory* due to an illegal signature/arguments.
382fn should_inline(
383 legal_globals: &FxHashMap<Word, LegalGlobal>,
384 functions_that_may_abort: &FxHashSet<Word>,
385 callee: &Function,
386 call_site: Option<CallSite<'_>>,
387) -> Result<bool, MustInlineToLegalize> {
388 let callee_def = callee.def.as_ref().unwrap();
389 let callee_control = callee_def.operands[0].unwrap_function_control();
390
391 // HACK(eddyb) this "has a call-site" check ensures entry-points don't get
392 // accidentally removed as "must inline to legalize" function, but can still
393 // be inlined into other entry-points (if such an unusual situation arises).
394 if call_site.is_some() && functions_that_may_abort.contains(&callee.def_id().unwrap()) {
395 return Err(MustInlineToLegalize);
396 }
397
398 let ret_ty = legal_globals
399 .get(&callee_def.result_type.unwrap())
400 .ok_or(MustInlineToLegalize)?;
401 if !ret_ty.legal_as_fn_ret_ty() {
402 return Err(MustInlineToLegalize);
403 }
404
405 for (i, param) in callee.parameters.iter().enumerate() {
406 let param_ty = legal_globals
407 .get(param.result_type.as_ref().unwrap())
408 .ok_or(MustInlineToLegalize)?;
409 if !param_ty.legal_as_fn_param_ty() {
410 return Err(MustInlineToLegalize);
411 }
412
413 // If the call isn't passing a legal pointer argument (a "memory object",
414 // i.e. an `OpVariable` or one of the caller's `OpFunctionParameters),
415 // then inlining is required to have a chance at producing legal SPIR-V.
416 //
417 // FIXME(eddyb) rewriting away the pointer could be another alternative.
418 if let (LegalGlobal::TypePointer(_), Some(call_site)) = (param_ty, call_site) {
419 let ptr_arg = call_site.call_inst.operands[i + 1].unwrap_id_ref();
420 match legal_globals.get(&ptr_arg) {
421 Some(LegalGlobal::Variable) => {}
422
423 // FIXME(eddyb) should some constants (undef/null) be allowed?
424 Some(_) => return Err(MustInlineToLegalize),
425
426 None => {
427 let mut caller_param_and_var_ids = call_site
428 .caller
429 .parameters
430 .iter()
431 .chain(
432 call_site.caller.blocks[0]
433 .instructions
434 .iter()
435 .filter(|caller_inst| {
436 // HACK(eddyb) this only avoids scanning the
437 // whole entry block for `OpVariable`s, so
438 // it can overapproximate debuginfo insts.
439 let may_be_debuginfo = matches!(

Callers 2

inlineFunction · 0.85
inline_blockMethod · 0.85

Calls 5

legal_as_fn_ret_tyMethod · 0.80
iterMethod · 0.80
legal_as_fn_param_tyMethod · 0.80
as_refMethod · 0.45
getMethod · 0.45

Tested by

no test coverage detected