[Bug middle-end/82089] New: emit_cstore sign-extends BImode result for STORE_FLAG_VALUE == 1
vries at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Sun Sep 3 08:58:00 GMT 2017
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. ]
More information about the Gcc-bugs
mailing list