[Bug rtl-optimization/35232] [4.3 regression] ICE in fp-int-convert-double.c at -O2

rsandifo at nildram dot co dot uk gcc-bugzilla@gcc.gnu.org
Sun Feb 17 22:13:00 GMT 2008



------- Comment #2 from rsandifo at nildram dot co dot uk  2008-02-17 22:13 -------
Subject: Re:  [4.3 regression] ICE in fp-int-convert-double.c at -O2

"ubizjak at gmail dot com" <gcc-bugzilla@gcc.gnu.org> writes:
> IMO is a bit suspicious that FP<->int conversions in mips.md operate on both FP
> operands, i.e:
>
> (define_insn "fix_truncdfsi2_insn"
>   [(set (match_operand:SI 0 "register_operand" "=f")
>         (fix:SI (match_operand:DF 1 "register_operand" "f")))]
>
> ...and similar patterns... , as well as:
>
> (define_insn "floatsidf2"
>   [(set (match_operand:DF 0 "register_operand" "=f")
>         (float:DF (match_operand:SI 1 "register_operand" "f")))]
>
> ...and similar patterns.
>
> One would expect a constraint that describes integer regs for output
> operand in the former case and integer regs for input operand in the
> later case.

I don't see why.  The MIPS insns in question operate on FP regs only.
"f" just denotes a class of register: it doesn't indicate an FP mode.

Anyway, it was indeed a reload inheritance bug.  We have an insn:

(insn 1749 1748 1750 193
../../../gcc/gcc/testsuite/gcc.dg/torture/fp-int-conver
t-double.c:12 (set (reg:SI 1475 [ ivout.331+-3 ])
        (zero_extend:SI (reg:QI 2209 [ ivout ]))) 147
{*zero_extendqisi2_mips16e
} (expr_list:REG_DEAD (reg:QI 2209 [ ivout ])
        (nil)))

and MIPS16 zero extensions require the input operand to match the output.
The insn gets the following reload:

Reloads for insn # 1749
Reload 0: reload_in (QI) = (reg:QI 2 $2 [orig:2209 ivout ] [2209])
        reload_out (SI) = (reg:SI 1475 [ ivout.331+-3 ])
        M16_REGS, RELOAD_OTHER (opnum = 0)
        reload_in_reg: (reg:QI 2 $2 [orig:2209 ivout ] [2209])
        reload_out_reg: (reg:SI 1475 [ ivout.331+-3 ])
        reload_reg_rtx: (reg:QI 2 $2 [orig:2209 ivout ] [2209])

Note that the reload_reg_rtx is QImode.  This is valid, because
(reg:QI 2) and (reg:SI 2) occupy the same number of registers
(and the code that chose (reg:QI 2) did check this).  But we
then record inheritance information as though we had a
(reg:SI 1475) <- (reg:QI 2) copy, and get confused later when
we expect the source to have SImode instead of QImode.

You can see the same thing in a wrong-code scenario with this
32-bit MIPS testcase:

--------------------------------------------------------------------
__attribute__((nomips16)) unsigned int
f1 (unsigned long long x)
{
  unsigned int r;
  asm ("# %0" : "=a" (r) : "0" (x));
  asm ("# %0" : "=h" (r) : "0" (r));
  return r;
}

__attribute__((nomips16)) unsigned int
f2 (unsigned long long x)
{
  unsigned int r;
  asm ("# %0" : "=a" (r) : "0" (x));
  asm ("# %0" : "=l" (r) : "0" (r));
  return r;
}

int
main (void)
{
  return f1 (4) != 4 || f2 (4) != 4;
}
--------------------------------------------------------------------

(one function for each endianness).  Here we have an in-out reload
with a 64-bit input (x) and a 32-bit output (r), so the reload register
itself is 64 bits wide.  emit_output_reload_insns correctly adjusts
the reload register for the output mode, but we record inheritance
as though the copy used an unadjusted register.  In other words,
we effectively record a 64-bit-to-32-bit copy instead of a 32-bit copy.
Despite the mode mismatch, we fluke correct output for one endianness,
but we get the wrong half of the register with the other endianness.

I'm testing a patch.

Richard


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35232



More information about the Gcc-bugs mailing list