Function constant pinning
function_constant_pinning
¶
PIN_CONSTANT_VALS = 'pin_to_constants'
module-attribute
¶
FunctionConstantPinning
¶
Bases: RewritePattern
Source code in xdsl/transforms/experimental/function_constant_pinning.py
match_and_rewrite(func_op: func.FuncOp, rewriter: PatternRewriter)
¶
Source code in xdsl/transforms/experimental/function_constant_pinning.py
FunctionConstantPinningPass
dataclass
¶
Bases: ModulePass
This pass consumes IR annotated with special hints to generate new functions that have certain SSA values pinned to a constant, usually to enable further optimization options on this pinned function.
The original function is changed to dynamically dispatch to this pinned function when the ssa value matches the given constant.
Any single-result operation annotated with a "pin_to_constants" attribute containing an array of values, that is located within a function body triggers this optimization. These annotations are usually inserted by previous passes that know that they would want to generate a more optimized version of their function for specific values of a run-time determined variable.
An example might be a function that branches repeatedly on a specific variable:
function test() {
x = calc_condition()
if (x) {
specific_thing()
}
some_thing() // A
if (x) {
another_thing()
}
some_thing() // B
}
if we can pin x to true, we are suddenly able to generate two much simple function bodies (after constant folding)
function test() {
x = calc_condition()
if (x) {
test_pinned()
return
}
some_thing() // A
some_thing() // B
}
function test_pinned() {
specific_thing()
some_thing() // A
another_thing()
some_thing() // B
}
Note that the function test_pinned might be much easier to optimize for a compiler if there are state
dependencies between specific_thing, another_thing and some_thing.
Source code in xdsl/transforms/experimental/function_constant_pinning.py
name = 'function-constant-pinning'
class-attribute
instance-attribute
¶
generate_func_with_pinned_val(func_op: func.FuncOp, pin: IntegerAttr[IntegerType | IndexType], rewriter: PatternRewriter)
¶
Specializes a function to pin a value to a compile time constant. Assumes the function is top-level inside the module.
This will do the following things: - clone the function - rename it to be uniquely named inside the module - erase all operations up until the operation producing the pinned value - replace the operation with a constant instantiation
Source code in xdsl/transforms/experimental/function_constant_pinning.py
func_contains_pinning_annotation(funcop: func.FuncOp) -> Operation | None
¶
Return the first operation inside the function that has a "pin_to_constants" attribute.
Only works on top-level operations, we can't handle nested things right now.
Source code in xdsl/transforms/experimental/function_constant_pinning.py
get_pinned_vals_for_op(op: Operation) -> list[IntegerAttr[IntegerType | IndexType]] | None
¶
Reads the "pin_to_constants" attribute of an operation, checks for valid formatting, and return the list of attribute values that should be pinned.
Source code in xdsl/transforms/experimental/function_constant_pinning.py
ops_between_op_and_func_start(func_op: func.FuncOp, op: Operation) -> Iterable[Operation]
¶
Get a list of all operations localed between op and the start of body. Returns them in reverse order of occurrence.
op must be a direct child of func_op!
func.func @test() { // <- func_op test.test() // A test.test() // B test.test() // <- op test.test() // C
should return only B, A not C
Source code in xdsl/transforms/experimental/function_constant_pinning.py
unique_pinned_name(module: builtin.ModuleOp, name: str, hint: str) -> str
¶
Generate a new name that is unique to the module