On 1/21/19 3:25 PM, Joseph Myers wrote:
> On Mon, 21 Jan 2019, Martin Liška wrote:
>
>> I like the if('lp64'), if('ilp32') approach and I'm sending patch
>> candidate for that. Would it be accepted by glibc folks?
>
> Since glibc supports libmvec for x86_64, both 64-bit and x32, but not for
> 32-bit x86, those particular conditionals are insufficient because they
> can't distinguish x32 (libmvec supported) from 32-bit x86 (libmvec not
> supported); you need some architecture-specific conditional that can be
> used in the Fortran header.
>
Hello.
I discussed with Jakub possibility of generating canonical triples that will
be then used in Fortran FE to filter the 'GCC$ builtin' directives. However,
the approach bring some possibilities and thus I enhanced the previous
version of patch to catch x32 ABI (I call it lp64ilp32), similarly to Debian:
https://wiki.debian.org/Multiarch/Tuples
If I'm correct, such ABI can be provided on i386, aarch64 and mips64 targets.
Will the suggested approach work?
Martin
>From d585da8b477ac13be1941d290d7e2b8c7b5bf96a Mon Sep 17 00:00:00 2001
From: marxin <[email protected]>
Date: Mon, 21 Jan 2019 08:46:06 +0100
Subject: [PATCH] Support if statement in !GCC$ builtin directive.
gcc/fortran/ChangeLog:
2019-01-21 Martin Liska <[email protected]>
* decl.c (gfc_match_gcc_builtin): Support filtering for
'lp64' and 'ilp32'.
gcc/testsuite/ChangeLog:
2019-01-21 Martin Liska <[email protected]>
* gfortran.dg/simd-builtins-7.f90: New test.
* gfortran.dg/simd-builtins-7.h: New test.
---
gcc/config/i386/i386.c | 15 ++++++++
gcc/coretypes.h | 9 +++++
gcc/doc/tm.texi | 4 +++
gcc/doc/tm.texi.in | 2 ++
gcc/fortran/decl.c | 35 +++++++++++++++++--
gcc/target.def | 6 ++++
gcc/targhooks.c | 6 ++++
gcc/targhooks.h | 1 +
gcc/testsuite/gfortran.dg/simd-builtins-7.f90 | 19 ++++++++++
gcc/testsuite/gfortran.dg/simd-builtins-7.h | 2 ++
10 files changed, 96 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gfortran.dg/simd-builtins-7.f90
create mode 100644 gcc/testsuite/gfortran.dg/simd-builtins-7.h
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8abff99cc62..0167b4bd3e5 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -29573,6 +29573,17 @@ ix86_warn_parameter_passing_abi (cumulative_args_t cum_v, tree type)
cum->warn_empty = false;
}
+static target_abi_type
+ix86_get_abi_type (void)
+{
+ if (!(TARGET_64BIT_P (ix86_isa_flags )))
+ return ABI_ILP32;
+ else if (TARGET_X32_P (ix86_isa_flags))
+ return ABI_LP64ILP32;
+ else
+ return ABI_LP64;
+}
+
/* Compute the alignment for a variable for Intel MCU psABI. TYPE is
the data type, and ALIGN is the alignment that the object would
ordinarily have. */
@@ -51900,6 +51911,10 @@ ix86_run_selftests (void)
#undef TARGET_WARN_PARAMETER_PASSING_ABI
#define TARGET_WARN_PARAMETER_PASSING_ABI ix86_warn_parameter_passing_abi
+#undef TARGET_GET_ABI_TYPE
+#define TARGET_GET_ABI_TYPE \
+ix86_get_abi_type
+
#if CHECKING_P
#undef TARGET_RUN_TARGET_SELFTESTS
#define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 2f6b8599d7c..ba3fe9c2e7c 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -290,6 +290,15 @@ enum warn_strict_overflow_code
WARN_STRICT_OVERFLOW_MAGNITUDE = 5
};
+/* Enum values for target ABI types. */
+enum target_abi_type
+{
+ ABI_LP64,
+ ABI_ILP32,
+ ABI_LP64ILP32,
+ ABI_OTHER
+};
+
/* The type of an alias set. Code currently assumes that variables of
this type can take the values 0 (the alias set which aliases
everything) and -1 (sometimes indicating that the alias set is
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 4347f89cd2f..7887217f10a 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1931,6 +1931,10 @@ superset of all other ABIs. @var{call_1} must always be a call insn,
call_2 may be NULL or a call insn.
@end deftypefn
+@deftypefn {Target Hook} {enum target_abi_type} TARGET_GET_ABI_TYPE (void)
+This hooks returns type of target ABI (LP64, ILP32, LP64ILP32 or other).
+@end deftypefn
+
@findex fixed_regs
@findex call_used_regs
@findex global_regs
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 41a6cb11cb0..b36a2064290 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -1711,6 +1711,8 @@ of @code{CALL_USED_REGISTERS}.
@hook TARGET_RETURN_CALL_WITH_MAX_CLOBBERS
+@hook TARGET_GET_ABI_TYPE
+
@findex fixed_regs
@findex call_used_regs
@findex global_regs
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 3314e176881..f4efc3140e3 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "match.h"
#include "parse.h"
#include "constructor.h"
+#include "target.h"
+#include "xregex.h"
/* Macros to access allocate memory for gfc_data_variable,
gfc_data_value and gfc_data. */
@@ -11338,19 +11340,24 @@ gfc_match_gcc_unroll (void)
return MATCH_ERROR;
}
-/* Match a !GCC$ builtin (b) attributes simd flags form:
+/* Match a !GCC$ builtin (b) attributes simd flags if(target) form:
The parameter b is name of a middle-end built-in.
- Flags are one of:
- - (empty)
+ FLAGS is optional and must be one of:
- inbranch
- notinbranch
+ IF(target) is optional and TARGET must be one of:
+ - lp64
+ - ilp32
+ - lp64ilp32
+
When we come here, we have already matched the !GCC$ builtin string. */
match
gfc_match_gcc_builtin (void)
{
char builtin[GFC_MAX_SYMBOL_LEN + 1];
+ char target[GFC_MAX_SYMBOL_LEN + 1];
if (gfc_match (" ( %n ) attributes simd", builtin) != MATCH_YES)
return MATCH_ERROR;
@@ -11361,6 +11368,28 @@ gfc_match_gcc_builtin (void)
else if (gfc_match (" ( inbranch ) ") == MATCH_YES)
clause = SIMD_INBRANCH;
+ if (gfc_match (" if ( %n ) ", target) == MATCH_YES)
+ {
+ enum target_abi_type abi = targetm.get_abi_type ();
+ if (strcmp (target, "lp64") == 0)
+ {
+ if (abi != ABI_LP64)
+ return MATCH_YES;
+ }
+ else if (strcmp (target, "ilp32") == 0)
+ {
+ if (abi != ABI_ILP32)
+ return MATCH_YES;
+ }
+ else if (strcmp (target, "lp64ilp32") == 0)
+ {
+ if (abi != ABI_LP64ILP32)
+ return MATCH_YES;
+ }
+ else
+ return MATCH_ERROR;
+ }
+
if (gfc_vectorized_builtins == NULL)
gfc_vectorized_builtins = new hash_map<nofree_string_hash, int> ();
diff --git a/gcc/target.def b/gcc/target.def
index 05c9cc1da28..d29d1324833 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5791,6 +5791,12 @@ call_2 may be NULL or a call insn.",
rtx_insn *, (rtx_insn *call_1, rtx_insn *call_2),
NULL)
+DEFHOOK
+(get_abi_type,
+ "This hooks returns type of target ABI (LP64, ILP32, LP64ILP32 or other).",
+ enum target_abi_type, (void),
+ NULL)
+
DEFHOOK
(remove_extra_call_preserved_regs,
"This hook removes registers from the set of call-clobbered registers\n\
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 529590b55df..37a04ff1012 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2379,4 +2379,10 @@ default_remove_extra_call_preserved_regs (rtx_insn *, HARD_REG_SET *)
{
}
+enum target_abi_type
+default_get_abi_type (void)
+{
+ return ABI_OTHER;
+}
+
#include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 59436278dcf..5494c5701de 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -286,5 +286,6 @@ extern bool speculation_safe_value_not_needed (bool);
extern rtx default_speculation_safe_value (machine_mode, rtx, rtx, rtx);
extern void default_remove_extra_call_preserved_regs (rtx_insn *,
HARD_REG_SET *);
+extern enum target_abi_type default_get_abi_type (void);
#endif /* GCC_TARGHOOKS_H */
diff --git a/gcc/testsuite/gfortran.dg/simd-builtins-7.f90 b/gcc/testsuite/gfortran.dg/simd-builtins-7.f90
new file mode 100644
index 00000000000..c3ce5543779
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/simd-builtins-7.f90
@@ -0,0 +1,19 @@
+! { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } }
+! { dg-additional-options "-msse2 -mno-avx -nostdinc -Ofast -fpre-include=simd-builtins-7.h -fdump-tree-optimized" }
+
+program test_overloaded_intrinsic
+ real(4) :: x4(3200), y4(3200)
+ real(8) :: x8(3200), y8(3200)
+
+ y4 = sin(x4)
+ print *, y4
+
+ y4 = sin(x8)
+ print *, y8
+end
+
+! { dg-final { scan-tree-dump "sinf.simdclone" "optimized" { target ilp32 } } } */
+! { dg-final { scan-tree-dump-not "sin.simdclone" "optimized" { target ilp32 } } } */
+
+! { dg-final { scan-tree-dump "sin.simdclone" "optimized" { target lp64} } } */
+! { dg-final { scan-tree-dump-not "sinf.simdclone" "optimized" { target lp64 } } } */
diff --git a/gcc/testsuite/gfortran.dg/simd-builtins-7.h b/gcc/testsuite/gfortran.dg/simd-builtins-7.h
new file mode 100644
index 00000000000..1617e1086d0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/simd-builtins-7.h
@@ -0,0 +1,2 @@
+!GCC$ builtin (sin) attributes simd (notinbranch) if(lp64)
+!GCC$ builtin (sinf) attributes simd (notinbranch) if(ilp32)
--
2.20.1