VAX: Handle constant 0 with QMATH DImode add/sub
authorMaciej W. Rozycki <macro@linux-mips.org>
Sun, 13 Dec 2020 20:46:17 +0000 (20:46 +0000)
committerMaciej W. Rozycki <macro@linux-mips.org>
Sun, 13 Dec 2020 20:46:17 +0000 (20:46 +0000)
Handle constant 0 passed to the QMATH DImode add/sub handler such as
with:

#2  0x0000000011d409b0 in gen_adddi3 (operand0=0x7ffff5c0a128,
    operand1=0x7ffff5c60480, operand2=0x7ffff5c60470)
    at .../gcc/config/vax/vax.md:755
755   "vax_expand_addsub_di_operands (operands, PLUS); DONE;")
(gdb) pr operand0
(reg:DI 31)
(gdb) pr operand1
(const_int 0 [0])
(gdb) pr operand2
(const_int -1 [0xffffffffffffffff])
(gdb)

causing an assertion in `vax_expand_addsub_di_operands':

      gcc_assert (operands[1] != const0_rtx || code == MINUS);

to trigger:

during RTL pass: expand
.../gcc/testsuite/gcc.c-torture/compile/sync-1.c: In function 'test_op_ignore':
.../gcc/testsuite/gcc.c-torture/compile/sync-1.c:33:10: internal compiler error: in vax_expand_addsub_di_operands, at config/vax/vax.c:2080
0x11815003 vax_expand_addsub_di_operands(rtx_def**, rtx_code)
.../gcc/config/vax/vax.c:2080
0x11d409af gen_adddi3(rtx_def*, rtx_def*, rtx_def*)
.../gcc/config/vax/vax.md:755
0x10ea2763 rtx_insn* insn_gen_fn::operator()<rtx_def*, rtx_def*, rtx_def*>(rtx_def*, rtx_def*, rtx_def*) const
.../gcc/recog.h:304
0x10f7fc8f maybe_gen_insn(insn_code, unsigned int, expand_operand*)
.../gcc/optabs.c:7402
0x10f67f8b expand_binop_directly
.../gcc/optabs.c:1122
0x10f684cf expand_binop(machine_mode, optab_tag, rtx_def*, rtx_def*, rtx_def*, int, optab_methods)
.../gcc/optabs.c:1209
0x10f6fb4f expand_unop(machine_mode, optab_tag, rtx_def*, rtx_def*, int)
.../gcc/optabs.c:3013
0x10f6c493 expand_simple_unop(machine_mode, rtx_code, rtx_def*, rtx_def*, int)
.../gcc/optabs.c:2200
0x10f7e2f3 expand_atomic_fetch_op(rtx_def*, rtx_def*, rtx_def*, rtx_code, memmodel, bool)
.../gcc/optabs.c:7021
0x107f7523 expand_builtin_sync_operation
.../gcc/builtins.c:7605
0x107ff547 expand_builtin(tree_node*, rtx_def*, rtx_def*, machine_mode, int)
.../gcc/builtins.c:9430
0x10acda63 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool)
.../gcc/expr.c:11249
0x10abeb9f expand_expr_real(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool)
.../gcc/expr.c:8486
0x1085606b expand_expr
.../gcc/expr.h:282
0x1086157f expand_call_stmt
.../gcc/cfgexpand.c:2709
0x10865ab7 expand_gimple_stmt_1
.../gcc/cfgexpand.c:3713
0x108662fb expand_gimple_stmt
.../gcc/cfgexpand.c:3877
0x10870387 expand_gimple_basic_block
.../gcc/cfgexpand.c:5918
0x10872b6b execute
.../gcc/cfgexpand.c:6602
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
compiler exited with status 1
FAIL: gcc.c-torture/compile/sync-1.c   -O0  (internal compiler error)

causing numerous failures in regression testing.

While requesting an addition operation to be produced for the constant
operands of 0 and -1 may seem silly, technically there is nothing wrong
with it, and non-QMATH code (as with the `-mno-qmath' option) has no
issues with that, so neither should QMATH code.  This operation will
normally be folded in later passes anyway.

Observe then, that adding or subtracting constant 0 amounts to a move
(and we even have a machine instruction available to do that with a
single operation) so handle the case explicitly, swapping the addends if
so required, removing the assertion failure and along with that 70 test
suite failures like:

FAIL: gcc.c-torture/compile/sync-1.c   -O0  (internal compiler error)
FAIL: gcc.c-torture/compile/sync-1.c   -O0  fetch_and_nand (test for warnings, line )
FAIL: gcc.c-torture/compile/sync-1.c   -O0  nand_and_fetch (test for warnings, line )
FAIL: gcc.c-torture/compile/sync-1.c   -O0  (test for excess errors)
FAIL: gcc.c-torture/compile/sync-2.c   -O0  (internal compiler error)
FAIL: gcc.c-torture/compile/sync-2.c   -O0   (test for warnings, line )
FAIL: gcc.c-torture/compile/sync-2.c   -O0  (test for excess errors)
FAIL: gcc.c-torture/compile/sync-3.c   -O0  (internal compiler error)
FAIL: gcc.c-torture/compile/sync-3.c   -O0   (test for warnings, line )
FAIL: gcc.c-torture/compile/sync-3.c   -O0  (test for excess errors)

and similarly across all the other optimization levels and compilation
options covered.

gcc/
* config/vax/vax.c (vax_expand_addsub_di_operands): Handle the
addition or subtraction of 0.

gcc/config/vax/vax.c

index 57408a57adc7f18e4eb3b6c98a28473ab05a2d91..2274cce6a5b9ebf49cf125be213bd628bc174550 100644 (file)
@@ -2066,6 +2066,19 @@ vax_expand_addsub_di_operands (rtx * operands, enum rtx_code code)
       else
        operands[2] = fixup_mathdi_operand (operands[2], DImode);
 
+      /* If we are adding or subtracting 0, then this is a move.  */
+      if (code == PLUS && operands[1] == const0_rtx)
+       {
+         temp = operands[2];
+         operands[2] = operands[1];
+         operands[1] = temp;
+       }
+      if (operands[2] == const0_rtx)
+       {
+         emit_move_insn (operands[0], operands[1]);
+         return;
+       }
+
       /* If we are subtracting not from ourselves [d = a - b], and because the
         carry ops are two operand only, we would need to do a move prior to
         the subtract.  And if d == b, we would need a temp otherwise