mlugg 457c94d353
compiler: implement @branchHint, replacing @setCold
Implements the accepted proposal to introduce `@branchHint`. This
builtin is permitted as the first statement of a block if that block is
the direct body of any of the following:

* a function (*not* a `test`)
* either branch of an `if`
* the RHS of a `catch` or `orelse`
* a `switch` prong
* an `or` or `and` expression

It lowers to the ZIR instruction `extended(branch_hint(...))`. When Sema
encounters this instruction, it sets `sema.branch_hint` appropriately,
and `zirCondBr` etc are expected to reset this value as necessary. The
state is on `Sema` rather than `Block` to make it automatically
propagate up non-conditional blocks without special handling. If
`@panic` is reached, the branch hint is set to `.cold` if none was
already set; similarly, error branches get a hint of `.unlikely` if no
hint is explicitly provided. If a condition is comptime-known, `cold`
hints from the taken branch are allowed to propagate up, but other hints
are discarded. This is because a `likely`/`unlikely` hint just indicates
the direction this branch is likely to go, which is redundant
information when the branch is known at comptime; but `cold` hints
indicate that control flow is unlikely to ever reach this branch,
meaning if the branch is always taken from its parent, then the parent
is also unlikely to ever be reached.

This branch information is stored in AIR `cond_br` and `switch_br`. In
addition, `try` and `try_ptr` instructions have variants `try_cold` and
`try_ptr_cold` which indicate that the error case is cold (rather than
just unlikely); this is reachable through e.g. `errdefer unreachable` or
`errdefer @panic("")`.

A new API `unwrapSwitch` is introduced to `Air` to make it more
convenient to access `switch_br` instructions. In time, I plan to update
all AIR instructions to be accessed via an `unwrap` method which returns
a convenient tagged union a la `InternPool.indexToKey`.

The LLVM backend lowers branch hints for conditional branches and
switches as follows:

* If any branch is marked `unpredictable`, the instruction is marked
  `!unpredictable`.
* Any branch which is marked as `cold` gets a
  `llvm.assume(i1 true) [ "cold"() ]` call to mark the code path cold.
* If any branch is marked `likely` or `unlikely`, branch weight metadata
  is attached with `!prof`. Likely branches get a weight of 2000, and
  unlikely branches a weight of 1. In `switch` statements, un-annotated
  branches get a weight of 1000 as a "middle ground" hint, since there
  could be likely *and* unlikely *and* un-annotated branches.

For functions, a `cold` hint corresponds to the `cold` function
attribute, and other hints are currently ignored -- as far as I can tell
LLVM doesn't really have a way to lower them. (Ideally, we would want
the branch hint given in the function to propagate to call sites.)

The compiler and standard library do not yet use this new builtin.

Resolves: #21148
2024-08-27 00:41:49 +01:00
..
2024-08-23 19:23:38 -07:00
2024-07-09 14:25:42 -07:00
2024-08-07 00:48:32 -07:00
2024-07-25 18:52:20 -07:00
2024-07-23 11:43:12 -07:00
2024-07-09 14:25:42 -07:00
2024-08-15 22:05:53 -07:00
2024-07-19 00:30:32 -07:00
2024-07-02 16:31:15 +02:00
2024-07-09 14:25:42 -07:00
2024-08-22 08:44:08 +02:00
2024-07-20 01:06:29 -07:00
2024-07-19 00:30:32 -07:00
2024-08-07 00:48:32 -07:00
2024-07-31 16:57:42 -07:00
2024-07-28 21:34:14 -07:00
2024-07-19 00:30:32 -07:00
2024-04-15 15:24:30 -07:00
2024-07-19 00:30:32 -07:00
2024-08-01 22:11:35 -07:00
2024-07-09 14:25:42 -07:00
2024-08-15 22:05:53 -07:00
2024-07-25 18:52:20 -07:00
2024-07-19 00:30:32 -07:00
2024-08-23 22:59:30 -07:00
2024-06-17 16:12:19 -04:00