Ping. Thanks, Wei.
On Tue, Dec 17, 2013 at 11:34 AM, Wei Mi <w...@google.com> wrote: > Ping. > > Thanks, > Wei. > > On Mon, Dec 9, 2013 at 9:54 PM, Wei Mi <w...@google.com> wrote: >> Ping. >> >> Thanks, >> wei. >> >> On Sat, Nov 23, 2013 at 10:46 AM, Wei Mi <w...@google.com> wrote: >>> bootstrap and regression of the updated patch pass. >>> >>> On Sat, Nov 23, 2013 at 12:05 AM, Wei Mi <w...@google.com> wrote: >>>> On Thu, Nov 21, 2013 at 12:19 AM, Zdenek Dvorak >>>> <rakd...@iuuk.mff.cuni.cz> wrote: >>>>> Hi, >>>>> >>>>>> This patch works on the intrinsic calls handling issue in IVOPT >>>>>> mentioned here: >>>>>> http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01295.html >>>>>> >>>>>> In find_interesting_uses_stmt, it changes >>>>>> >>>>>> arg = expr >>>>>> __builtin_xxx (arg) >>>>>> >>>>>> to >>>>>> >>>>>> arg = expr; >>>>>> tmp = addr_expr (mem_ref(arg)); >>>>>> __builtin_xxx (tmp, ...) >>>>> >>>>> this looks a bit confusing (and wasteful) to me. It would make more sense >>>>> to >>>>> just record the argument as USE_ADDRESS and do the rewriting in >>>>> rewrite_use_address. >>>>> >>>>> Zdenek >>>> >>>> I updated the patch. The gimple changing part is now moved to >>>> rewrite_use_address. Add support for plain address expr in addition to >>>> reference expr in find_interesting_uses_address. >>>> >>>> bootstrap and testing is going on. >>>> >>>> 2013-11-22 Wei Mi <w...@google.com> >>>> >>>> * expr.c (expand_expr_addr_expr_1): Not to split TMR. >>>> (expand_expr_real_1): Ditto. >>>> * targhooks.c (default_builtin_has_mem_ref_p): Default >>>> builtin. >>>> * tree-ssa-loop-ivopts.c (builtin_has_mem_ref_p): New function. >>>> (rewrite_use_address): Add TMR for builtin. >>>> (find_interesting_uses_stmt): Special handling of builtins. >>>> * gimple-expr.c (is_gimple_address): Add handling of TMR. >>>> * gimple-expr.h (is_gimple_addressable): Ditto. >>>> * config/i386/i386.c (ix86_builtin_has_mem_ref_p): New target hook. >>>> (ix86_atomic_assign_expand_fenv): Ditto. >>>> (ix86_expand_special_args_builtin): Special handling of TMR for >>>> builtin. >>>> * target.def (builtin_has_mem_ref_p): New hook. >>>> * doc/tm.texi.in: Ditto. >>>> * doc/tm.texi: Generated. >>>> >>>> 2013-11-22 Wei Mi <w...@google.com> >>>> >>>> * gcc.dg/tree-ssa/ivopt_5.c: New test. >>>> >>>> Index: testsuite/gcc.dg/tree-ssa/ivopt_5.c >>>> =================================================================== >>>> --- testsuite/gcc.dg/tree-ssa/ivopt_5.c (revision 0) >>>> +++ testsuite/gcc.dg/tree-ssa/ivopt_5.c (revision 0) >>>> @@ -0,0 +1,21 @@ >>>> +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ >>>> +/* { dg-options "-O2 -m64 -fdump-tree-ivopts-details" } */ >>>> + >>>> +/* Make sure only one iv is selected after IVOPT. */ >>>> + >>>> +#include <x86intrin.h> >>>> +extern __m128i arr[], d[]; >>>> +void test (void) >>>> +{ >>>> + unsigned int b; >>>> + for (b = 0; b < 1000; b += 2) { >>>> + __m128i *p = (__m128i *)(&d[b]); >>>> + __m128i a = _mm_load_si128(&arr[4*b+3]); >>>> + __m128i v = _mm_loadu_si128(p); >>>> + v = _mm_xor_si128(v, a); >>>> + _mm_storeu_si128(p, v); >>>> + } >>>> +} >>>> + >>>> +/* { dg-final { scan-tree-dump-times "PHI <ivtmp" 1 "ivopts"} } */ >>>> +/* { dg-final { cleanup-tree-dump "ivopts" } } */ >>>> Index: targhooks.c >>>> =================================================================== >>>> --- targhooks.c (revision 204792) >>>> +++ targhooks.c (working copy) >>>> @@ -566,6 +566,13 @@ default_builtin_reciprocal (unsigned int >>>> } >>>> >>>> bool >>>> +default_builtin_has_mem_ref_p (int built_in_function ATTRIBUTE_UNUSED, >>>> + int i ATTRIBUTE_UNUSED) >>>> +{ >>>> + return false; >>>> +} >>>> + >>>> +bool >>>> hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false ( >>>> cumulative_args_t ca ATTRIBUTE_UNUSED, >>>> enum machine_mode mode ATTRIBUTE_UNUSED, >>>> Index: expr.c >>>> =================================================================== >>>> --- expr.c (revision 204792) >>>> +++ expr.c (working copy) >>>> @@ -7467,7 +7467,19 @@ expand_expr_addr_expr_1 (tree exp, rtx t >>>> tem = fold_build_pointer_plus (tem, TREE_OPERAND (exp, 1)); >>>> return expand_expr (tem, target, tmode, modifier); >>>> } >>>> + case TARGET_MEM_REF: >>>> + { >>>> + int old_cse_not_expected; >>>> + addr_space_t as >>>> + = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, >>>> 0)))); >>>> >>>> + result = addr_for_mem_ref (exp, as, true); >>>> + old_cse_not_expected = cse_not_expected; >>>> + cse_not_expected = true; >>>> + result = memory_address_addr_space (tmode, result, as); >>>> + cse_not_expected = old_cse_not_expected; >>>> + return result; >>>> + } >>>> case CONST_DECL: >>>> /* Expand the initializer like constants above. */ >>>> result = XEXP (expand_expr_constant (DECL_INITIAL (exp), >>>> @@ -9526,9 +9538,13 @@ expand_expr_real_1 (tree exp, rtx target >>>> = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, >>>> 0)))); >>>> enum insn_code icode; >>>> unsigned int align; >>>> + int old_cse_not_expected; >>>> >>>> op0 = addr_for_mem_ref (exp, as, true); >>>> + old_cse_not_expected = cse_not_expected; >>>> + cse_not_expected = true; >>>> op0 = memory_address_addr_space (mode, op0, as); >>>> + cse_not_expected = old_cse_not_expected; >>>> temp = gen_rtx_MEM (mode, op0); >>>> set_mem_attributes (temp, exp, 0); >>>> set_mem_addr_space (temp, as); >>>> Index: gimple-expr.c >>>> =================================================================== >>>> --- gimple-expr.c (revision 204792) >>>> +++ gimple-expr.c (working copy) >>>> @@ -633,7 +633,8 @@ is_gimple_address (const_tree t) >>>> op = TREE_OPERAND (op, 0); >>>> } >>>> >>>> - if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF) >>>> + if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF >>>> + || TREE_CODE (op) == TARGET_MEM_REF) >>>> return true; >>>> >>>> switch (TREE_CODE (op)) >>>> Index: gimple-expr.h >>>> =================================================================== >>>> --- gimple-expr.h (revision 204792) >>>> +++ gimple-expr.h (working copy) >>>> @@ -122,7 +122,8 @@ static inline bool >>>> is_gimple_addressable (tree t) >>>> { >>>> return (is_gimple_id (t) || handled_component_p (t) >>>> - || TREE_CODE (t) == MEM_REF); >>>> + || TREE_CODE (t) == MEM_REF >>>> + || TREE_CODE (t) == TARGET_MEM_REF); >>>> } >>>> >>>> /* Return true if T is a valid gimple constant. */ >>>> Index: target.def >>>> =================================================================== >>>> --- target.def (revision 204792) >>>> +++ target.def (working copy) >>>> @@ -1742,6 +1742,14 @@ HOOK_VECTOR_END (vectorize) >>>> #undef HOOK_PREFIX >>>> #define HOOK_PREFIX "TARGET_" >>>> >>>> +DEFHOOK >>>> +(builtin_has_mem_ref_p, >>>> + "This hook return whether the @var{i}th param of the >>>> @var{builtin_function}\n\ >>>> +is a memory reference. If @var{i} is -1, return whether the >>>> @var{builtin_function}\n\ >>>> +contains any memory reference type param.", >>>> + bool, (int builtin_function, int i), >>>> + default_builtin_has_mem_ref_p) >>>> + >>>> /* Allow target specific overriding of option settings after options have >>>> been changed by an attribute or pragma or when it is reset at the >>>> end of the code affected by an attribute or pragma. */ >>>> Index: tree-ssa-loop-ivopts.c >>>> =================================================================== >>>> --- tree-ssa-loop-ivopts.c (revision 204792) >>>> +++ tree-ssa-loop-ivopts.c (working copy) >>>> @@ -1822,7 +1822,8 @@ find_interesting_uses_address (struct iv >>>> >>>> /* Check that the base expression is addressable. This needs >>>> to be done after substituting bases of IVs into it. */ >>>> - if (may_be_nonaddressable_p (base)) >>>> + if (may_be_nonaddressable_p (base) >>>> + && REFERENCE_CLASS_P (base)) >>>> goto fail; >>>> >>>> /* Moreover, on strict alignment platforms, check that it is >>>> @@ -1830,7 +1831,11 @@ find_interesting_uses_address (struct iv >>>> if (STRICT_ALIGNMENT && may_be_unaligned_p (base, step)) >>>> goto fail; >>>> >>>> - base = build_fold_addr_expr (base); >>>> + /* If base is of reference class, build its addr expr here. If >>>> + base is already an address, then don't need to build addr >>>> + expr. */ >>>> + if (REFERENCE_CLASS_P (base)) >>>> + base = build_fold_addr_expr (base); >>>> >>>> /* Substituting bases of IVs into the base expression might >>>> have caused folding opportunities. */ >>>> @@ -1874,13 +1879,36 @@ find_invariants_stmt (struct ivopts_data >>>> } >>>> } >>>> >>>> +/* Find whether the Ith param of the BUILTIN is a mem >>>> + reference. If I is -1, it returns whether the BUILTIN >>>> + contains any mem reference type param. */ >>>> + >>>> +static bool >>>> +builtin_has_mem_ref_p (gimple builtin, int i) >>>> +{ >>>> + tree fndecl = gimple_call_fndecl (builtin); >>>> + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) >>>> + { >>>> + switch (DECL_FUNCTION_CODE (fndecl)) >>>> + { >>>> + case BUILT_IN_PREFETCH: >>>> + if (i == -1 || i == 0) >>>> + return true; >>>> + } >>>> + } >>>> + else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) >>>> + return targetm.builtin_has_mem_ref_p ((int) DECL_FUNCTION_CODE >>>> (fndecl), i); >>>> + >>>> + return false; >>>> +} >>>> + >>>> /* Finds interesting uses of induction variables in the statement STMT. >>>> */ >>>> >>>> static void >>>> find_interesting_uses_stmt (struct ivopts_data *data, gimple stmt) >>>> { >>>> struct iv *iv; >>>> - tree op, *lhs, *rhs; >>>> + tree op, *lhs, *rhs, callee; >>>> ssa_op_iter iter; >>>> use_operand_p use_p; >>>> enum tree_code code; >>>> @@ -1928,14 +1956,40 @@ find_interesting_uses_stmt (struct ivopt >>>> find_interesting_uses_cond (data, stmt); >>>> return; >>>> } >>>> + } >>>> + /* Handle builtin call if it could be expanded to insn >>>> + with memory access operands. Generate USE_ADDRESS type >>>> + use for address expr which is used for memory access of >>>> + such builtin. */ >>>> + else if (is_gimple_call (stmt) >>>> + && (callee = gimple_call_fndecl (stmt)) >>>> + && is_builtin_fn (callee) >>>> + && builtin_has_mem_ref_p (stmt, -1)) >>>> + { >>>> + size_t i; >>>> + for (i = 0; i < gimple_call_num_args (stmt); i++) >>>> + { >>>> + if (builtin_has_mem_ref_p (stmt, i)) >>>> + { >>>> + gimple def; >>>> + tree *arg = gimple_call_arg_ptr (stmt, i); >>>> >>>> - /* TODO -- we should also handle address uses of type >>>> - >>>> - memory = call (whatever); >>>> - >>>> - and >>>> + if (TREE_CODE (*arg) != SSA_NAME) >>>> + continue; >>>> >>>> - call (memory). */ >>>> + def = SSA_NAME_DEF_STMT (*arg); >>>> + gcc_assert (gimple_code (def) == GIMPLE_PHI >>>> + || is_gimple_assign (def)); >>>> + gcc_assert (POINTER_TYPE_P (TREE_TYPE (*arg))); >>>> + find_interesting_uses_address (data, stmt, arg); >>>> + } >>>> + else >>>> + { >>>> + tree arg = gimple_call_arg (stmt, i); >>>> + find_interesting_uses_op (data, arg); >>>> + } >>>> + } >>>> + return; >>>> } >>>> >>>> if (gimple_code (stmt) == GIMPLE_PHI >>>> @@ -6360,7 +6414,7 @@ rewrite_use_address (struct ivopts_data >>>> aff_tree aff; >>>> gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt); >>>> tree base_hint = NULL_TREE; >>>> - tree ref, iv; >>>> + tree ref, iv, callee; >>>> bool ok; >>>> >>>> adjust_iv_update_pos (cand, use); >>>> @@ -6383,10 +6437,41 @@ rewrite_use_address (struct ivopts_data >>>> base_hint = var_at_stmt (data->current_loop, cand, use->stmt); >>>> >>>> iv = var_at_stmt (data->current_loop, cand, use->stmt); >>>> - ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff, >>>> - reference_alias_ptr_type (*use->op_p), >>>> - iv, base_hint, data->speed); >>>> - copy_ref_info (ref, *use->op_p); >>>> + >>>> + /* For builtin_call(addr_expr), change it to: >>>> + tmp = ADDR_EXPR(TMR(...)); >>>> + call (tmp); */ >>>> + if (is_gimple_call (use->stmt) >>>> + && (callee = gimple_call_fndecl (use->stmt)) >>>> + && is_builtin_fn (callee)) >>>> + { >>>> + gimple g; >>>> + gimple_seq seq = NULL; >>>> + tree addr; >>>> + tree type = TREE_TYPE (TREE_TYPE (*use->op_p)); >>>> + location_t loc = gimple_location (use->stmt); >>>> + gimple_stmt_iterator gsi = gsi_for_stmt (use->stmt); >>>> + >>>> + ref = create_mem_ref (&bsi, type, &aff, >>>> + TREE_TYPE (*use->op_p), >>>> + iv, base_hint, data->speed); >>>> + addr = build1 (ADDR_EXPR, TREE_TYPE (*use->op_p), ref); >>>> + g = gimple_build_assign_with_ops (ADDR_EXPR, >>>> + make_ssa_name (TREE_TYPE (*use->op_p), >>>> NULL), >>>> + addr, NULL); >>>> + gimple_set_location (g, loc); >>>> + gimple_seq_add_stmt_without_update (&seq, g); >>>> + gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT); >>>> + >>>> + ref = gimple_assign_lhs (g); >>>> + } >>>> + else >>>> + { >>>> + ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff, >>>> + reference_alias_ptr_type (*use->op_p), >>>> + iv, base_hint, data->speed); >>>> + copy_ref_info (ref, *use->op_p); >>>> + } >>>> *use->op_p = ref; >>>> } >>>> >>>> Index: config/i386/i386.c >>>> =================================================================== >>>> --- config/i386/i386.c (revision 204792) >>>> +++ config/i386/i386.c (working copy) >>>> @@ -29639,6 +29639,50 @@ ix86_init_mmx_sse_builtins (void) >>>> } >>>> } >>>> >>>> +/* Return whether the Ith param of the BUILTIN_FUNCTION >>>> + is a memory reference. If I == -1, return whether the >>>> + BUILTIN_FUNCTION contains any memory reference param. */ >>>> + >>>> +static bool >>>> +ix86_builtin_has_mem_ref_p (int builtin_function, int i) >>>> +{ >>>> + switch ((enum ix86_builtins) builtin_function) >>>> + { >>>> + /* LOAD. */ >>>> + case IX86_BUILTIN_LOADHPS: >>>> + case IX86_BUILTIN_LOADLPS: >>>> + case IX86_BUILTIN_LOADHPD: >>>> + case IX86_BUILTIN_LOADLPD: >>>> + if (i == -1 || i == 1) >>>> + return true; >>>> + break; >>>> + case IX86_BUILTIN_LOADUPS: >>>> + case IX86_BUILTIN_LOADUPD: >>>> + case IX86_BUILTIN_LOADDQU: >>>> + case IX86_BUILTIN_LOADUPD256: >>>> + case IX86_BUILTIN_LOADUPS256: >>>> + case IX86_BUILTIN_LOADDQU256: >>>> + case IX86_BUILTIN_LDDQU256: >>>> + if (i == -1 || i == 0) >>>> + return true; >>>> + break; >>>> + /* STORE. */ >>>> + case IX86_BUILTIN_STOREHPS: >>>> + case IX86_BUILTIN_STORELPS: >>>> + case IX86_BUILTIN_STOREUPS: >>>> + case IX86_BUILTIN_STOREUPD: >>>> + case IX86_BUILTIN_STOREDQU: >>>> + case IX86_BUILTIN_STOREUPD256: >>>> + case IX86_BUILTIN_STOREUPS256: >>>> + case IX86_BUILTIN_STOREDQU256: >>>> + if (i == -1 || i == 0) >>>> + return true; >>>> + default: >>>> + break; >>>> + } >>>> + return false; >>>> +} >>>> + >>>> /* This adds a condition to the basic_block NEW_BB in function >>>> FUNCTION_DECL >>>> to return a pointer to VERSION_DECL if the outcome of the expression >>>> formed by PREDICATE_CHAIN is true. This function will be called during >>>> @@ -32525,7 +32569,13 @@ ix86_expand_special_args_builtin (const >>>> if (i == memory) >>>> { >>>> /* This must be the memory operand. */ >>>> - op = force_reg (Pmode, convert_to_mode (Pmode, op, 1)); >>>> + >>>> + /* We expect the builtin could be expanded to rtl with memory >>>> + operand and proper addressing mode will be kept as >>>> specified >>>> + in TARGET_MEM_REF. */ >>>> + if (!(TREE_CODE (arg) == ADDR_EXPR >>>> + && TREE_CODE (TREE_OPERAND (arg, 0)) == >>>> TARGET_MEM_REF)) >>>> + op = force_reg (Pmode, convert_to_mode (Pmode, op, 1)); >>>> op = gen_rtx_MEM (mode, op); >>>> gcc_assert (GET_MODE (op) == mode >>>> || GET_MODE (op) == VOIDmode); >>>> @@ -43737,6 +43787,9 @@ ix86_atomic_assign_expand_fenv (tree *ho >>>> #undef TARGET_BUILTIN_RECIPROCAL >>>> #define TARGET_BUILTIN_RECIPROCAL ix86_builtin_reciprocal >>>> >>>> +#undef TARGET_BUILTIN_HAS_MEM_REF_P >>>> +#define TARGET_BUILTIN_HAS_MEM_REF_P ix86_builtin_has_mem_ref_p >>>> + >>>> #undef TARGET_ASM_FUNCTION_EPILOGUE >>>> #define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue >>>> >>>> Index: doc/tm.texi >>>> =================================================================== >>>> --- doc/tm.texi (revision 204792) >>>> +++ doc/tm.texi (working copy) >>>> @@ -709,6 +709,12 @@ If a target implements string objects th >>>> If a target implements string objects then this hook should should >>>> provide a facility to check the function arguments in @var{args_list} >>>> against the format specifiers in @var{format_arg} where the type of >>>> @var{format_arg} is one recognized as a valid string reference type. >>>> @end deftypefn >>>> >>>> +@deftypefn {Target Hook} bool TARGET_BUILTIN_HAS_MEM_REF_P (int >>>> @var{builtin_function}, int @var{i}) >>>> +This hook return whether the @var{i}th param of the @var{builtin_function} >>>> +is a memory reference. If @var{i} is -1, return whether the >>>> @var{builtin_function} >>>> +contains any memory reference type param. >>>> +@end deftypefn >>>> + >>>> @deftypefn {Target Hook} void TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE (void) >>>> This target function is similar to the hook @code{TARGET_OPTION_OVERRIDE} >>>> but is called when the optimize level is changed via an attribute or >>>> Index: doc/tm.texi.in >>>> =================================================================== >>>> --- doc/tm.texi.in (revision 204792) >>>> +++ doc/tm.texi.in (working copy) >>>> @@ -697,6 +697,8 @@ should use @code{TARGET_HANDLE_C_OPTION} >>>> >>>> @hook TARGET_CHECK_STRING_OBJECT_FORMAT_ARG >>>> >>>> +@hook TARGET_BUILTIN_HAS_MEM_REF_P >>>> + >>>> @hook TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE >>>> >>>> @defmac C_COMMON_OVERRIDE_OPTIONS