From: sayle Date: Tue, 26 Aug 2003 13:22:14 +0000 (+0000) Subject: * builtins.c (fold_builtin_bitop): New function to perform constant X-Git-Tag: upstream/4.9.2~77079 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=70fb4c079170fe4c00d0d6b7747c9a2ce822f9d1;p=platform%2Fupstream%2Flinaro-gcc.git * builtins.c (fold_builtin_bitop): New function to perform constant folding of ffs, clz, ctz, popcount and parity builtin functions and their long and long long variants (such as ffsl and ffsll). (fold_builtin): fold_builtin_bitop when appropriate. * simplify-rtx.c (simplify_unary_operation): Honor both CLZ_DEFINED_VALUE_AT_ZERO and CTZ_DEFINED_VALUE_AT_ZERO when evaluating clz and ctz at compile-time, for operands wider than HOST_WIDE_INT. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70806 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 147b68e..6c195ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2003-08-26 Roger Sayle + + * builtins.c (fold_builtin_bitop): New function to perform constant + folding of ffs, clz, ctz, popcount and parity builtin functions + and their long and long long variants (such as ffsl and ffsll). + (fold_builtin): fold_builtin_bitop when appropriate. + * simplify-rtx.c (simplify_unary_operation): Honor both + CLZ_DEFINED_VALUE_AT_ZERO and CTZ_DEFINED_VALUE_AT_ZERO when + evaluating clz and ctz at compile-time, for operands wider + than HOST_WIDE_INT. + 2003-08-26 Nathan Sidwell * builtins.c (build_function_call_expr): Don't set diff --git a/gcc/builtins.c b/gcc/builtins.c index fea2a15..227bb49 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -162,6 +162,7 @@ static tree fold_builtin_cabs (tree, tree, tree); static tree fold_builtin_trunc (tree); static tree fold_builtin_floor (tree); static tree fold_builtin_ceil (tree); +static tree fold_builtin_bitop (tree); /* Initialize mathematical constants for constant folding builtins. These constants need to be given to at least 160 bits precision. */ @@ -5770,6 +5771,114 @@ fold_builtin_ceil (tree exp) return fold_trunc_transparent_mathfn (exp); } +/* Fold function call to builtin ffs, clz, ctz, popcount and parity + and their long and long long variants (i.e. ffsl and ffsll). + Return NULL_TREE if no simplification can be made. */ + +static tree +fold_builtin_bitop (tree exp) +{ + tree fndecl = get_callee_fndecl (exp); + tree arglist = TREE_OPERAND (exp, 1); + tree arg; + + if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE)) + return NULL_TREE; + + /* Optimize for constant argument. */ + arg = TREE_VALUE (arglist); + if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg)) + { + HOST_WIDE_INT hi, width, result; + unsigned HOST_WIDE_INT lo; + tree type, t; + + type = TREE_TYPE (arg); + width = TYPE_PRECISION (type); + lo = TREE_INT_CST_LOW (arg); + + /* Clear all the bits that are beyond the type's precision. */ + if (width > HOST_BITS_PER_WIDE_INT) + { + 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)); + } + else + { + hi = 0; + if (width < HOST_BITS_PER_WIDE_INT) + lo &= ~((unsigned HOST_WIDE_INT) (-1) << width); + } + + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_FFS: + case BUILT_IN_FFSL: + case BUILT_IN_FFSLL: + if (lo != 0) + result = exact_log2 (lo & -lo) + 1; + else if (hi != 0) + result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1; + else + result = 0; + break; + + case BUILT_IN_CLZ: + case BUILT_IN_CLZL: + case BUILT_IN_CLZLL: + if (hi != 0) + result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT; + else if (lo != 0) + result = width - floor_log2 (lo) - 1; + else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result)) + result = width; + break; + + case BUILT_IN_CTZ: + case BUILT_IN_CTZL: + case BUILT_IN_CTZLL: + if (lo != 0) + result = exact_log2 (lo & -lo); + else if (hi != 0) + result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi); + else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result)) + result = width; + break; + + case BUILT_IN_POPCOUNT: + case BUILT_IN_POPCOUNTL: + case BUILT_IN_POPCOUNTLL: + result = 0; + while (lo) + result++, lo &= lo - 1; + while (hi) + result++, hi &= hi - 1; + break; + + case BUILT_IN_PARITY: + case BUILT_IN_PARITYL: + case BUILT_IN_PARITYLL: + result = 0; + while (lo) + result++, lo &= lo - 1; + while (hi) + result++, hi &= hi - 1; + result &= 1; + break; + + default: + abort(); + } + + t = build_int_2 (result, 0); + TREE_TYPE (t) = TREE_TYPE (exp); + return t; + } + + return NULL_TREE; +} + /* Used by constant folding to eliminate some builtin calls early. EXP is the CALL_EXPR of a call to a builtin function. */ @@ -6225,6 +6334,23 @@ fold_builtin (tree exp) case BUILT_IN_NEARBYINTL: return fold_trunc_transparent_mathfn (exp); + case BUILT_IN_FFS: + case BUILT_IN_FFSL: + case BUILT_IN_FFSLL: + case BUILT_IN_CLZ: + case BUILT_IN_CLZL: + case BUILT_IN_CLZLL: + case BUILT_IN_CTZ: + case BUILT_IN_CTZL: + case BUILT_IN_CTZLL: + case BUILT_IN_POPCOUNT: + case BUILT_IN_POPCOUNTL: + case BUILT_IN_POPCOUNTLL: + case BUILT_IN_PARITY: + case BUILT_IN_PARITYL: + case BUILT_IN_PARITYLL: + return fold_builtin_bitop (exp); + default: break; } diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 36a8585..919bea6 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -649,24 +649,23 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode, case CLZ: hv = 0; - if (h1 == 0) - lv = GET_MODE_BITSIZE (mode) - floor_log2 (l1) - 1; - else + if (h1 != 0) lv = GET_MODE_BITSIZE (mode) - floor_log2 (h1) - 1 - HOST_BITS_PER_WIDE_INT; + else if (l1 != 0) + lv = GET_MODE_BITSIZE (mode) - floor_log2 (l1) - 1; + else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, lv)) + lv = GET_MODE_BITSIZE (mode); break; case CTZ: hv = 0; - if (l1 == 0) - { - if (h1 == 0) - lv = GET_MODE_BITSIZE (mode); - else - lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1); - } - else + if (l1 != 0) lv = exact_log2 (l1 & -l1); + else if (h1 != 0) + lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1); + else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv)) + lv = GET_MODE_BITSIZE (mode); break; case POPCOUNT: