Skip to content

[schedule] Better builder defaults#87

Merged
adam-smnk merged 2 commits intollvm:mainfrom
adam-smnk:builder-fix-sequence-default-result
Mar 23, 2026
Merged

[schedule] Better builder defaults#87
adam-smnk merged 2 commits intollvm:mainfrom
adam-smnk:builder-fix-sequence-default-result

Conversation

@adam-smnk
Copy link
Member

@adam-smnk adam-smnk commented Mar 20, 2026

Moves defaults from the named sequence builder to the schedule boilerplate helper.

The new defaults assign a single input argument and expect no results.
This aligns better with current usage of the boilerplate to create simple schedules that do not return any values.

Switches named sequeunce builder to expect no results by default.
This aligns better with most schedules that do not return any values.
@adam-smnk adam-smnk requested review from rengolin and rolfmorel March 20, 2026 15:32
Copy link
Contributor

@rolfmorel rolfmorel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will just comment that for "bundle schedules" to be useful for being composed into an overall schedule, they will need to return the (modified) payload module. These overall schedules, e.g., enable a straightforward approach to specifying the relevant tuning problem.

I am okay with this going in as it changes the default, though would strongly encourage (sub-)schedules to still yield a/the relevant result(s) when possible -- especially if it's not possible to still have a handle to them to due the bundle invalidating the passed-in handles.

@rolfmorel
Copy link
Contributor

As an alternative approach, we might want an @schedule decorator which works like the @func.func decorator, which takes the return types as arguments, whereby the decorated Python function just defines the body of the named sequence (which could be automatically wrapped in a module depending on args).

Have a look at

# The first overload:
def wrapper(func):
# Create a ConstrainParamsOp with just the transform parameters as block arguments.
param_args = [p for p in args if isinstance(p, ir.Value)]
constrain_params = ConstrainParamsOp([], param_args, **kwargs)
constrain_params.body_.blocks.append(*[smt.IntType.get()] * len(param_args))
# Call `func` with !smt.int block arguments for corresponding transform params,
# and just normal ints for those passed via `args`. The body of `func` will be
# the body of the op, and it can yield a mix of Python integers and `!smt.int`s.
# A corresponding `smt.yield` will be generated as the terminator.
block_args_iter = iter(constrain_params.body_.blocks[0].arguments)
with ir.InsertionPoint(constrain_params.body):
yielded_results = func(
*(
next(block_args_iter) if isinstance(arg, ir.Value) else arg
for arg in args
)
)
if not isinstance(yielded_results, Sequence):
yielded_results = [yielded_results]
smt.yield_(res for res in yielded_results if isinstance(res, ir.Value))
# In case no results are returned, the current ConstrainParamsOp is sufficient.
if len(yielded_results) == 0:
return constrain_params
# Create a new version of the ConstrainParamsOp that has the same
# parameters but whose results correspond to the mix of integers and
# SMT values yielded from the body.
result_values_or_types = [
transform.AnyParamType.get() if isinstance(res, ir.Value) else res
for res in yielded_results
]
mixed_result_op = MixedResultConstrainParamsOp(
params=param_args,
result_values_or_types=result_values_or_types,
**kwargs,
)
# Move the body of the original op to the version with (mixed) results.
constrain_params.body_.blocks[0].append_to(mixed_result_op.body_)
# Safe to remove as the op doesn't have results, so no users either.
constrain_params.erase()
return mixed_result_op
return wrapper
for an approach where the result types don't even need to specified on the decorator. The relevant bit is moving the block from the original op to a new op instance.

@adam-smnk
Copy link
Member Author

+1 to overall direction
These bundles could be named sequences to compose with transform.include or to be simply wrapped in a schedule.

I'll move these defaults to schedule_boilerplate as they're more relevant for its use cases i.e., simple one-shot schedules.
The sequence builder itself shouldn't be that opinionated.

@adam-smnk adam-smnk changed the title [schedule] Better named sequence builder's result default [schedule] Better builder defaults Mar 23, 2026
@adam-smnk adam-smnk merged commit 074f833 into llvm:main Mar 23, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants