From 9c4c8b7bbbef7569b2bc9dedece5352c48a8701d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 21 Oct 2016 17:39:25 +0200 Subject: [PATCH] re PR target/78057 (FAIL: gcc.target/i386/bmi-{4,5,6}.c) PR target/78057 * config/i386/i386.c: Include fold-const-call.h, tree-vrp.h and tree-ssanames.h. (ix86_fold_builtin): Fold IX86_BUILTIN_[LT]ZCNT{16,32,64} with INTEGER_CST argument. (ix86_gimple_fold_builtin): New function. (TARGET_GIMPLE_FOLD_BUILTIN): Define. * gcc.target/i386/pr78057.c: New test. From-SVN: r241411 --- gcc/ChangeLog | 8 ++ gcc/config/i386/i386.c | 104 ++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 3 + gcc/testsuite/gcc.target/i386/pr78057.c | 42 ++++++++++ 4 files changed, 157 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr78057.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 299ffe41a70..4d88ef755aa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2016-10-21 Jakub Jelinek + PR target/78057 + * config/i386/i386.c: Include fold-const-call.h, tree-vrp.h + and tree-ssanames.h. + (ix86_fold_builtin): Fold IX86_BUILTIN_[LT]ZCNT{16,32,64} + with INTEGER_CST argument. + (ix86_gimple_fold_builtin): New function. + (TARGET_GIMPLE_FOLD_BUILTIN): Define. + * dwarf2out.c (ranges_table): Change into vec *. (ranges_by_label): Change into vec *. (ranges_table_allocated, ranges_table_in_use, diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 618d9741f69..69ad339797c 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -77,6 +77,9 @@ along with GCC; see the file COPYING3. If not see #include "case-cfn-macros.h" #include "regrename.h" #include "dojump.h" +#include "fold-const-call.h" +#include "tree-vrp.h" +#include "tree-ssanames.h" /* This file should be included last. */ #include "target-def.h" @@ -33332,6 +33335,40 @@ ix86_fold_builtin (tree fndecl, int n_args, return build_real (type, inf); } + case IX86_BUILTIN_TZCNT16: + case IX86_BUILTIN_TZCNT32: + case IX86_BUILTIN_TZCNT64: + gcc_assert (n_args == 1); + if (TREE_CODE (args[0]) == INTEGER_CST) + { + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + tree arg = args[0]; + if (fn_code == IX86_BUILTIN_TZCNT16) + arg = fold_convert (short_unsigned_type_node, arg); + if (integer_zerop (arg)) + return build_int_cst (type, TYPE_PRECISION (TREE_TYPE (arg))); + else + return fold_const_call (CFN_CTZ, type, arg); + } + break; + + case IX86_BUILTIN_LZCNT16: + case IX86_BUILTIN_LZCNT32: + case IX86_BUILTIN_LZCNT64: + gcc_assert (n_args == 1); + if (TREE_CODE (args[0]) == INTEGER_CST) + { + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + tree arg = args[0]; + if (fn_code == IX86_BUILTIN_LZCNT16) + arg = fold_convert (short_unsigned_type_node, arg); + if (integer_zerop (arg)) + return build_int_cst (type, TYPE_PRECISION (TREE_TYPE (arg))); + else + return fold_const_call (CFN_CLZ, type, arg); + } + break; + default: break; } @@ -33344,6 +33381,70 @@ ix86_fold_builtin (tree fndecl, int n_args, return NULL_TREE; } +/* Fold a MD builtin (use ix86_fold_builtin for folding into + constant) in GIMPLE. */ + +bool +ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi) +{ + gimple *stmt = gsi_stmt (*gsi); + tree fndecl = gimple_call_fndecl (stmt); + gcc_checking_assert (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD); + int n_args = gimple_call_num_args (stmt); + enum ix86_builtins fn_code = (enum ix86_builtins) DECL_FUNCTION_CODE (fndecl); + tree decl = NULL_TREE; + tree arg0; + + switch (fn_code) + { + case IX86_BUILTIN_TZCNT32: + decl = builtin_decl_implicit (BUILT_IN_CTZ); + goto fold_tzcnt_lzcnt; + + case IX86_BUILTIN_TZCNT64: + decl = builtin_decl_implicit (BUILT_IN_CTZLL); + goto fold_tzcnt_lzcnt; + + case IX86_BUILTIN_LZCNT32: + decl = builtin_decl_implicit (BUILT_IN_CLZ); + goto fold_tzcnt_lzcnt; + + case IX86_BUILTIN_LZCNT64: + decl = builtin_decl_implicit (BUILT_IN_CLZLL); + goto fold_tzcnt_lzcnt; + + fold_tzcnt_lzcnt: + gcc_assert (n_args == 1); + arg0 = gimple_call_arg (stmt, 0); + if (TREE_CODE (arg0) == SSA_NAME && decl && gimple_call_lhs (stmt)) + { + int prec = TYPE_PRECISION (TREE_TYPE (arg0)); + /* If arg0 is provably non-zero, optimize into generic + __builtin_c[tl]z{,ll} function the middle-end handles + better. */ + if (!expr_not_equal_to (arg0, wi::zero (prec))) + return false; + + location_t loc = gimple_location (stmt); + gimple *g = gimple_build_call (decl, 1, arg0); + gimple_set_location (g, loc); + tree lhs = make_ssa_name (integer_type_node); + gimple_call_set_lhs (g, lhs); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign (gimple_call_lhs (stmt), NOP_EXPR, lhs); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; + } + break; + + default: + break; + } + + return false; +} + /* Make builtins to detect cpu type and features supported. NAME is the builtin name, CODE is the builtin code, and FTYPE is the function type of the builtin. */ @@ -50531,6 +50632,9 @@ ix86_addr_space_zero_address_valid (addr_space_t as) #undef TARGET_FOLD_BUILTIN #define TARGET_FOLD_BUILTIN ix86_fold_builtin +#undef TARGET_GIMPLE_FOLD_BUILTIN +#define TARGET_GIMPLE_FOLD_BUILTIN ix86_gimple_fold_builtin + #undef TARGET_COMPARE_VERSION_PRIORITY #define TARGET_COMPARE_VERSION_PRIORITY ix86_compare_version_priority diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fafdbfcf93b..0754aec5004 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2016-10-21 Jakub Jelinek + PR target/78057 + * gcc.target/i386/pr78057.c: New test. + * g++.dg/debug/dwarf2/constexpr-var-1.C: New test. 2016-10-21 Paul Thomas diff --git a/gcc/testsuite/gcc.target/i386/pr78057.c b/gcc/testsuite/gcc.target/i386/pr78057.c new file mode 100644 index 00000000000..493a53332bb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr78057.c @@ -0,0 +1,42 @@ +/* PR target/78057 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mbmi -mlzcnt -fdump-tree-optimized" } */ + +extern void link_error (void); + +int +foo (int x) +{ + if (__builtin_ia32_tzcnt_u16 (16) != 4 + || __builtin_ia32_tzcnt_u16 (0) != 16 + || __builtin_ia32_lzcnt_u16 (0x1ff) != 7 + || __builtin_ia32_lzcnt_u16 (0) != 16 + || __builtin_ia32_tzcnt_u32 (8) != 3 + || __builtin_ia32_tzcnt_u32 (0) != 32 + || __builtin_ia32_lzcnt_u32 (0x3fffffff) != 2 + || __builtin_ia32_lzcnt_u32 (0) != 32 +#ifdef __x86_64__ + || __builtin_ia32_tzcnt_u64 (4) != 2 + || __builtin_ia32_tzcnt_u64 (0) != 64 + || __builtin_ia32_lzcnt_u64 (0x1fffffff) != 35 + || __builtin_ia32_lzcnt_u64 (0) != 64 +#endif + ) + link_error (); + x += 2; + if (x == 0) + return 5; + return __builtin_ia32_tzcnt_u32 (x) + + __builtin_ia32_lzcnt_u32 (x) +#ifdef __x86_64__ + + __builtin_ia32_tzcnt_u64 (x) + + __builtin_ia32_lzcnt_u64 (x) +#endif + ; +} + +/* { dg-final { scan-tree-dump-not "link_error" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "__builtin_ia32_\[lt]zcnt" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_ctz " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_clz " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_ctzll " 1 "optimized" { target lp64 } } } */ -- 2.30.2