Next: , Previous: Allocation Order, Up: Registers


17.7.3 如何使值适合寄存器

这节讨论的宏,描述了每个寄存器可以存放哪类的值(明确的说, 是哪些机器模式的),以及对于给定的机器模式需要多少个连续的寄存器。

— Macro: HARD_REGNO_NREGS (regno, mode)

一个C表达式,为存放模式mode的值所需要的连续的硬件寄存器, 起始于寄存器编号regno。该宏不要返回0, 即使寄存器不能存放指定的mode —— 替代的, 使用HARD_REGNO_MODE_OK 和/或 CANNOT_CHANGE_MODE_CLASS。

在所有寄存器都是一个字大小的机器上,该宏的一个合适的定义为

          #define HARD_REGNO_NREGS(REGNO, MODE)            \
             ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
              / UNITS_PER_WORD)
— Macro: HARD_REGNO_NREGS_HAS_PADDING (regno, mode)

一个C表达式,为非0,如果模式为mode的值,存储在内存中, 并由padding结尾,这使得其占有更多的空间, 比在起始于寄存器编号regno的寄存器中。缺省的为0。

例如,如果浮点值存储在三个32位寄存器中,但是在内存中占有128位,则该宏应该为非0。

该宏只有当subreg_get_info会错误的确定一个subreg可以通过寄存器编号的偏移量来表示, 而实际上这样的subreg将会保存一些不应该被表示的padding时, 才需要被定义。

— Macro: HARD_REGNO_NREGS_WITH_PADDING (regno, mode)

对于HARD_REGNO_NREGS_HAS_PADDING会返回非0的regnomode的值, 其为一个C表达式,返回保存包括任何padding的值所需要的寄存器的最大数。 在上面的例子中,值将为4。

— Macro: REGMODE_NATURAL_SIZE (mode)

定义该宏,如果存放模式mode的值的寄存器的自然大小,不是word大小。 其为一个C表达式,对于指定的mode给出以字节为单位的自然的大小。 其被寄存器分配用于尝试优化它的结果。 例如这出现在SPARC 64位机器上,其浮点寄存器的自然大小仍然是32位。

— Macro: HARD_REGNO_MODE_OK (regno, mode)

一个C表达式,其为非0, 如果允许将一个mode模式的值存储在硬件寄存器编号regno (或者起始于它的多个寄存器)中。对于所有寄存器都是等价的机器上, 一个合适的定义为

          #define HARD_REGNO_MODE_OK(REGNO, MODE) 1

你不需要包含检查固定寄存器编号的代码, 因为分配机制总是认为它们已经被占用了。

在一些机器上,双精度值必须放在偶/奇寄存器对。 你可以通过定义该宏来拒绝这样模式的奇数寄存器编号。

对于一个模式可以放在寄存器中的最小需求为, ‘movmode’指令模式支持在寄存器和同一类别的其它硬件寄存器之间的移动, 并且将一个值移动到寄存器中并移动回来,而不会改变。

由于用于move word_mode的同一指令,也可以用于所有更窄的整数模式, 所以HARD_REGNO_MODE_OK不必要在任何机器上对于这些模式都不同, 假定你定义了指令模式‘movhi’等。

许多机器对于浮点算术具有特定的寄存器。 通常人们假设浮点机器模式只在浮点寄存器中被允许。这并不真实。 任何可以存放整数的寄存器都可以安全的存放一个浮点机器模式, 而不管是否可以在这些寄存器上进行浮点算术。 整数move指令可以用于移动这些值。

然而在一些机器上,定点机器模式不可以放在浮点寄存器中。 比如如果浮点寄存器对任何存储的值进行标准化, 因为存储一个非浮点值将会使值变得混淆。这种情况下, HARD_REGNO_MODE_OK应该拒绝定点机器模式放在浮点寄存器中。 但是,如果浮点寄存器不自动标准化, 如果你可以存储任何位的指令模式并无需改动的获得它, 则任何机器模式都可以放在浮点寄存器中,这样你可以定义该宏来表明可以这么做。

当然,特定的浮点寄存器的主要意义是它们在浮点算术指令中可以使用。 但是,这根HARD_REGNO_MODE_OK没有关系。 你可以通过对那些执行写合适的约束来处理。

在一些机器上,浮点寄存器访问起来特别慢,所以如果浮点算术没有完成前, 最好将值存在栈帧中,而不是在这样的寄存器中。 只要浮点寄存器不在GENERAL_REGS类别中,它们将不会被使用, 除非某个指令模式的约束要求这样。

— Macro: HARD_REGNO_RENAME_OK (from, to)

一个C表达式,为非0, 如果可以将一个硬件寄存器from重命名为另一个寄存器to

该宏的一个通用的用法是防止将一个寄存器重命名为另一个寄存器, 而其在中断处理函数的序言中没有被保存。

缺省总是为非0。

— Macro: MODES_TIEABLE_P (mode1, mode2)

一个C表达式,其为非0,如果一个模式mode1的值, 不需要复制便可以按照模式mode2来访问。

如果HARD_REGNO_MODE_OK (r, mode1)HARD_REGNO_MODE_OK (r, mode2)对于任何r总是相同, 则MODES_TIEABLE_P (mode1, mode2)应该为非0。 如果它们对于任何r都不同,则你应该定义该宏来返回0, 除非某个其它机制能够确保值可以按照更窄的模式来访问。

你应该定义该宏来尽可能情况的返回非0, 因为这样会使得GCC执行更好的寄存器分配。

— Target Hook: bool TARGET_HARD_REGNO_SCRATCH_OK (unsigned int regno)

This target hook should return true if it is OK to use a hard register regno as scratch reg in peephole2. This target hook should return true if it is OK to use a hard register regno as scratch reg in peephole2.

One common use of this macro is to prevent using of a register that is not saved by a prologue in an interrupt handler.

The default version of this hook always returns true.

— Macro: AVOID_CCMODE_COPIES

定义该宏,如果编译器应该避免复制从/到CCmode寄存器。 你应该只当对复制从/到CCmode寄存器的支持不完善的时候定义该宏。