https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82089

            Bug ID: 82089
           Summary: emit_cstore sign-extends BImode result for
                    STORE_FLAG_VALUE == 1
           Product: gcc
           Version: 8.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vries at gcc dot gnu.org
  Target Milestone: ---

Say that in bfin.md, we redefine cstoresi4 in the following way:
... 
(define_expand "cstoresi4"
  [(set (match_operand:BI 0 "")
        (match_operator:BI 1 "ordered_comparison_operator"
                       [(match_operand:SI 2 "register_operand" "")
                        (match_operand:SI 3 "reg_or_const_int_operand" "")]))]
  "" {})
...

Then for a test-case:
...
int
foo (int a, int b)
{
  return a == b;
}
...

compiled like this:
...
$ gcc test.c -S -O2 -fdump-rtl-all-all
...

we expand into this:
...
(insn 7 6 8 (set (reg:BI 62)
        (ne:BI (reg/v:SI 58 [ aD.1438 ])
            (reg/v:SI 59 [ bD.1439 ]))) "test.c":4 -1
     (nil))

(insn 8 7 9 (set (reg:SI 61)
        (ashift:SI (subreg:SI (reg:BI 62) 0)
            (const_int 31 [0x1f]))) "test.c":4 -1
     (nil))

(insn 9 8 10 (set (reg:SI 61)
        (ashiftrt:SI (reg:SI 61)
            (const_int 31 [0x1f]))) "test.c":4 -1
     (nil))

(insn 10 9 11 (set (reg:SI 57 [ <retval> ])
        (reg:SI 61)) "test.c":4 -1
     (nil))
...
before ICE-ing in vregs because insn 7 does not match any insn.

Note that we sign-extend the BImode result of insn 7, using insn 8 and 9.

The sign-extend is generated here in emit_cstore:
...
  /* If we are converting to a wider mode, first convert to
     INT_TARGET_MODE, then normalize.  This produces better combining
     opportunities on machines that have a SIGN_EXTRACT when we are
     testing a single bit.  This mostly benefits the 68k.

     If STORE_FLAG_VALUE does not have the sign bit set when
     interpreted in MODE, we can do this conversion as unsigned, which
     is usually more efficient.  */
  if (GET_MODE_SIZE (int_target_mode) > GET_MODE_SIZE (result_mode))
    {
      convert_move (target, subtarget,
                    val_signbit_known_clear_p (result_mode,
                                               STORE_FLAG_VALUE));
      op0 = target;
      result_mode = int_target_mode;
    }
...

We call
  val_signbit_known_clear_p (mode == BImode, val == 1)
which returns false, so then we call
  convert_move (to == reg:SI 61, from == reg:BI 62, unsignedp == false)
which generates the sign-extend because unsignedp == false.

Disregarding other STORE_FLAG_VALUES for the moment, the idea of the code is to
sign-extend if STORE_FLAG_VALUE is -1, and to zero-extend if STORE_FLAG_VALUE
is 1.

However, 1 and -1 are indistinguishable in BImode, so this happens to go the
sign-extend way. [ The comment mentions 68k, which has STORE_FLAG_VALUE -1, so
that might be reason it choose the sign-extend in this case. ]

Reply via email to