> No, the second follow-up was about moving the simplification to combine.c
> and guarding it with !WORD_REGISTER_OPERATIONS, or whatever other check
> you prefer, so that no undoing is necessary.

In fact the mere distribution of the SUBREG seems to be questionable, whatever 
the target.  For the testcase of PR58295, the redundant masking is eliminated 
because:

(insn 9 7 10 2 (set (reg:SI 120)
        (plus:SI (reg:SI 119)
            (const_int -48 [0xffffffffffffffd0]))) pr58295.c:8 5 {*arm_addsi3}
     (expr_list:REG_DEAD (reg:SI 119)
        (nil)))
(insn 10 9 11 2 (set (reg:SI 121)
        (and:SI (reg:SI 120)
            (const_int 255 [0xff]))) pr58295.c:8 80 {*arm_andsi3_insn}
     (expr_list:REG_DEAD (reg:SI 120)
        (nil)))
(insn 11 10 12 2 (set (reg:CC 100 cc)
        (compare:CC (reg:SI 121)
            (const_int 9 [0x9]))) pr58295.c:8 227 {*arm_cmpsi_insn}
     (expr_list:REG_DEAD (reg:SI 121)
        (nil)))

is combined into:

(set (reg:CC 100 cc)
    (compare:CC (plus:SI (reg:SI 119)
            (const_int -48 [0xffffffffffffffd0]))
        (const_int 9 [0x9])))

and then split, thanks to:

        case SUBREG:
          /* Check for the case where we are comparing A - C1 with C2, that is

               (subreg:MODE (plus (A) (-C1))) op (C2)

             with C1 a constant, and try to lift the SUBREG, i.e. to do the
             comparison in the wider mode.  One of the following two conditions
             must be true in order for this to be valid:

               1. The mode extension results in the same bit pattern being added
                  on both sides and the comparison is equality or unsigned.  As
                  C2 has been truncated to fit in MODE, the pattern can only be
                  all 0s or all 1s.

               2. The mode extension results in the sign bit being copied on
                  each side.

             The difficulty here is that we have predicates for A but not for
             (A - C1) so we need to check that C1 is within proper bounds so
             as to perturbate A as little as possible.  */

in simplify_comparison (and the SUBREG is generated from the AND by another 
case of simplify_comparison).  Distributing the SUBREG disables the code.

Therefore, I think that the best thing to do is to go back to Uros' original 
idea of distributing the SUBREG only within a PLUS or a MINUS:
  http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01682.html
The outer operation sort of guarantees that operating in this mode is OK for 
the target, so the transformation can be done unconditionally.  It could be 
also done in simplify-rtx.c instead of combine.c.

-- 
Eric Botcazou

Reply via email to