Mode Switching (GNU Compiler Collection (GCC) Internals)

### 19.25 Mode Switching Instructions ¶

The following macros control mode switching optimizations:

Macro: OPTIMIZE_MODE_SWITCHING (entity) ¶

  Define this macro if the port needs extra instructions inserted for mode switching.

  For an example, the SH4 can perform both single and double precision floating point operations, but to perform a single precision operation, the FPSCR PR bit has to be cleared, while for a double precision operation, this bit has to be set. Changing the PR bit requires a general purpose register as a scratch register, hence these FPSCR sets have to be inserted before reload, i.e. you cannot put this into instruction emitting or `TARGET_MACHINE_DEPENDENT_REORG`.

  You can have multiple entities that are mode-switched, some of which might only be needed conditionally. The entities are identified by their index into the `NUM_MODES_FOR_MODE_SWITCHING` initializer, with the length of the initializer determining the number of entities.

  `OPTIMIZE_MODE_SWITCHING` should return nonzero for any entity that needs mode-switching.

  If you define this macro, you also have to define `NUM_MODES_FOR_MODE_SWITCHING`, `TARGET_MODE_NEEDED`, `TARGET_MODE_PRIORITY` and `TARGET_MODE_EMIT`. The other macros in this section are optional.

Macro: NUM_MODES_FOR_MODE_SWITCHING ¶

  If you define `OPTIMIZE_MODE_SWITCHING`, you have to define this as initializer for an array of integers. Each initializer element N refers to an entity that needs mode switching, and specifies the number of different modes that are defined for that entity. The position of the element in the initializer—starting counting at zero—determines the integer that is used to refer to the mode-switched entity in question. Modes are represented as numbers 0 … N − 1. In mode arguments and return values, N either represents an unknown mode or “no mode”, depending on context.

Target Hook: `void` TARGET_MODE_EMIT `(int entity, int mode, int prev_mode, HARD_REG_SET regs_live)` ¶

  Generate one or more insns to set entity to mode. regs_live is the set of hard registers live at the point where the insn(s) are to be inserted. prev_mode indicates the mode to switch from, or is the number of modes if the previous mode is not known. Sets of a lower numbered entity will be emitted before sets of a higher numbered entity to a mode of the same or lower priority.

Target Hook: `int` TARGET_MODE_NEEDED `(int entity, rtx_insn *insn, HARD_REG_SET regs_live)` ¶

  entity is an integer specifying a mode-switched entity. If `OPTIMIZE_MODE_SWITCHING` is defined, you must define this hook to return the mode that entity must be switched into prior to the execution of insn, or the number of modes if insn has no such requirement. regs_live contains the set of hard registers that are live before insn.

Target Hook: `int` TARGET_MODE_AFTER `(int entity, int mode, rtx_insn *insn, HARD_REG_SET regs_live)` ¶

  entity is an integer specifying a mode-switched entity. If this hook is defined, it is evaluated for every insn during mode switching. It returns the mode that entity is in after insn has been executed. mode is the mode that entity was in before insn was executed, taking account of TARGET_MODE_NEEDED. regs_live is the set of hard registers that are live after insn has been executed.

  mode is equal to the number of modes defined for entity if the mode before insn is unknown. The hook should likewise return the number of modes if it does not know what mode entity has after insn.

  Not defining the hook is equivalent to returning mode.

Target Hook: `int` TARGET_MODE_CONFLUENCE `(int entity, int mode1, int mode2)` ¶

  By default, the mode-switching pass assumes that a given entity’s modes are mutually exclusive. This means that the pass can only tell `TARGET_MODE_EMIT` about an entity’s previous mode if all incoming paths of execution leave the entity in the same state.

  However, some entities might have overlapping, non-exclusive modes, so that it is sometimes possible to represent “mode mode1 or mode mode2” with something more specific than “mode not known”. If this is true for at least one entity, you should define this hook and make it return a mode that includes mode1 and mode2 as possibilities. (The mode can include other possibilities too.) The hook should return the number of modes if no suitable mode exists for the given arguments.

Target Hook: `int` TARGET_MODE_BACKPROP `(int entity, int mode1, int mode2)` ¶

  If defined, the mode-switching pass uses this hook to back-propagate mode requirements through blocks that have no mode requirements of their own. Specifically, mode1 is the mode that entity has on exit from a block B1 (say) and mode2 is the mode that the next block requires entity to have. B1 does not have any mode requirements of its own.

  The hook should return the mode that it prefers or requires entity to have in B1, or the number of modes if there is no such requirement. If the hook returns a required mode for more than one of B1’s outgoing edges, those modes are combined as for `TARGET_MODE_CONFLUENCE`.

  For example, suppose there is a “one-shot” entity that, for a given execution of a function, either stays off or makes exactly one transition from off to on. It is safe to make the transition at any time, but it is better not to do so unnecessarily. This hook allows the function to manage such an entity without having to track its state at runtime. Specifically. the entity would have two modes, 0 for off and 1 for on, with 2 representing “don’t know”. The system is forbidden from transitioning from 2 to 1, since 2 represents the possibility that the entity is already on (and the aim is to avoid having to emit code to check for that case). This hook would therefore return 1 when mode1 is 2 and mode2 is 1, which would force the entity to be on in the source block. Applying this inductively would remove all transitions in which the previous state is unknown.

Target Hook: `int` TARGET_MODE_ENTRY `(int entity)` ¶

  If this hook is defined, it is evaluated for every entity that needs mode switching. It should return the mode that entity is guaranteed to be in on entry to the function, or the number of modes if there is no such guarantee. If `TARGET_MODE_ENTRY` is defined then `TARGET_MODE_EXIT` must be defined.

Target Hook: `int` TARGET_MODE_EXIT `(int entity)` ¶

  If this hook is defined, it is evaluated for every entity that needs mode switching. It should return the mode that entity must be in on return from the function, or the number of modes if there is no such requirement. If `TARGET_MODE_EXIT` is defined then `TARGET_MODE_ENTRY` must be defined.

Target Hook: `int` TARGET_MODE_EH_HANDLER `(int entity)` ¶

  If this hook is defined, it should return the mode that entity is guaranteed to be in on entry to an exception handler, or the number of modes if there is no such guarantee.

Target Hook: `int` TARGET_MODE_PRIORITY `(int entity, int n)` ¶

  This hook specifies the order in which modes for entity are processed. 0 is the highest priority, `NUM_MODES_FOR_MODE_SWITCHING[entity] - 1` the lowest. The hook returns an integer designating a mode for entity. For any fixed entity, `mode_priority` (entity, n) shall be a bijection in 0 … `num_modes_for_mode_switching[entity] - 1`.