Bug 82931 - Missing Optimization for Bit-Transfer
Summary: Missing Optimization for Bit-Transfer
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 14.0
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2017-11-10 08:00 UTC by Wilhelm M
Modified: 2023-05-25 18:09 UTC (History)
1 user (show)

See Also:
Host:
Target: avr
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-01-15 00:00:00


Attachments
Minimum complete verifying example (237 bytes, text/x-csrc)
2017-11-10 08:00 UTC, Wilhelm M
Details
Minimum complete verifying example (241 bytes, text/x-csrc)
2017-11-10 08:23 UTC, Wilhelm M
Details
Valid C++ test case (202 bytes, text/plain)
2018-01-15 13:17 UTC, Georg-Johann Lay
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Wilhelm M 2017-11-10 08:00:24 UTC
Created attachment 42574 [details]
Minimum complete verifying example

The attached example produces optimal code for the AVR-target: it uses the bst/bld assembler instructions. But this is only true for bit 0 (least significant) in an uint8_t type. If the same instruction sequence is used to transfer bit 1...7 less optimal code is generated.

This is unlogical to some respect since the backend recognizes the special case for bit 0, so it should be possible to use the very same optimization for other bits.

The same holds true if one used another datatype such as uint16_t and greater. No optimization takes place.
Comment 1 Wilhelm M 2017-11-10 08:02:51 UTC
Should compile with -Os to reproduce the result.
Comment 2 Wilhelm M 2017-11-10 08:23:41 UTC
Created attachment 42575 [details]
Minimum complete verifying example
Comment 3 Georg-Johann Lay 2018-01-15 13:17:17 UTC
Created attachment 43134 [details]
Valid C++ test case

Confirmed for current trunk and the attached test case with

$ avr-g++ pr82931.cc -Os -mmcu=avr4 -fdump-rtl-combine-details && cat pr82931.cc.265r.combine

The patterns are just getting too complicated due to the involved MEMs:

Failed to match this instruction:
(set (zero_extract:QI (mem:QI (reg/v/f:HI 50 [ dst ]) [0 *dst_11(D)+0 S1 A8])
        (const_int 1 [0x1])
        (const_int 4 [0x4]))
    (lshiftrt:QI (reg:QI 52)
        (const_int 4 [0x4])))

Note that the avr BE provides zero_extract, but not with MEM operands:

;; Insert bit $2.$3 into $0.$1
(define_insn "*insv.shiftrt"
  [(set (zero_extract:QI (match_operand:QI 0 "register_operand"    "+r")
                         (const_int 1)
                         (match_operand:QI 1 "const_0_to_7_operand" "n"))
        (any_shiftrt:QI (match_operand:QI 2 "register_operand"      "r")
                        (match_operand:QI 3 "const_0_to_7_operand"  "n")))]
  ""
  "bst %2,%3\;bld %0,%1"
  ...

Adding versions with MEM operand would explode the BEs complexity, and such patches are usually rejected because of that.

Instead, insn combiner should try versions that use the MEMs as a split point and try REGs instead.
Comment 4 Georg-Johann Lay 2018-01-15 13:26:06 UTC
As lined out in comment #3, this is a middle-end flaw in insn combine:  For merge1 it should use MEM as split-points.  For merge2 it doesn't even recognize that the expression is a bit-insertion.
Comment 5 GCC Commits 2023-05-25 17:07:07 UTC
The master branch has been updated by Georg-Johann Lay <gjl@gcc.gnu.org>:

https://gcc.gnu.org/g:ff0a6900700636ac4c7f40b88490a20d19a68db3

commit r14-1244-gff0a6900700636ac4c7f40b88490a20d19a68db3
Author: Georg-Johann Lay <avr@gjlay.de>
Date:   Thu May 25 19:02:34 2023 +0200

    target/82931: Make a pattern more generic to match more bit-transfers.
    
    There is already a pattern in avr.md that matches single-bit transfers
    from one register to another one, but it only handled bit 0 of 8-bit
    registers.  This change makes that pattern more generic so it matches
    more of similar single-bit transfers.
    
    gcc/
            PR target/82931
            * config/avr/avr.md (*movbitqi.0): Rename to *movbit<mode>.0-6.
            Handle any bit position and use mode QISI.
            * config/avr/avr.cc (avr_rtx_costs_1) [IOR]: Return a cost
            of 2 insns for bit-transfer of respective style.
    
    gcc/testsuite/
            PR target/82931
            * gcc.target/avr/pr82931.c: New test.
Comment 6 GCC Commits 2023-05-25 17:25:49 UTC
The releases/gcc-13 branch has been updated by Georg-Johann Lay <gjl@gcc.gnu.org>:

https://gcc.gnu.org/g:a499ab08d18eff4ca9c079cafaee0708d2bcbf20

commit r13-7377-ga499ab08d18eff4ca9c079cafaee0708d2bcbf20
Author: Georg-Johann Lay <avr@gjlay.de>
Date:   Thu May 25 19:02:34 2023 +0200

    target/82931: Make a pattern more generic to match more bit-transfers.
    
    There is already a pattern in avr.md that matches single-bit transfers
    from one register to another one, but it only handled bit 0 of 8-bit
    registers.  This change makes that pattern more generic so it matches
    more of similar single-bit transfers.
    
    gcc/
            PR target/82931
            * config/avr/avr.md (*movbitqi.0): Rename to *movbit<mode>.0-6.
            Handle any bit position and use mode QISI.
            * config/avr/avr.cc (avr_rtx_costs_1) [IOR]: Return a cost
            of 2 insns for bit-transfer of respective style.
    
    gcc/testsuite/
            PR target/82931
            * gcc.target/avr/pr82931.c: New test.
Comment 7 GCC Commits 2023-05-25 17:46:03 UTC
The releases/gcc-12 branch has been updated by Georg-Johann Lay <gjl@gcc.gnu.org>:

https://gcc.gnu.org/g:4d39f68b891ed2ac7aca5ef24119f50976b84c22

commit r12-9654-g4d39f68b891ed2ac7aca5ef24119f50976b84c22
Author: Georg-Johann Lay <avr@gjlay.de>
Date:   Thu May 25 19:02:34 2023 +0200

    target/82931: Make a pattern more generic to match more bit-transfers.
    
    There is already a pattern in avr.md that matches single-bit transfers
    from one register to another one, but it only handled bit 0 of 8-bit
    registers.  This change makes that pattern more generic so it matches
    more of similar single-bit transfers.
    
    gcc/
            PR target/82931
            * config/avr/avr.md (*movbitqi.0): Rename to *movbit<mode>.0-6.
            Handle any bit position and use mode QISI.
            * config/avr/avr.cc (avr_rtx_costs_1) [IOR]: Return a cost
            of 2 insns for bit-transfer of respective style.
    
    gcc/testsuite/
            PR target/82931
            * gcc.target/avr/pr82931.c: New test.
Comment 8 Georg-Johann Lay 2023-05-25 18:09:31 UTC
Should work in v12.4 and v13.2+.