Improve do_store_flag for comparing single bit against that bit
This is a case which I noticed while working on the previous patch. Sometimes we end up with `a == CST` instead of comparing against 0. This happens in the following code: ``` unsigned f(unsigned t) { if (t & ~(1<<30)) __builtin_unreachable(); t ^= (1<<30); return t != 0; } ``` We should handle the case where the nonzero bits is the same as the comparison operand. Changes from v1: * v2: Updated for the bit extraction changes. OK? Bootstrapped and tested on x86_64-linux-gnu. gcc/ChangeLog: * expr.cc (do_store_flag): Improve for single bit testing not against zero but against that single bit.
This commit is contained in:
parent
908e5ab5c1
commit
6cf856f873
1 changed files with 8 additions and 3 deletions
11
gcc/expr.cc
11
gcc/expr.cc
|
@ -13159,12 +13159,15 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
|
|||
than an scc insn even if we have it. */
|
||||
|
||||
if ((code == NE || code == EQ)
|
||||
&& integer_zerop (arg1)
|
||||
&& (integer_zerop (arg1)
|
||||
|| integer_pow2p (arg1))
|
||||
&& (TYPE_PRECISION (ops->type) != 1 || TYPE_UNSIGNED (ops->type)))
|
||||
{
|
||||
wide_int nz = tree_nonzero_bits (arg0);
|
||||
|
||||
if (wi::popcount (nz) == 1)
|
||||
if (wi::popcount (nz) == 1
|
||||
&& (integer_zerop (arg1)
|
||||
|| wi::to_wide (arg1) == nz))
|
||||
{
|
||||
tree op0;
|
||||
int bitnum;
|
||||
|
@ -13182,7 +13185,9 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
|
|||
op0 = arg0;
|
||||
bitnum = wi::exact_log2 (nz);
|
||||
}
|
||||
enum tree_code tcode = code == NE ? NE_EXPR : EQ_EXPR;
|
||||
enum tree_code tcode = EQ_EXPR;
|
||||
if ((code == NE) ^ !integer_zerop (arg1))
|
||||
tcode = NE_EXPR;
|
||||
|
||||
type = lang_hooks.types.type_for_mode (mode, unsignedp);
|
||||
return expand_single_bit_test (loc, tcode,
|
||||
|
|
Loading…
Add table
Reference in a new issue