[Bug target/98683] New: Non-canonical compare produced with the VAX backend

macro@linux-mips.org gcc-bugzilla@gcc.gnu.org
Thu Jan 14 14:35:59 GMT 2021


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

            Bug ID: 98683
           Summary: Non-canonical compare produced with the VAX backend
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: macro@linux-mips.org
                CC: macro@linux-mips.org
  Target Milestone: ---
            Target: vax-*-netbsdelf

Due to how operands are presented to the `cbranch*' patterns a
non-canonical compare operation might be produced with reload that has
an immediate in its first input operand (and a non-immediate second input
operand, although forms with two immediate inputs have been also
observed).

This can be reproduced with the existing 20000422-1.c test case and the
`-O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer
-finline-functions' options, a set from the usual ones used with
regression testing:

(jump_insn 549 550 556 99 (set (pc)
        (if_then_else (ge (const_int 0 [0])
                (reg:SI 10 %r10 [orig:188 _138 ] [188]))
            (label_ref:SI 707)
            (pc))) ".../gcc/testsuite/gcc.c-torture/execute/20000422-1.c":21:27
521 {*cbranchsi4_ccn}
     (int_list:REG_BR_PROB 118111604 (nil))
 -> 707)

which gets split to:

(insn 1959 550 1960 99 (set (reg:CCN 16 %psl)
        (compare:CCN (const_int 0 [0])
            (reg:SI 10 %r10 [orig:188 _138 ] [188])))
".../gcc/testsuite/gcc.c-torture/execute/20000422-1.c":21:27 6 {*cmpsi_ccn}
     (nil))
(jump_insn 1960 1959 556 99 (set (pc)
        (if_then_else (ge (reg:CCN 16 %psl)
                (const_int 0 [0]))
            (label_ref 707)
            (pc))) ".../gcc/testsuite/gcc.c-torture/execute/20000422-1.c":21:27
535 {*branch_ccn}
     (int_list:REG_BR_PROB 118111604 (nil))
 -> 707)

and ultimately leads to:

#(insn 1959 550 1960 (set (reg:CCN 16 %psl)
#        (compare:CCN (const_int 0 [0])
#            (reg:SI 10 %r10 [orig:188 _138 ] [188])))
".../gcc/testsuite/gcc.c-torture/execute/20000422-1.c":21:27 6 {*cmpsi_ccn}
#     (nil))
        cmpl $0,%r10    # 1959  [c=6]  *cmpsi_ccn/1
#(jump_insn 1960 1959 556 (set (pc)
#        (if_then_else (ge (reg:CCN 16 %psl)
#                (const_int 0 [0]))
#            (label_ref 707)
#            (pc)))
".../gcc/testsuite/gcc.c-torture/execute/20000422-1.c":21:27 535 {*branch_ccn}
#     (expr_list:REG_DEAD (reg:CCN 16 %psl)
#        (int_list:REG_BR_PROB 118111604 (nil)))
# -> 707)
        jgeq .L73               # 1960  [c=26]  *branch_ccn

As observed here this is handled by the backend just fine, however causes
the less optimal CMPL instruction to be produced rather than TSTL that
has an implicit immediate zero second operand, which could be used if the
inputs were swapped.  This applies to both integer and FP operations.

Currently canonicalization requires that an immediate input operand to
to the compare operation has to come as the second one, however there is
no such requirement for the `cbranch*' patterns, so the fix would have to
be made in the backend, in the relevant splitters, presumably by swapping
the operands and using the reverse branch if an immediate is presented
as the first input operand.

Requiring the first input operand to `cbranch*' to be non-immediate by
means of a predicate results in yet worse code being produced as any
immediate used is then moved to a register by reload, so this would best
be avoided.


More information about the Gcc-bugs mailing list