builtin-arith-overflow-3 has been failing on bfin-elf for a while. I've had a workaround installed on the tester for a few months and I finally got some time to dig into it over the weekend.

Ultimately I was able to nail the problem down to the representation of the rotate left by one position instruction.  I'm actually quite happy with that result as I was briefly worried it was a deeper problem in combine.

Essentially we're trying to synthesize a DImode shift using an SImode rotates through CC.  The key backend insn looks like:
(define_insn "rol_one"
  [(set (match_operand:SI 0 "register_operand" "+d")
        (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 1))
                (zero_extend:SI (reg:BI REG_CC))))
   (set (reg:BI REG_CC)
        (zero_extract:BI (match_dup 1) (const_int 31) (const_int 0)))]
  ""
  "%0 = ROT %1 BY 1%!"
  [(set_attr "type" "dsp32shiftimm")])

What the 2nd set in the pattern wants to do is indicate that CC is set to the high bit from operand 1.  But the RTL pattern is completely bogus as it's asking for a 31 bit wide field starting at offset 0, which is just silly for BImode.  That bogus representation led combine to do some "unexpected" transformations.

The obvious fix is to use (const_int 1) (const_int 31) in the 2nd set.  That indicates we want one bit starting at position 31.

With that pattern fixed, bfin returns to a normal state without needing my workaround.

Installed on the trunk,
Jeff


commit 8d331aab65488b3998bd106205bbe6cab5df31b5
Author: Jeff Law <jeffreya...@gmail.com>
Date:   Sun Apr 10 23:02:48 2022 -0400

    [committed] Minor bfin codegen bugfix
    
    gcc/
            * config/bfin/bfin.md (rol_one): Fix pattern to indicate the
            sign bit of the source ends up in CC.

diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 0e44653d7cb..56b24726bc2 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -1741,7 +1741,7 @@
        (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") 
(const_int 1))
                (zero_extend:SI (reg:BI REG_CC))))
    (set (reg:BI REG_CC)
-       (zero_extract:BI (match_dup 1) (const_int 31) (const_int 0)))]
+       (zero_extract:BI (match_dup 1) (const_int 1) (const_int 31)))]
   ""
   "%0 = ROT %1 BY 1%!"
   [(set_attr "type" "dsp32shiftimm")])

Reply via email to