so we just call into the folder and expand its result. */
if ((code == NE || code == EQ)
- && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
- && integer_pow2p (TREE_OPERAND (arg0, 1))
+ && integer_zerop (arg1)
&& (TYPE_PRECISION (ops->type) != 1 || TYPE_UNSIGNED (ops->type)))
{
- tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
- return expand_expr (fold_single_bit_test (loc,
- code == NE ? NE_EXPR : EQ_EXPR,
- arg0, arg1, type),
- target, VOIDmode, EXPAND_NORMAL);
+ gimple srcstmt = get_def_for_expr (arg0, BIT_AND_EXPR);
+ if (srcstmt
+ && integer_pow2p (gimple_assign_rhs2 (srcstmt)))
+ {
+ enum tree_code tcode = code == NE ? NE_EXPR : EQ_EXPR;
+ tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
+ tree temp = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg1),
+ gimple_assign_rhs1 (srcstmt),
+ gimple_assign_rhs2 (srcstmt));
+ temp = fold_single_bit_test (loc, tcode, temp, arg1, type);
+ if (temp)
+ return expand_expr (temp, target, VOIDmode, EXPAND_NORMAL);
+ }
}
if (! get_subtarget (target)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int foo(long long a)
+{
+ if (a & (long long) 0x400)
+ return 1;
+ return 0;
+}
+
+/* { dg-final { scan-assembler "andl" { target i?86-*-linux* x86_64-*-linux* } } } " */
+/* { dg-final { scan-assembler-not "setne" { target i?86-*-linux* x86_64-*-linux* } } }" */
+/* { dg-final { scan-assembler "and" { target arm*-*-* } } }" */
+/* { dg-final { scan-assembler-not "moveq" { target arm*-*-* } } }" */