]> git.ipfire.org Git - thirdparty/gcc.git/commit
Hard register constraints
authorStefan Schulze Frielinghaus <stefansf@gcc.gnu.org>
Mon, 21 Jul 2025 11:05:26 +0000 (13:05 +0200)
committerStefan Schulze Frielinghaus <stefansf@gcc.gnu.org>
Mon, 21 Jul 2025 11:05:26 +0000 (13:05 +0200)
commita51c146ebce41b5e4326b222f2d9e04bb22d276f
tree12927e37861a3a7e6707f6763e3ad552edd202a1
parent1eb17c6b20e662b4aa4b33e7e84ceccf6b6c41d8
Hard register constraints

Implement hard register constraints of the form {regname} where regname
must be a valid register name for the target.  Such constraints may be
used in asm statements as a replacement for register asm and in machine
descriptions.  A more verbose description is given in extend.texi.

It is expected and desired that optimizations coalesce multiple pseudos
into one whenever possible.  However, in case of hard register
constraints we may have to undo this and introduce copies since
otherwise we would constraint a single pseudo to multiple hard
registers.  This is done prior RA during asmcons in
match_asm_constraints_2().  While IRA tries to reduce live ranges, it
also replaces some register-register moves.  That in turn might undo
those copies of a pseudo which we just introduced during asmcons.  Thus,
check in decrease_live_ranges_number() via
valid_replacement_for_asm_input_p() whether it is valid to perform a
replacement.

The reminder of the patch mostly deals with parsing and decoding hard
register constraints.  The actual work is done by LRA in
process_alt_operands() where a register filter, according to the
constraint, is installed.

For the sake of "reviewability" and in order to show the beauty of LRA,
error handling (which gets pretty involved) is spread out into a
subsequent patch.

Limitation
----------

Currently, a fixed register cannot be used as hard register constraint.
For example, loading the stack pointer on x86_64 via

void *
foo (void)
{
  void *y;
  __asm__ ("" : "={rsp}" (y));
  return y;
}

leads to an error.

Asm Adjust Hook
---------------

The following targets implement TARGET_MD_ASM_ADJUST:

- aarch64
- arm
- avr
- cris
- i386
- mn10300
- nds32
- pdp11
- rs6000
- s390
- vax

Most of them only add the CC register to the list of clobbered register.
However, cris, i386, and s390 need some minor adjustment.

gcc/ChangeLog:

* config/cris/cris.cc (cris_md_asm_adjust): Deal with hard
register constraint.
* config/i386/i386.cc (map_egpr_constraints): Ditto.
* config/s390/s390.cc (f_constraint_p): Ditto.
* doc/extend.texi: Document hard register constraints.
* doc/md.texi: Ditto.
* function.cc (match_asm_constraints_2): Have a unique pseudo
for each operand with a hard register constraint.
(pass_match_asm_constraints::execute): Calling into new helper
match_asm_constraints_2().
* genoutput.cc (mdep_constraint_len): Return the length of a
hard register constraint.
* genpreds.cc (write_insn_constraint_len): Support hard register
constraints for insn_constraint_len().
* ira.cc (valid_replacement_for_asm_input_p_1): New helper.
(valid_replacement_for_asm_input_p): New helper.
(decrease_live_ranges_number): Similar to
match_asm_constraints_2() ensure that each operand has a unique
pseudo if constrained by a hard register.
* lra-constraints.cc (process_alt_operands): Install hard
register filter according to constraint.
* recog.cc (asm_operand_ok): Accept register type for hard
register constrained asm operands.
(constrain_operands): Validate hard register constraints.
* stmt.cc (decode_hard_reg_constraint): Parse a hard register
constraint into the corresponding register number or bail out.
(parse_output_constraint): Parse hard register constraint and
set *ALLOWS_REG.
(parse_input_constraint): Ditto.
* stmt.h (decode_hard_reg_constraint): Declaration of new
function.

gcc/testsuite/ChangeLog:

* gcc.dg/asm-hard-reg-1.c: New test.
* gcc.dg/asm-hard-reg-2.c: New test.
* gcc.dg/asm-hard-reg-3.c: New test.
* gcc.dg/asm-hard-reg-4.c: New test.
* gcc.dg/asm-hard-reg-5.c: New test.
* gcc.dg/asm-hard-reg-6.c: New test.
* gcc.dg/asm-hard-reg-7.c: New test.
* gcc.dg/asm-hard-reg-8.c: New test.
* gcc.target/aarch64/asm-hard-reg-1.c: New test.
* gcc.target/i386/asm-hard-reg-1.c: New test.
* gcc.target/i386/asm-hard-reg-2.c: New test.
* gcc.target/s390/asm-hard-reg-1.c: New test.
* gcc.target/s390/asm-hard-reg-2.c: New test.
* gcc.target/s390/asm-hard-reg-3.c: New test.
* gcc.target/s390/asm-hard-reg-4.c: New test.
* gcc.target/s390/asm-hard-reg-5.c: New test.
* gcc.target/s390/asm-hard-reg-6.c: New test.
* gcc.target/s390/asm-hard-reg-longdouble.h: New test.
31 files changed:
gcc/config/cris/cris.cc
gcc/config/i386/i386.cc
gcc/config/s390/s390.cc
gcc/doc/extend.texi
gcc/doc/md.texi
gcc/function.cc
gcc/genoutput.cc
gcc/genpreds.cc
gcc/ira.cc
gcc/lra-constraints.cc
gcc/recog.cc
gcc/stmt.cc
gcc/stmt.h
gcc/testsuite/gcc.dg/asm-hard-reg-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-hard-reg-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-hard-reg-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-hard-reg-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-hard-reg-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-hard-reg-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-hard-reg-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-hard-reg-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/asm-hard-reg-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/asm-hard-reg-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/asm-hard-reg-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/asm-hard-reg-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/asm-hard-reg-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/asm-hard-reg-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/asm-hard-reg-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/asm-hard-reg-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/asm-hard-reg-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/asm-hard-reg-longdouble.h [new file with mode: 0644]