Files
Andrea Gussoni 8443f06170 DetectUninlinableHelpers: introduce pass
Introduce a pass which statically demotes some helpers from candidates
for inlining:
1) Helpers which are part of SCC on the callgraph.
2) Helpers which contains an `insertvalue`.
3) Helpers which _fail_ the `CriticalArguments` criterion.

A critical argument is defined starting from the critical operand
definition.
A critical operand is either the condition of a `switch` instruction or
the indices of a `getelementptr` instruction.
If the dataflow computing the the operand trace back to a formal
parameter of the function, that parameter will be considered critical
when attempting the inlining of the helper.

In case each condition is satisfied, the `revng.inline.policy` metadata
is attached to the function, so that it can be used at _inline_ time to
take the decision based on the critical arguments constantness.

The metadata is encoded as an `iN` integer with N = `arg_size() + 1`:
the extra most-significant bit is always zero so LLVM's signed-decimal
`iN` printer renders the value positively (avoiding e.g. `!{i2 -2}`).

The (de)serialisation primitives live in `revng/Support/IRHelpers.h`
as `serializeInliningPolicy` / `deserializeInliningPolicy` so the
runtime `revngFunctionIsolation` doesn't need to link the build-time
`revngHelperInliningAnalyses` to read the metadata back.
2026-05-29 17:12:35 +02:00

39 lines
1.4 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <optional>
#include "llvm/ADT/BitVector.h"
#include "llvm/IR/Function.h"
namespace DetectUninlinableHelpers {
/// \return `true` if `Pointer` addresses a `GlobalVariable` marked as
/// `constant`.
bool isPointerToConstantGlobal(const llvm::Value *Pointer);
/// Compute the set of *critical formal arguments* of `Helper`.
///
/// An operand of an instruction is *critical* when one of the following holds:
/// - it is the condition of a `switch` instruction;
/// - it is one of the index operands of a `getelementptr` instruction.
///
/// A *critical argument* of `Helper` is a formal parameter that flows into a
/// critical operand. The function performs a backward dataflow walk from every
/// critical operand and classifies as critical every formal parameter reached
/// during the walk.
///
/// \return One of three possible values:
/// - `std::nullopt`: the helper cannot be inlined at any call site (the
/// backward walk reaches a `load` from runtime memory).
/// - empty `BitVector`: the helper can always be inlined.
/// - non-empty `BitVector`: the set of formal-parameter indices that must be
/// `isa<Constant>` at the call site for the helper to be inlinable.
std::optional<llvm::BitVector>
computeCriticalArgumentsFor(const llvm::Function &Helper);
} // namespace DetectUninlinableHelpers