Skip to content

Commit d6cb779

Browse files
author
Mikael Morin
committed
fortran: Add -finline-intrinsics flag for MINLOC/MAXLOC [PR90608]
Introduce the -finline-intrinsics flag to control from the command line whether to generate either inline code or calls to the functions from the library, for the MINLOC and MAXLOC intrinsics. The flag allows to specify inlining either independently for each intrinsic (either MINLOC or MAXLOC), or all together. For each intrinsic, a default value is set if none was set. The default value depends on the optimization setting: inlining is avoided if not optimizing or if optimizing for size; otherwise inlining is preferred. There is no direct support for this behaviour provided by the .opt options framework. It is obtained by defining three different variants of the flag (finline-intrinsics, fno-inline-intrinsics, finline-intrinsics=) all using the same underlying option variable. Each enum value (corresponding to an intrinsic function) uses two identical bits, and the variable is initialized with alternated bits, so that we can tell whether the value was set or not by checking whether the two bits have different values. PR fortran/90608 gcc/ChangeLog: * flag-types.h (enum gfc_inlineable_intrinsics): New type. gcc/fortran/ChangeLog: * invoke.texi(finline-intrinsics): Document new flag. * lang.opt (finline-intrinsics, finline-intrinsics=, fno-inline-intrinsics): New flags. * options.cc (gfc_post_options): If the option variable controlling the inlining of MAXLOC (respectively MINLOC) has not been set, set it or clear it depending on the optimization option variables. * trans-intrinsic.cc (gfc_inline_intrinsic_function_p): Return false if inlining for the intrinsic is disabled according to the option variable. gcc/testsuite/ChangeLog: * gfortran.dg/minmaxloc_18.f90: New test. * gfortran.dg/minmaxloc_18a.f90: New test. * gfortran.dg/minmaxloc_18b.f90: New test. * gfortran.dg/minmaxloc_18c.f90: New test. * gfortran.dg/minmaxloc_18d.f90: New test.
1 parent 3c01ddc commit d6cb779

File tree

10 files changed

+927
-5
lines changed

10 files changed

+927
-5
lines changed

gcc/flag-types.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,36 @@ enum gfc_convert
451451
};
452452

453453

454+
/* gfortran -finline-intrinsics= values;
455+
We use two identical bits for each value, and initialize with alternated
456+
bits, so that we can check whether a value has been set by checking whether
457+
the two bits have identical value. */
458+
459+
#define GFC_INL_INTR_VAL(idx) (3 << (2 * idx))
460+
#define GFC_INL_INTR_UNSET_VAL(val) (0x55555555 & (val))
461+
462+
enum gfc_inlineable_intrinsics
463+
{
464+
GFC_FLAG_INLINE_INTRINSIC_NONE = 0,
465+
GFC_FLAG_INLINE_INTRINSIC_MAXLOC = GFC_INL_INTR_VAL (0),
466+
GFC_FLAG_INLINE_INTRINSIC_MINLOC = GFC_INL_INTR_VAL (1),
467+
GFC_FLAG_INLINE_INTRINSIC_ALL = GFC_FLAG_INLINE_INTRINSIC_MAXLOC
468+
| GFC_FLAG_INLINE_INTRINSIC_MINLOC,
469+
470+
GFC_FLAG_INLINE_INTRINSIC_NONE_UNSET
471+
= GFC_INL_INTR_UNSET_VAL (GFC_FLAG_INLINE_INTRINSIC_NONE),
472+
GFC_FLAG_INLINE_INTRINSIC_MAXLOC_UNSET
473+
= GFC_INL_INTR_UNSET_VAL (GFC_FLAG_INLINE_INTRINSIC_MAXLOC),
474+
GFC_FLAG_INLINE_INTRINSIC_MINLOC_UNSET
475+
= GFC_INL_INTR_UNSET_VAL (GFC_FLAG_INLINE_INTRINSIC_MINLOC),
476+
GFC_FLAG_INLINE_INTRINSIC_ALL_UNSET
477+
= GFC_INL_INTR_UNSET_VAL (GFC_FLAG_INLINE_INTRINSIC_ALL)
478+
};
479+
480+
#undef GFC_INL_INTR_UNSET_VAL
481+
#undef GFC_INL_INTR_VAL
482+
483+
454484
/* Inline String Operations functions. */
455485
enum ilsop_fn
456486
{

gcc/fortran/invoke.texi

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ and warnings}.
194194
-finit-character=@var{n} -finit-integer=@var{n} -finit-local-zero
195195
-finit-derived -finit-logical=@var{<true|false>}
196196
-finit-real=@var{<zero|inf|-inf|nan|snan>}
197+
-finline-intrinsics[=<@var{minloc},@var{maxloc}>]
197198
-finline-matmul-limit=@var{n}
198199
-finline-arg-packing -fmax-array-constructor=@var{n}
199200
-fmax-stack-var-size=@var{n} -fno-align-commons -fno-automatic
@@ -1997,6 +1998,34 @@ geometric mean of the dimensions of the argument and result matrices.
19971998

19981999
The default value for @var{n} is 30.
19992000

2001+
@opindex @code{finline-intrinsics}
2002+
@item -finline-intrinsics
2003+
@itemx -finline-intrinsics=@var{intr1},@var{intr2},...
2004+
Prefer generating inline code over calls to libgfortran functions to implement
2005+
intrinsics.
2006+
2007+
Usage of intrinsics can be implemented either by generating a call to the
2008+
libgfortran library function or by directly generating inline code. For most
2009+
intrinsics, only a single variant is available, and there is no choice of
2010+
implementation. However, some intrinsics can use a library function or inline
2011+
code, where inline code typically offers opportunities for additional
2012+
optimization over a library function. With @code{-finline-intrinsics=...} or
2013+
@code{-fno-inline-intrinsics=...}, the choice applies only to the intrinsics
2014+
present in the comma-separated list provided as argument.
2015+
2016+
For each intrinsic, if no choice of implementation was made through either of
2017+
the flag variants, a default behaviour is chosen depending on optimization:
2018+
library calls are generated when not optimizing or when optimizing for size;
2019+
otherwise inline code is preferred.
2020+
2021+
The set of intrinsics allowed as argument to @code{-finline-intrinsics=}
2022+
is currently limited to @code{MAXLOC} and @code{MINLOC}. The effect of
2023+
the flag is moreover limited to calls of those intrinsics without
2024+
@code{DIM} argument and with @code{ARRAY} of a non-@code{CHARACTER} type.
2025+
The case of rank-1 argument and @code{DIM} argument present, i.e.
2026+
@code{MAXLOC(A(:),DIM=1)} or @code{MINLOC(A(:),DIM=1)} is inlined
2027+
unconditionally for numeric rank-1 array argument @code{A}.
2028+
20002029
@opindex @code{finline-matmul-limit}
20012030
@item -finline-matmul-limit=@var{n}
20022031
When front-end optimization is active, some calls to the @code{MATMUL}

gcc/fortran/lang.opt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,33 @@ finline-arg-packing
676676
Fortran Var(flag_inline_arg_packing) Init(-1)
677677
-finline-arg-packing Perform argument packing inline.
678678

679+
finline-intrinsics
680+
Fortran RejectNegative Enum(gfc_inlineable_intrinsics) Var(flag_inline_intrinsics, GFC_FLAG_INLINE_INTRINSIC_ALL) Undocumented
681+
682+
fno-inline-intrinsics
683+
Fortran RejectNegative Enum(gfc_inlineable_intrinsics) Var(flag_inline_intrinsics, GFC_FLAG_INLINE_INTRINSIC_NONE) Undocumented
684+
685+
finline-intrinsics=
686+
Fortran Joined Var(flag_inline_intrinsics) Enum(gfc_inlineable_intrinsics) Init(GFC_FLAG_INLINE_INTRINSIC_ALL_UNSET) EnumSet
687+
Enable generation of inline code instead of calls to functions from the library to implement intrinsics.
688+
689+
Enum
690+
Name(gfc_inlineable_intrinsics) Type(int) UnknownError(%qs is not an inline-controlable intrinsic)
691+
692+
; This is not part of any set
693+
; EnumValue
694+
; Enum(gfc_inlineable_intrinsics) String(none) Value(GFC_FLAG_INLINE_INTRINSIC_NONE)
695+
696+
EnumValue
697+
Enum(gfc_inlineable_intrinsics) String(maxloc) Value(GFC_FLAG_INLINE_INTRINSIC_MAXLOC) Set(1)
698+
699+
EnumValue
700+
Enum(gfc_inlineable_intrinsics) String(minloc) Value(GFC_FLAG_INLINE_INTRINSIC_MINLOC) Set(2)
701+
702+
; This is not part of any set
703+
; EnumValue
704+
; Enum(gfc_inlineable_intrinsics) String(all) Value(GFC_FLAG_INLINE_INTRINSIC_ALL)
705+
679706
finline-matmul-limit=
680707
Fortran RejectNegative Joined UInteger Var(flag_inline_matmul_limit) Init(-1)
681708
-finline-matmul-limit=<n> Specify the size of the largest matrix for which matmul will be inlined.

gcc/fortran/options.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,26 @@ gfc_post_options (const char **pfilename)
472472
/* Implement -fno-automatic as -fmax-stack-var-size=0. */
473473
if (!flag_automatic)
474474
flag_max_stack_var_size = 0;
475-
475+
476+
/* Decide inlining preference depending on optimization if nothing was
477+
specified on the command line. */
478+
if ((flag_inline_intrinsics & GFC_FLAG_INLINE_INTRINSIC_MAXLOC)
479+
== GFC_FLAG_INLINE_INTRINSIC_MAXLOC_UNSET)
480+
{
481+
if (optimize == 0 || optimize_size != 0)
482+
flag_inline_intrinsics &= ~GFC_FLAG_INLINE_INTRINSIC_MAXLOC;
483+
else
484+
flag_inline_intrinsics |= GFC_FLAG_INLINE_INTRINSIC_MAXLOC;
485+
}
486+
if ((flag_inline_intrinsics & GFC_FLAG_INLINE_INTRINSIC_MINLOC)
487+
== GFC_FLAG_INLINE_INTRINSIC_MINLOC_UNSET)
488+
{
489+
if (optimize == 0 || optimize_size != 0)
490+
flag_inline_intrinsics &= ~GFC_FLAG_INLINE_INTRINSIC_MINLOC;
491+
else
492+
flag_inline_intrinsics |= GFC_FLAG_INLINE_INTRINSIC_MINLOC;
493+
}
494+
476495
/* If the user did not specify an inline matmul limit, inline up to the BLAS
477496
limit or up to 30 if no external BLAS is specified. */
478497

gcc/fortran/trans-intrinsic.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11868,10 +11868,11 @@ gfc_inline_intrinsic_function_p (gfc_expr *expr)
1186811868
gfc_actual_arglist *args, *dim_arg, *mask_arg;
1186911869
gfc_expr *maskexpr;
1187011870

11871-
if (!expr->value.function.isym)
11871+
gfc_intrinsic_sym *isym = expr->value.function.isym;
11872+
if (!isym)
1187211873
return false;
1187311874

11874-
switch (expr->value.function.isym->id)
11875+
switch (isym->id)
1187511876
{
1187611877
case GFC_ISYM_PRODUCT:
1187711878
case GFC_ISYM_SUM:
@@ -11907,8 +11908,12 @@ gfc_inline_intrinsic_function_p (gfc_expr *expr)
1190711908
case GFC_ISYM_MINLOC:
1190811909
case GFC_ISYM_MAXLOC:
1190911910
{
11910-
/* Disable inline expansion if code size matters. */
11911-
if (optimize_size)
11911+
if ((isym->id == GFC_ISYM_MINLOC
11912+
&& (flag_inline_intrinsics
11913+
& GFC_FLAG_INLINE_INTRINSIC_MINLOC) == 0)
11914+
|| (isym->id == GFC_ISYM_MAXLOC
11915+
&& (flag_inline_intrinsics
11916+
& GFC_FLAG_INLINE_INTRINSIC_MAXLOC) == 0))
1191211917
return false;
1191311918

1191411919
gfc_actual_arglist *array_arg = expr->value.function.actual;

0 commit comments

Comments
 (0)