https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124221

            Bug ID: 124221
           Summary: ICE in multi-alternative asm with"=X"
           Product: gcc
           Version: 15.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: sparks05 at proton dot me
  Target Milestone: ---
              Host: x86_64-linux-gnu
            Target: x86_64-linux-gnu
             Build: x86_64-linux-gnu

Created attachment 63772
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63772&action=edit
Copy of source also included in main text.

The following parity-computation function:

bool parity(unsigned long x) {
    bool p;
    unsigned y = (unsigned)x ^ (unsigned)(x >> 16 >> 16);
    y ^= y >> 16;
    asm("xorb %h2, %b2; setpo %b0" : "=Q,q"(p), "=X,Q"(y) : "0,1"(y));
    return p;
}

produces the following (output from godbolt; the MSYS2 gcc does
the same, but is a custom build):

# Compilation provided by Compiler Explorer at https://godbolt.org/
<Compilation failed>
# Compiler exited with result code 1
Standard error:
<source>: In function 'bool parity(long unsigned int)':
<source>:9:1: error: unrecognizable insn:
    9 | }
      | ^
(insn 33 0 0 (set (reg:SI 113)
        (xor:SI (xor:SI (lshiftrt:SI (xor:SI (subreg:SI (zero_extract:DI
(reg:DI 111 [ x ])
                                (const_int 32 [0x20])
                                (const_int 32 [0x20])) 0)
                        (subreg:SI (reg:DI 111 [ x ]) 0))
                    (const_int 16 [0x10]))
                (subreg:SI (zero_extract:DI (reg:DI 111 [ x ])
                        (const_int 32 [0x20])
                        (const_int 32 [0x20])) 0))
            (subreg:SI (reg:DI 111 [ x ]) 0))) -1
     (nil))
during RTL pass: reload
<source>:9:1: internal compiler error: in extract_insn, at recog.cc:2882
0x228dd45 diagnostic_context::diagnostic_impl(rich_location*,
diagnostic_metadata const*, diagnostic_option_id, char const*, __va_list_tag
(*) [1], diagnostic_t)
        ???:0
0x229f296 internal_error(char const*, ...)
        ???:0
0x7d44da fancy_abort(char const*, int, char const*)
        ???:0
0x7aabdd _fatal_insn(char const*, rtx_def const*, char const*, int, char
const*)
        ???:0
0x7aabff _fatal_insn_not_found(rtx_def const*, char const*, int, char const*)
        ???:0
0xdcb2e5 ira_remove_insn_scratches(rtx_insn*, bool, _IO_FILE*, rtx_def*
(*)(rtx_def*))
        ???:0
0xe0af5f lra_emit_move(rtx_def*, rtx_def*)
        ???:0
0xe20516 lra_constraints(bool)
        ???:0
0xe0da32 lra(_IO_FILE*, int)
        ???:0
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.


The input needs to be in a "Q" register, and is clobbered.  The output
needs to be in "qm", which may be in the same register as the input.

The problem is that the "input is clobbered" is expressed using a dummy output
operand, but there's no way to tell GCC that it may overlap with the desired
output.
Nor is there a way to make the dummy output optional.

So I tried to give it the wildcard "X" constraint to come as close to "you
don't need a register at all" as possible, and kaboom.

FWIW (I know the bug-reporting instructions say don't bother, but I poked
around a bit for my own interest), the ICE goes away if:
- I remove either constraint alternative (i.e. "=X" works without ",Q"), or
- I replace "=X,Q" with "=gfyxvk,Q".

Reply via email to