From 146aef0b3998e76f16c3ab8255d1caa3dcb4c870 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 21 Jun 2011 18:25:57 +0200 Subject: [PATCH] re PR middle-end/49489 (gcc.c-torture/execute/builtin-bitops-1.c fails on x86_64-linux) PR middle-end/49489 * builtins.c (expand_builtin_unop): Call expand_unop with 0 as unsignedp argument instead of 1 for clrsb_optab. (fold_builtin_bitop): Fix masking for width > HOST_BITS_PER_WIDE_INT and < 2 * HOST_BITS_PER_WIDE_INT. Optimize BUILT_IN_CLRSB*. (fold_builtin_1): Call fold_builtin_binop for BUILT_IN_CLRSB*. * optabs.c (widen_leading): Call widen_operand and expand_unop with 0 as unsignedp argument instead of 1 for clrsb_optab. (expand_unop): Subtract difference of mode sizes also for clrsb_optab. From-SVN: r175265 --- gcc/ChangeLog | 13 +++++++++++++ gcc/builtins.c | 26 ++++++++++++++++++++++++-- gcc/optabs.c | 15 +++++++++------ 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0392ffc..db3b00b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2011-06-21 Jakub Jelinek + + PR middle-end/49489 + * builtins.c (expand_builtin_unop): Call expand_unop with 0 as + unsignedp argument instead of 1 for clrsb_optab. + (fold_builtin_bitop): Fix masking for width > HOST_BITS_PER_WIDE_INT + and < 2 * HOST_BITS_PER_WIDE_INT. Optimize BUILT_IN_CLRSB*. + (fold_builtin_1): Call fold_builtin_binop for BUILT_IN_CLRSB*. + * optabs.c (widen_leading): Call widen_operand and expand_unop + with 0 as unsignedp argument instead of 1 for clrsb_optab. + (expand_unop): Subtract difference of mode sizes also for + clrsb_optab. + 2011-06-21 Georg-Johann Lay * config/avr/avr.md (*jcindirect_jump): Fix build warning. diff --git a/gcc/builtins.c b/gcc/builtins.c index 8fc5ac3..5a3835f 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -4578,7 +4578,7 @@ expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target, /* Compute op, into TARGET if possible. Set TARGET to wherever the result comes back. */ target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))), - op_optab, op0, target, 1); + op_optab, op0, target, op_optab != clrsb_optab); gcc_assert (target); return convert_to_mode (target_mode, target, 0); @@ -7265,7 +7265,8 @@ fold_builtin_bitop (tree fndecl, tree arg) { hi = TREE_INT_CST_HIGH (arg); if (width < 2 * HOST_BITS_PER_WIDE_INT) - hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT)); + hi &= ~((unsigned HOST_WIDE_INT) (-1) + << (width - HOST_BITS_PER_WIDE_INT)); } else { @@ -7303,6 +7304,26 @@ fold_builtin_bitop (tree fndecl, tree arg) result = width; break; + CASE_INT_FN (BUILT_IN_CLRSB): + if (width > HOST_BITS_PER_WIDE_INT + && (hi & ((unsigned HOST_WIDE_INT) 1 + << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0) + { + hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1) + << (width - HOST_BITS_PER_WIDE_INT - 1)); + lo = ~lo; + } + else if (width <= HOST_BITS_PER_WIDE_INT + && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0) + lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1)); + if (hi != 0) + result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT; + else if (lo != 0) + result = width - floor_log2 (lo) - 2; + else + result = width - 1; + break; + CASE_INT_FN (BUILT_IN_POPCOUNT): result = 0; while (lo) @@ -9737,6 +9758,7 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore) CASE_INT_FN (BUILT_IN_FFS): CASE_INT_FN (BUILT_IN_CLZ): CASE_INT_FN (BUILT_IN_CTZ): + CASE_INT_FN (BUILT_IN_CLRSB): CASE_INT_FN (BUILT_IN_POPCOUNT): CASE_INT_FN (BUILT_IN_PARITY): return fold_builtin_bitop (fndecl, arg0); diff --git a/gcc/optabs.c b/gcc/optabs.c index 7448450..969d5cf 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -1,7 +1,7 @@ /* Expand the basic unary and binary arithmetic operations, for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -2350,8 +2350,10 @@ widen_leading (enum machine_mode mode, rtx op0, rtx target, optab unoptab) if (target == 0) target = gen_reg_rtx (mode); - xop0 = widen_operand (op0, wider_mode, mode, true, false); - temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, true); + xop0 = widen_operand (op0, wider_mode, mode, + unoptab != clrsb_optab, false); + temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, + unoptab != clrsb_optab); if (temp != 0) temp = expand_binop (wider_mode, sub_optab, temp, GEN_INT (GET_MODE_BITSIZE (wider_mode) @@ -3075,8 +3077,9 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, unsignedp); /* If we are generating clz using wider mode, adjust the - result. */ - if (unoptab == clz_optab && temp != 0) + result. Similarly for clrsb. */ + if ((unoptab == clz_optab || unoptab == clrsb_optab) + && temp != 0) temp = expand_binop (wider_mode, sub_optab, temp, GEN_INT (GET_MODE_BITSIZE (wider_mode) - GET_MODE_BITSIZE (mode)), -- 2.7.4