API

FunctionProperties.hasbranching — Function
hasbranching(f, x...)

Checks whether the function f has branches (if statements) that are dependent on the value x that would be taken in a tracing system, such as during AD tracing by a package like ReverseDiff.jl.

Arguments

  • f: the function to inspect.
  • x: test arguments. These values don't need to match the actual call values, but their types must match — they are used to select the right method specialization.

Outputs

Boolean for whether the function contains a value-dependent conditional branch (GotoIfNot). The type-inferred IR (code_typed(...; optimize = false)) of f is scanned, and the scan recurses through statically resolved calls into other user-defined methods so that branches living behind a non-inlined call boundary are still detected. Calls into Base, Core, and the standard libraries are treated as leaves: their internal branches are structural/compile-time rather than value-dependent user logic, and recursing into them (e.g. matrix multiply, broadcasting, getindex bounds checks) produces false positives.

Branches whose condition inference proves constant are ignored (they are not value-dependent), and — where the compiler cooperates — a call with constant arguments is re-inferred with those constants preserved so branches they decide fold away rather than being reported.

Customizing and Removing Functions from the Checks

Some functions may produce false positives because their internal branches are compile-time constants. Override is_leaf to opt them out (this also prevents recursion into them):

FunctionProperties.is_leaf(::typeof(my_fn)) = true
source
FunctionProperties.is_leaf — Function
is_leaf(f, args...) -> Bool

Override this to exempt a function from hasbranching analysis. Return true to treat f as branch-free regardless of its implementation, which also stops hasbranching from recursing into its callees.

Example

FunctionProperties.is_leaf(::typeof(my_fn)) = true
source