From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7472 invoked by alias); 17 Nov 2015 09:55:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 7462 invoked by uid 89); 17 Nov 2015 09:55:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL,BAYES_00,SPF_PASS autolearn=ham version=3.3.2 X-HELO: eu-smtp-delivery-143.mimecast.com Received: from eu-smtp-delivery-143.mimecast.com (HELO eu-smtp-delivery-143.mimecast.com) (146.101.78.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 17 Nov 2015 09:55:49 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-27-MJozvarzS0CdARzw7BP2Cg-1; Tue, 17 Nov 2015 09:55:43 +0000 Received: from localhost ([10.1.2.79]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 17 Nov 2015 09:55:42 +0000 From: Richard Sandiford To: Richard Biener Mail-Followup-To: Richard Biener ,GCC Patches , richard.sandiford@arm.com Cc: GCC Patches Subject: Re: Short-cut generation of simple built-in functions References: <878u6aos0i.fsf@e105548-lin.cambridge.arm.com> <877flpmtsv.fsf@e105548-lin.cambridge.arm.com> <87h9kqkm1r.fsf@e105548-lin.cambridge.arm.com> Date: Tue, 17 Nov 2015 09:55:00 -0000 In-Reply-To: <87h9kqkm1r.fsf@e105548-lin.cambridge.arm.com> (Richard Sandiford's message of "Fri, 13 Nov 2015 14:32:00 +0000") Message-ID: <87si45j6g1.fsf@e105548-lin.cambridge.arm.com> User-Agent: Gnus/5.130012 (Ma Gnus v0.12) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 X-MC-Unique: MJozvarzS0CdARzw7BP2Cg-1 Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable X-SW-Source: 2015-11/txt/msg02052.txt.bz2 Richard Sandiford writes: > Richard Biener writes: >> On Tue, Nov 10, 2015 at 10:24 PM, Richard Sandiford >> wrote: >>> Richard Biener writes: >>>> On Sat, Nov 7, 2015 at 2:31 PM, Richard Sandiford >>>> wrote: >>>>> This patch short-circuits the builtins.c expansion code for a particu= lar >>>>> gimple call if: >>>>> >>>>> - the function has an associated internal function >>>>> - the target implements that internal function >>>>> - the call has no side effects >>>>> >>>>> This allows a later patch to remove the builtins.c code, once calls w= ith >>>>> side effects have been handled. >>>>> >>>>> Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi. >>>>> OK to install? >>>>> >>>>> Thanks, >>>>> Richard >>>>> >>>>> >>>>> gcc/ >>>>> * builtins.h (called_as_built_in): Declare. >>>>> * builtins.c (called_as_built_in): Make external. >>>>> * internal-fn.h (expand_internal_call): Define a variant that >>>>> specifies the internal function explicitly. >>>>> * internal-fn.c (expand_load_lanes_optab_fn) >>>>> (expand_store_lanes_optab_fn, expand_ANNOTATE, expand_GOMP_SI= MD_LANE) >>>>> (expand_GOMP_SIMD_VF, expand_GOMP_SIMD_LAST_LANE) >>>>> (expand_GOMP_SIMD_ORDERED_START, expand_GOMP_SIMD_ORDERED_END) >>>>> (expand_UBSAN_NULL, expand_UBSAN_BOUNDS, expand_UBSAN_VPTR) >>>>> (expand_UBSAN_OBJECT_SIZE, expand_ASAN_CHECK, expand_TSAN_FUN= C_EXIT) >>>>> (expand_UBSAN_CHECK_ADD, expand_UBSAN_CHECK_SUB) >>>>> (expand_UBSAN_CHECK_MUL, expand_ADD_OVERFLOW, expand_SUB_OVER= FLOW) >>>>> (expand_MUL_OVERFLOW, expand_LOOP_VECTORIZED) >>>>> (expand_mask_load_optab_fn, expand_mask_store_optab_fn) >>>>> (expand_ABNORMAL_DISPATCHER, expand_BUILTIN_EXPECT, expand_VA= _ARG) >>>>> (expand_UNIQUE, expand_GOACC_DIM_SIZE, expand_GOACC_DIM_POS) >>>>> (expand_GOACC_LOOP, expand_GOACC_REDUCTION, expand_direct_opt= ab_fn) >>>>> (expand_unary_optab_fn, expand_binary_optab_fn): Add an inter= nal_fn >>>>> argument. >>>>> (internal_fn_expanders): Update prototype. >>>>> (expand_internal_call): Define a variant that specifies the >>>>> internal function explicitly. Use it to implement the previous >>>>> interface. >>>>> * cfgexpand.c (expand_call_stmt): Try to expand calls to buil= t-in >>>>> functions as calls to internal functions. >>>>> >>>>> diff --git a/gcc/builtins.c b/gcc/builtins.c >>>>> index f65011e..bbcc7dc3 100644 >>>>> --- a/gcc/builtins.c >>>>> +++ b/gcc/builtins.c >>>>> @@ -222,7 +222,7 @@ is_builtin_fn (tree decl) >>>>> of the optimization level. This means whenever a function is inv= oked with >>>>> its "internal" name, which normally contains the prefix "__builti= n". */ >>>>> >>>>> -static bool >>>>> +bool >>>>> called_as_built_in (tree node) >>>>> { >>>>> /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P = since >>>>> diff --git a/gcc/builtins.h b/gcc/builtins.h >>>>> index 917eb90..1d00068 100644 >>>>> --- a/gcc/builtins.h >>>>> +++ b/gcc/builtins.h >>>>> @@ -50,6 +50,7 @@ extern struct target_builtins *this_target_builtins; >>>>> extern bool force_folding_builtin_constant_p; >>>>> >>>>> extern bool is_builtin_fn (tree); >>>>> +extern bool called_as_built_in (tree); >>>>> extern bool get_object_alignment_1 (tree, unsigned int *, >>>>> unsigned HOST_WIDE_INT *); >>>>> extern unsigned int get_object_alignment (tree); >>>>> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c >>>>> index bfbc958..dc7d4f5 100644 >>>>> --- a/gcc/cfgexpand.c >>>>> +++ b/gcc/cfgexpand.c >>>>> @@ -2551,10 +2551,25 @@ expand_call_stmt (gcall *stmt) >>>>> return; >>>>> } >>>>> >>>>> + /* If this is a call to a built-in function and it has no effect o= ther >>>>> + than setting the lhs, try to implement it using an internal fun= ction >>>>> + instead. */ >>>>> + decl =3D gimple_call_fndecl (stmt); >>>>> + if (gimple_call_lhs (stmt) >>>>> + && !gimple_vdef (stmt) >>>> >>>> I think you want && ! gimple_has_side_effects (stmt) >>>> instead of checking !gimple_vdef (stmt). >>> >>> OK, I can do that, but what would the difference be in practice for >>> these types of call? I.e. are there cases for built-ins where: >>> >>> (A) gimple_vdef (stmt) && !gimple_side_effects (stmt) >>> >>> or: >>> >>> (B) !gimple_vdef (stmt) && gimple_side_effects (stmt) >>> >>> ? >> >> There was talk to make calls use volatile to prevent CSE and friends. >> >> Using gimple_has_side_effects is just the better check. >> >>> It just seems like this check should be the opposite of the one used >>> in the call-cdce patch (when deciding whether to optimise a call >>> with an lhs). In order to keep them in sync I'd need to use >>> gimple_side_effects rather than gimple_vdef there too, but is >>> (B) a possibility there? >> >> Not sure if the tests should be in-sync. > > Well, with the series, we have two opportunities to use optabs: > > - in tree-call-cdce.c, if we need to keep the original call > (or something that sets EDOM) > > - here in cfgexpand.c, if we don't need to keep the original call. > > So both are really asking "do I need to keep the call?" > > If we don't do either then we don't use the optab. Anyway, the updated patch below uses gimple_side_effects_p. >> I'm also not sure what you really want to check with >> >>>>> + /* If this is a call to a built-in function and it has no effect o= ther >>>>> + than setting the lhs, try to implement it using an internal fun= ction >>>>> + instead. */ >>>>> + decl =3D gimple_call_fndecl (stmt); >>>>> + if (gimple_call_lhs (stmt) >>>>> + && !gimple_vdef (stmt) >> >> I know you want to catch errno setting here but shouldn't that use a >> different kind of check and only done for a specific subset of >> functions? For example do you want to replace sqrt() with >> an IFN in case it has a VUSE (it will have that with -frounding-math)? >> In this case you'll lose the implicit dependence on fesetround and >> friends. This implicit dependence is not checked by gimple_has_side_eff= ects >> either btw. > > Yeah, we want to replace even in that case. Remember that this is > expand code, so we're going to generate rtl whatever happens. It's up > to the rtl patterns to represent any ordering requirements. (Not that > we do have explicit rtl dependencies for rounding mode, but we don't for > +, -. * or / either.) > > If for some reason a particular .md pattern doesn't honour the current > rounding mode when normally the optab would be expected to, the .md file > should limit the pattern to !flag_rounding_math. Tested as before. OK to install? Thanks, Richard gcc/ * builtins.h (called_as_built_in): Declare. * builtins.c (called_as_built_in): Make external. * internal-fn.h (expand_internal_call): Define a variant that specifies the internal function explicitly. * internal-fn.c (expand_load_lanes_optab_fn) (expand_store_lanes_optab_fn, expand_ANNOTATE, expand_GOMP_SIMD_LANE) (expand_GOMP_SIMD_VF, expand_GOMP_SIMD_LAST_LANE) (expand_GOMP_SIMD_ORDERED_START, expand_GOMP_SIMD_ORDERED_END) (expand_UBSAN_NULL, expand_UBSAN_BOUNDS, expand_UBSAN_VPTR) (expand_UBSAN_OBJECT_SIZE, expand_ASAN_CHECK, expand_TSAN_FUNC_EXIT) (expand_UBSAN_CHECK_ADD, expand_UBSAN_CHECK_SUB) (expand_UBSAN_CHECK_MUL, expand_ADD_OVERFLOW, expand_SUB_OVERFLOW) (expand_MUL_OVERFLOW, expand_LOOP_VECTORIZED) (expand_mask_load_optab_fn, expand_mask_store_optab_fn) (expand_ABNORMAL_DISPATCHER, expand_BUILTIN_EXPECT, expand_VA_ARG) (expand_UNIQUE, expand_GOACC_DIM_SIZE, expand_GOACC_DIM_POS) (expand_GOACC_LOOP, expand_GOACC_REDUCTION, expand_direct_optab_fn) (expand_unary_optab_fn, expand_binary_optab_fn): Add an internal_fn argument. (internal_fn_expanders): Update prototype. (expand_internal_call): Define a variant that specifies the internal function explicitly. Use it to implement the previous interface. * cfgexpand.c (expand_call_stmt): Try to expand calls to built-in functions as calls to internal functions. diff --git a/gcc/builtins.c b/gcc/builtins.c index 6df1b9b..c422d0d 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -222,7 +222,7 @@ is_builtin_fn (tree decl) of the optimization level. This means whenever a function is invoked w= ith its "internal" name, which normally contains the prefix "__builtin". */ =20 -static bool +bool called_as_built_in (tree node) { /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since diff --git a/gcc/builtins.h b/gcc/builtins.h index 917eb90..1d00068 100644 --- a/gcc/builtins.h +++ b/gcc/builtins.h @@ -50,6 +50,7 @@ extern struct target_builtins *this_target_builtins; extern bool force_folding_builtin_constant_p; =20 extern bool is_builtin_fn (tree); +extern bool called_as_built_in (tree); extern bool get_object_alignment_1 (tree, unsigned int *, unsigned HOST_WIDE_INT *); extern unsigned int get_object_alignment (tree); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index e55467a..1990e10 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2551,10 +2551,25 @@ expand_call_stmt (gcall *stmt) return; } =20 + /* If this is a call to a built-in function and it has no effect other + than setting the lhs, try to implement it using an internal function + instead. */ + decl =3D gimple_call_fndecl (stmt); + if (gimple_call_lhs (stmt) + && !gimple_has_side_effects (stmt) + && (optimize || (decl && called_as_built_in (decl)))) + { + internal_fn ifn =3D replacement_internal_fn (stmt); + if (ifn !=3D IFN_LAST) + { + expand_internal_call (ifn, stmt); + return; + } + } + exp =3D build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3); =20 CALL_EXPR_FN (exp) =3D gimple_call_fn (stmt); - decl =3D gimple_call_fndecl (stmt); builtin_p =3D decl && DECL_BUILT_IN (decl); =20 /* If this is not a builtin function, the function type through which the diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index b853162..f23d799 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -103,7 +103,7 @@ get_multi_vector_move (tree array_type, convert_optab o= ptab) /* Expand LOAD_LANES call STMT using optab OPTAB. */ =20 static void -expand_load_lanes_optab_fn (gcall *stmt, convert_optab optab) +expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab) { struct expand_operand ops[2]; tree type, lhs, rhs; @@ -127,7 +127,7 @@ expand_load_lanes_optab_fn (gcall *stmt, convert_optab = optab) /* Expand STORE_LANES call STMT using optab OPTAB. */ =20 static void -expand_store_lanes_optab_fn (gcall *stmt, convert_optab optab) +expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab) { struct expand_operand ops[2]; tree type, lhs, rhs; @@ -149,7 +149,7 @@ expand_store_lanes_optab_fn (gcall *stmt, convert_optab= optab) } =20 static void -expand_ANNOTATE (gcall *) +expand_ANNOTATE (internal_fn, gcall *) { gcc_unreachable (); } @@ -157,7 +157,7 @@ expand_ANNOTATE (gcall *) /* This should get expanded in adjust_simduid_builtins. */ =20 static void -expand_GOMP_SIMD_LANE (gcall *) +expand_GOMP_SIMD_LANE (internal_fn, gcall *) { gcc_unreachable (); } @@ -165,7 +165,7 @@ expand_GOMP_SIMD_LANE (gcall *) /* This should get expanded in adjust_simduid_builtins. */ =20 static void -expand_GOMP_SIMD_VF (gcall *) +expand_GOMP_SIMD_VF (internal_fn, gcall *) { gcc_unreachable (); } @@ -173,7 +173,7 @@ expand_GOMP_SIMD_VF (gcall *) /* This should get expanded in adjust_simduid_builtins. */ =20 static void -expand_GOMP_SIMD_LAST_LANE (gcall *) +expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *) { gcc_unreachable (); } @@ -181,7 +181,7 @@ expand_GOMP_SIMD_LAST_LANE (gcall *) /* This should get expanded in adjust_simduid_builtins. */ =20 static void -expand_GOMP_SIMD_ORDERED_START (gcall *) +expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *) { gcc_unreachable (); } @@ -189,7 +189,7 @@ expand_GOMP_SIMD_ORDERED_START (gcall *) /* This should get expanded in adjust_simduid_builtins. */ =20 static void -expand_GOMP_SIMD_ORDERED_END (gcall *) +expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *) { gcc_unreachable (); } @@ -197,7 +197,7 @@ expand_GOMP_SIMD_ORDERED_END (gcall *) /* This should get expanded in the sanopt pass. */ =20 static void -expand_UBSAN_NULL (gcall *) +expand_UBSAN_NULL (internal_fn, gcall *) { gcc_unreachable (); } @@ -205,7 +205,7 @@ expand_UBSAN_NULL (gcall *) /* This should get expanded in the sanopt pass. */ =20 static void -expand_UBSAN_BOUNDS (gcall *) +expand_UBSAN_BOUNDS (internal_fn, gcall *) { gcc_unreachable (); } @@ -213,7 +213,7 @@ expand_UBSAN_BOUNDS (gcall *) /* This should get expanded in the sanopt pass. */ =20 static void -expand_UBSAN_VPTR (gcall *) +expand_UBSAN_VPTR (internal_fn, gcall *) { gcc_unreachable (); } @@ -221,7 +221,7 @@ expand_UBSAN_VPTR (gcall *) /* This should get expanded in the sanopt pass. */ =20 static void -expand_UBSAN_OBJECT_SIZE (gcall *) +expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *) { gcc_unreachable (); } @@ -229,7 +229,7 @@ expand_UBSAN_OBJECT_SIZE (gcall *) /* This should get expanded in the sanopt pass. */ =20 static void -expand_ASAN_CHECK (gcall *) +expand_ASAN_CHECK (internal_fn, gcall *) { gcc_unreachable (); } @@ -237,7 +237,7 @@ expand_ASAN_CHECK (gcall *) /* This should get expanded in the tsan pass. */ =20 static void -expand_TSAN_FUNC_EXIT (gcall *) +expand_TSAN_FUNC_EXIT (internal_fn, gcall *) { gcc_unreachable (); } @@ -1639,7 +1639,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree a= rg0, tree arg1, /* Expand UBSAN_CHECK_ADD call STMT. */ =20 static void -expand_UBSAN_CHECK_ADD (gcall *stmt) +expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt) { location_t loc =3D gimple_location (stmt); tree lhs =3D gimple_call_lhs (stmt); @@ -1652,7 +1652,7 @@ expand_UBSAN_CHECK_ADD (gcall *stmt) /* Expand UBSAN_CHECK_SUB call STMT. */ =20 static void -expand_UBSAN_CHECK_SUB (gcall *stmt) +expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt) { location_t loc =3D gimple_location (stmt); tree lhs =3D gimple_call_lhs (stmt); @@ -1668,7 +1668,7 @@ expand_UBSAN_CHECK_SUB (gcall *stmt) /* Expand UBSAN_CHECK_MUL call STMT. */ =20 static void -expand_UBSAN_CHECK_MUL (gcall *stmt) +expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt) { location_t loc =3D gimple_location (stmt); tree lhs =3D gimple_call_lhs (stmt); @@ -1853,7 +1853,7 @@ expand_arith_overflow (enum tree_code code, gimple *s= tmt) /* Expand ADD_OVERFLOW STMT. */ =20 static void -expand_ADD_OVERFLOW (gcall *stmt) +expand_ADD_OVERFLOW (internal_fn, gcall *stmt) { expand_arith_overflow (PLUS_EXPR, stmt); } @@ -1861,7 +1861,7 @@ expand_ADD_OVERFLOW (gcall *stmt) /* Expand SUB_OVERFLOW STMT. */ =20 static void -expand_SUB_OVERFLOW (gcall *stmt) +expand_SUB_OVERFLOW (internal_fn, gcall *stmt) { expand_arith_overflow (MINUS_EXPR, stmt); } @@ -1869,7 +1869,7 @@ expand_SUB_OVERFLOW (gcall *stmt) /* Expand MUL_OVERFLOW STMT. */ =20 static void -expand_MUL_OVERFLOW (gcall *stmt) +expand_MUL_OVERFLOW (internal_fn, gcall *stmt) { expand_arith_overflow (MULT_EXPR, stmt); } @@ -1877,7 +1877,7 @@ expand_MUL_OVERFLOW (gcall *stmt) /* This should get folded in tree-vectorizer.c. */ =20 static void -expand_LOOP_VECTORIZED (gcall *) +expand_LOOP_VECTORIZED (internal_fn, gcall *) { gcc_unreachable (); } @@ -1885,7 +1885,7 @@ expand_LOOP_VECTORIZED (gcall *) /* Expand MASK_LOAD call STMT using optab OPTAB. */ =20 static void -expand_mask_load_optab_fn (gcall *stmt, convert_optab optab) +expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab) { struct expand_operand ops[3]; tree type, lhs, rhs, maskt; @@ -1914,7 +1914,7 @@ expand_mask_load_optab_fn (gcall *stmt, convert_optab= optab) /* Expand MASK_STORE call STMT using optab OPTAB. */ =20 static void -expand_mask_store_optab_fn (gcall *stmt, convert_optab optab) +expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab) { struct expand_operand ops[3]; tree type, lhs, rhs, maskt; @@ -1939,12 +1939,12 @@ expand_mask_store_optab_fn (gcall *stmt, convert_op= tab optab) } =20 static void -expand_ABNORMAL_DISPATCHER (gcall *) +expand_ABNORMAL_DISPATCHER (internal_fn, gcall *) { } =20 static void -expand_BUILTIN_EXPECT (gcall *stmt) +expand_BUILTIN_EXPECT (internal_fn, gcall *stmt) { /* When guessing was done, the hints should be already stripped away. */ gcc_assert (!flag_guess_branch_prob || optimize =3D=3D 0 || seen_error (= )); @@ -1964,7 +1964,7 @@ expand_BUILTIN_EXPECT (gcall *stmt) should never be called. */ =20 static void -expand_VA_ARG (gcall *stmt ATTRIBUTE_UNUSED) +expand_VA_ARG (internal_fn, gcall *) { gcc_unreachable (); } @@ -1972,7 +1972,7 @@ expand_VA_ARG (gcall *stmt ATTRIBUTE_UNUSED) /* Expand the IFN_UNIQUE function according to its first argument. */ =20 static void -expand_UNIQUE (gcall *stmt) +expand_UNIQUE (internal_fn, gcall *stmt) { rtx pattern =3D NULL_RTX; enum ifn_unique_kind kind @@ -2018,7 +2018,7 @@ expand_UNIQUE (gcall *stmt) /* The size of an OpenACC compute dimension. */ =20 static void -expand_GOACC_DIM_SIZE (gcall *stmt) +expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt) { tree lhs =3D gimple_call_lhs (stmt); =20 @@ -2039,7 +2039,7 @@ expand_GOACC_DIM_SIZE (gcall *stmt) /* The position of an OpenACC execution engine along one compute axis. */ =20 static void -expand_GOACC_DIM_POS (gcall *stmt) +expand_GOACC_DIM_POS (internal_fn, gcall *stmt) { tree lhs =3D gimple_call_lhs (stmt); =20 @@ -2060,7 +2060,7 @@ expand_GOACC_DIM_POS (gcall *stmt) /* This is expanded by oacc_device_lower pass. */ =20 static void -expand_GOACC_LOOP (gcall *stmt ATTRIBUTE_UNUSED) +expand_GOACC_LOOP (internal_fn, gcall *) { gcc_unreachable (); } @@ -2068,20 +2068,20 @@ expand_GOACC_LOOP (gcall *stmt ATTRIBUTE_UNUSED) /* This is expanded by oacc_device_lower pass. */ =20 static void -expand_GOACC_REDUCTION (gcall *stmt ATTRIBUTE_UNUSED) +expand_GOACC_REDUCTION (internal_fn, gcall *) { gcc_unreachable (); } =20 -/* Expand call STMT using OPTAB, which has a single output operand and - NARGS input operands. */ +/* Expand a call to FN using the operands in STMT. FN has a single + output operand and NARGS input operands. */ =20 static void -expand_direct_optab_fn (gcall *stmt, direct_optab optab, unsigned int narg= s) +expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab, + unsigned int nargs) { expand_operand *ops =3D XALLOCAVEC (expand_operand, nargs + 1); =20 - internal_fn fn =3D gimple_call_internal_fn (stmt); tree_pair types =3D direct_internal_fn_types (fn, stmt); insn_code icode =3D direct_optab_handler (optab, TYPE_MODE (types.first)= ); =20 @@ -2119,11 +2119,11 @@ expand_direct_optab_fn (gcall *stmt, direct_optab o= ptab, unsigned int nargs) =20 /* Expanders for optabs that can use expand_direct_optab_fn. */ =20 -#define expand_unary_optab_fn(STMT, OPTAB) \ - expand_direct_optab_fn (STMT, OPTAB, 1) +#define expand_unary_optab_fn(FN, STMT, OPTAB) \ + expand_direct_optab_fn (FN, STMT, OPTAB, 1) =20 -#define expand_binary_optab_fn(STMT, OPTAB) \ - expand_direct_optab_fn (STMT, OPTAB, 2) +#define expand_binary_optab_fn(FN, STMT, OPTAB) \ + expand_direct_optab_fn (FN, STMT, OPTAB, 2) =20 /* RETURN_TYPE and ARGS are a return type and argument list that are in principle compatible with FN (which satisfies direct_internal_fn_p). @@ -2219,9 +2219,9 @@ direct_internal_fn_supported_p (internal_fn fn, tree = type) =20 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \ static void \ - expand_##CODE (gcall *stmt) \ + expand_##CODE (internal_fn fn, gcall *stmt) \ { \ - expand_##TYPE##_optab_fn (stmt, OPTAB##_optab); \ + expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \ } #include "internal-fn.def" =20 @@ -2231,16 +2231,24 @@ direct_internal_fn_supported_p (internal_fn fn, tre= e type) expand_ (gcall *stmt) =20 where STMT is the statement that performs the call. */ -static void (*const internal_fn_expanders[]) (gcall *) =3D { +static void (*const internal_fn_expanders[]) (internal_fn, gcall *) =3D { #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE, #include "internal-fn.def" 0 }; =20 +/* Expand STMT as though it were a call to internal function FN. */ + +void +expand_internal_call (internal_fn fn, gcall *stmt) +{ + internal_fn_expanders[fn] (fn, stmt); +} + /* Expand STMT, which is a call to internal function FN. */ =20 void expand_internal_call (gcall *stmt) { - internal_fn_expanders[(int) gimple_call_internal_fn (stmt)] (stmt); + expand_internal_call (gimple_call_internal_fn (stmt), stmt); } diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h index 31e895e..5ee43b8 100644 --- a/gcc/internal-fn.h +++ b/gcc/internal-fn.h @@ -162,5 +162,6 @@ extern bool direct_internal_fn_supported_p (internal_fn= , tree_pair); extern bool direct_internal_fn_supported_p (internal_fn, tree); =20 extern void expand_internal_call (gcall *); +extern void expand_internal_call (internal_fn, gcall *); =20 #endif