* Backports to gcc-9-branch
@ 2019-06-05 12:24 Jakub Jelinek
0 siblings, 0 replies; 4+ messages in thread
From: Jakub Jelinek @ 2019-06-05 12:24 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 139 bytes --]
Hi!
I've backported following 4 patches from trunk to 9 branch,
bootstrapped/regtested on x86_64-linux and i686-linux, committed.
Jakub
[-- Attachment #2: r271597 --]
[-- Type: text/plain, Size: 2430 bytes --]
2019-06-05 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-24 Jakub Jelinek <jakub@redhat.com>
PR libgomp/90585
* plugin/plugin-hsa.c (print_kernel_dispatch, run_kernel): Use PRIu64
macro instead of "lu".
(release_kernel_dispatch): Likewise. Cast shadow->debug to uintptr_t
before casting to void *.
--- libgomp/plugin/plugin-hsa.c (revision 271596)
+++ libgomp/plugin/plugin-hsa.c (revision 271597)
@@ -1154,8 +1164,9 @@ create_single_kernel_dispatch (struct ke
static void
release_kernel_dispatch (struct GOMP_hsa_kernel_dispatch *shadow)
{
- HSA_DEBUG ("Released kernel dispatch: %p has value: %lu (%p)\n", shadow,
- shadow->debug, (void *) shadow->debug);
+ HSA_DEBUG ("Released kernel dispatch: %p has value: %" PRIu64 " (%p)\n",
+ shadow, shadow->debug,
+ (void *) (uintptr_t) shadow->debug);
hsa_fns.hsa_memory_free_fn (shadow->kernarg_address);
@@ -1276,9 +1287,9 @@ print_kernel_dispatch (struct GOMP_hsa_k
indent_stream (stderr, indent);
fprintf (stderr, "kernarg_address: %p\n", dispatch->kernarg_address);
indent_stream (stderr, indent);
- fprintf (stderr, "object: %lu\n", dispatch->object);
+ fprintf (stderr, "object: %" PRIu64 "\n", dispatch->object);
indent_stream (stderr, indent);
- fprintf (stderr, "signal: %lu\n", dispatch->signal);
+ fprintf (stderr, "signal: %" PRIu64 "\n", dispatch->signal);
indent_stream (stderr, indent);
fprintf (stderr, "private_segment_size: %u\n",
dispatch->private_segment_size);
@@ -1286,8 +1297,8 @@ print_kernel_dispatch (struct GOMP_hsa_k
fprintf (stderr, "group_segment_size: %u\n",
dispatch->group_segment_size);
indent_stream (stderr, indent);
- fprintf (stderr, "children dispatches: %lu\n",
- dispatch->kernel_dispatch_count);
+ fprintf (stderr, "children dispatches: %" PRIu64 "\n",
+ dispatch->kernel_dispatch_count);
indent_stream (stderr, indent);
fprintf (stderr, "omp_num_threads: %u\n",
dispatch->omp_num_threads);
@@ -1594,8 +1605,8 @@ run_kernel (struct kernel_info *kernel,
hsa_signal_t child_s;
child_s.handle = shadow->children_dispatches[i]->signal;
- HSA_DEBUG ("Waiting for children completion signal: %lu\n",
- shadow->children_dispatches[i]->signal);
+ HSA_DEBUG ("Waiting for children completion signal: %" PRIu64 "\n",
+ shadow->children_dispatches[i]->signal);
hsa_fns.hsa_signal_load_acquire_fn (child_s);
}
[-- Attachment #3: r271671 --]
[-- Type: text/plain, Size: 6248 bytes --]
2019-06-05 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-27 Jakub Jelinek <jakub@redhat.com>
PR libgomp/90641
* work.c (gomp_init_work_share): Instead of aligning final ordered
value to multiples of long long alignment, align to that the
first part (ordered team ids) and if inline_ordered_team_ids
is not on a long long alignment boundary within the structure,
use __alignof__ (long long) - 1 pad size always.
* loop.c (GOMP_loop_start): Fix *mem computation if
inline_ordered_team_ids is not aligned on long long alignment boundary
within the structure.
* loop-ull.c (GOMP_loop_ull_start): Likewise.
* sections.c (GOMP_sections2_start): Likewise.
--- libgomp/loop.c (revision 271670)
+++ libgomp/loop.c (revision 271671)
@@ -267,14 +267,17 @@ GOMP_loop_start (long start, long end, l
if (mem)
{
uintptr_t size = (uintptr_t) *mem;
+#define INLINE_ORDERED_TEAM_IDS_OFF \
+ ((offsetof (struct gomp_work_share, inline_ordered_team_ids) \
+ + __alignof__ (long long) - 1) & ~(__alignof__ (long long) - 1))
if (size > (sizeof (struct gomp_work_share)
- - offsetof (struct gomp_work_share,
- inline_ordered_team_ids)))
- thr->ts.work_share->ordered_team_ids
- = gomp_malloc_cleared (size);
+ - INLINE_ORDERED_TEAM_IDS_OFF))
+ *mem
+ = (void *) (thr->ts.work_share->ordered_team_ids
+ = gomp_malloc_cleared (size));
else
- memset (thr->ts.work_share->ordered_team_ids, '\0', size);
- *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ *mem = memset (((char *) thr->ts.work_share)
+ + INLINE_ORDERED_TEAM_IDS_OFF, '\0', size);
}
gomp_work_share_init_done ();
}
@@ -287,7 +290,18 @@ GOMP_loop_start (long start, long end, l
first_reductions);
}
if (mem)
- *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ {
+ if ((offsetof (struct gomp_work_share, inline_ordered_team_ids)
+ & (__alignof__ (long long) - 1)) == 0)
+ *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ else
+ {
+ uintptr_t p = (uintptr_t) thr->ts.work_share->ordered_team_ids;
+ p += __alignof__ (long long) - 1;
+ p &= ~(__alignof__ (long long) - 1);
+ *mem = (void *) p;
+ }
+ }
}
if (!istart)
--- libgomp/loop_ull.c (revision 271670)
+++ libgomp/loop_ull.c (revision 271671)
@@ -266,14 +266,17 @@ GOMP_loop_ull_start (bool up, gomp_ull s
if (mem)
{
uintptr_t size = (uintptr_t) *mem;
+#define INLINE_ORDERED_TEAM_IDS_OFF \
+ ((offsetof (struct gomp_work_share, inline_ordered_team_ids) \
+ + __alignof__ (long long) - 1) & ~(__alignof__ (long long) - 1))
if (size > (sizeof (struct gomp_work_share)
- - offsetof (struct gomp_work_share,
- inline_ordered_team_ids)))
- thr->ts.work_share->ordered_team_ids
- = gomp_malloc_cleared (size);
+ - INLINE_ORDERED_TEAM_IDS_OFF))
+ *mem
+ = (void *) (thr->ts.work_share->ordered_team_ids
+ = gomp_malloc_cleared (size));
else
- memset (thr->ts.work_share->ordered_team_ids, '\0', size);
- *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ *mem = memset (((char *) thr->ts.work_share)
+ + INLINE_ORDERED_TEAM_IDS_OFF, '\0', size);
}
gomp_work_share_init_done ();
}
@@ -286,7 +289,18 @@ GOMP_loop_ull_start (bool up, gomp_ull s
first_reductions);
}
if (mem)
- *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ {
+ if ((offsetof (struct gomp_work_share, inline_ordered_team_ids)
+ & (__alignof__ (long long) - 1)) == 0)
+ *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ else
+ {
+ uintptr_t p = (uintptr_t) thr->ts.work_share->ordered_team_ids;
+ p += __alignof__ (long long) - 1;
+ p &= ~(__alignof__ (long long) - 1);
+ *mem = (void *) p;
+ }
+ }
}
return ialias_call (GOMP_loop_ull_runtime_next) (istart, iend);
--- libgomp/sections.c (revision 271670)
+++ libgomp/sections.c (revision 271671)
@@ -118,14 +118,17 @@ GOMP_sections2_start (unsigned count, ui
if (mem)
{
uintptr_t size = (uintptr_t) *mem;
+#define INLINE_ORDERED_TEAM_IDS_OFF \
+ ((offsetof (struct gomp_work_share, inline_ordered_team_ids) \
+ + __alignof__ (long long) - 1) & ~(__alignof__ (long long) - 1))
if (size > (sizeof (struct gomp_work_share)
- - offsetof (struct gomp_work_share,
- inline_ordered_team_ids)))
- thr->ts.work_share->ordered_team_ids
- = gomp_malloc_cleared (size);
+ - INLINE_ORDERED_TEAM_IDS_OFF))
+ *mem
+ = (void *) (thr->ts.work_share->ordered_team_ids
+ = gomp_malloc_cleared (size));
else
- memset (thr->ts.work_share->ordered_team_ids, '\0', size);
- *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ *mem = memset (((char *) thr->ts.work_share)
+ + INLINE_ORDERED_TEAM_IDS_OFF, '\0', size);
}
gomp_work_share_init_done ();
}
@@ -138,7 +141,18 @@ GOMP_sections2_start (unsigned count, ui
first_reductions);
}
if (mem)
- *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ {
+ if ((offsetof (struct gomp_work_share, inline_ordered_team_ids)
+ & (__alignof__ (long long) - 1)) == 0)
+ *mem = (void *) thr->ts.work_share->ordered_team_ids;
+ else
+ {
+ uintptr_t p = (uintptr_t) thr->ts.work_share->ordered_team_ids;
+ p += __alignof__ (long long) - 1;
+ p &= ~(__alignof__ (long long) - 1);
+ *mem = (void *) p;
+ }
+ }
}
#ifdef HAVE_SYNC_BUILTINS
--- libgomp/work.c (revision 271670)
+++ libgomp/work.c (revision 271671)
@@ -110,9 +110,12 @@ gomp_init_work_share (struct gomp_work_s
if (__builtin_expect (ordered != 1, 0))
{
- ordered += nthreads * sizeof (*ws->ordered_team_ids) - 1;
- ordered = ordered + __alignof__ (long long) - 1;
- ordered &= ~(__alignof__ (long long) - 1);
+ size_t o = nthreads * sizeof (*ws->ordered_team_ids);
+ o += __alignof__ (long long) - 1;
+ if ((offsetof (struct gomp_work_share, inline_ordered_team_ids)
+ & (__alignof__ (long long) - 1)) == 0)
+ o &= ~(__alignof__ (long long) - 1);
+ ordered += o - 1;
}
else
ordered = nthreads * sizeof (*ws->ordered_team_ids);
[-- Attachment #4: r271752 --]
[-- Type: text/plain, Size: 1865 bytes --]
2019-06-05 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-29 Jakub Jelinek <jakub@redhat.com>
PR c++/90598
* tree.c (lvalue_kind): Return clk_none for expressions with
with VOID_TYPE_P.
* g++.dg/cpp0x/pr90598.C: New test.
2019-05-02 Jonathan Wakely <jwakely@redhat.com>
* testsuite/experimental/propagate_const/requirements2.cc: Adjust
dg-error.
--- gcc/cp/tree.c (revision 271751)
+++ gcc/cp/tree.c (revision 271752)
@@ -83,6 +83,10 @@ lvalue_kind (const_tree ref)
if (ref == current_class_ptr)
return clk_none;
+ /* Expressions with cv void type are prvalues. */
+ if (TREE_TYPE (ref) && VOID_TYPE_P (TREE_TYPE (ref)))
+ return clk_none;
+
switch (TREE_CODE (ref))
{
case SAVE_EXPR:
--- gcc/testsuite/g++.dg/cpp0x/pr90598.C (nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/pr90598.C (revision 271752)
@@ -0,0 +1,8 @@
+// PR c++/90598
+// { dg-do compile { target c++11 } }
+
+struct A {};
+using B = decltype(A ().~A ());
+template <typename T> struct C;
+template <> struct C<void> {};
+C<B> t;
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements2.cc (revision 270808)
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements2.cc (revision 270809)
@@ -21,9 +21,8 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
-// { dg-error "not a pointer-to-object type" "" { target *-*-* } 66 }
-// { dg-error "forming pointer to reference type" "" { target *-*-* } 187 }
-// { dg-error "forming pointer to reference type" "" { target *-*-* } 213 }
-
propagate_const<void*> test1;
+
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 0 }
+// { dg-prune-output "forming pointer to reference type" }
+// { dg-prune-output "not a pointer-to-object type" }
[-- Attachment #5: r271952 --]
[-- Type: text/plain, Size: 1069 bytes --]
2019-06-05 Jakub Jelinek <jakub@redhat.com>
PR debug/90733
* var-tracking.c (vt_expand_loc_callback): Don't create raw subregs
with VOIDmode inner operands.
* gcc.dg/pr90733.c: New test.
--- gcc/var-tracking.c (revision 271951)
+++ gcc/var-tracking.c (revision 271952)
@@ -8491,7 +8491,7 @@ vt_expand_loc_callback (rtx x, bitmap re
/* Invalid SUBREGs are ok in debug info. ??? We could try
alternate expansions for the VALUE as well. */
- if (!result)
+ if (!result && GET_MODE (subreg) != VOIDmode)
result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
return result;
--- gcc/testsuite/gcc.dg/pr90733.c (nonexistent)
+++ gcc/testsuite/gcc.dg/pr90733.c (revision 271952)
@@ -0,0 +1,22 @@
+/* PR debug/90733 */
+/* { dg-do compile } */
+/* { dg-options "-g -O2 -w" } */
+
+struct S { unsigned a : 1; };
+union U { struct S b; _Complex unsigned c; };
+
+union U
+foo (union U d)
+{
+ union U e = d;
+ return e;
+}
+
+int
+bar (void)
+{
+ union U x, y;
+ x.c = x.b.a;
+ y = foo (x);
+ return x.c != y.c;
+}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Backports to gcc-9-branch
@ 2019-11-08 19:30 Jakub Jelinek
0 siblings, 0 replies; 4+ messages in thread
From: Jakub Jelinek @ 2019-11-08 19:30 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 153 bytes --]
Hi!
I've backorted following 10 patches from trunk to 9 branch,
bootstrapped/regtested them on x86_64-linux and i686-linux and committed.
Jakub
[-- Attachment #2: r277267 --]
[-- Type: text/plain, Size: 1460 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-10-21 Jakub Jelinek <jakub@redhat.com>
PR c++/92015
* constexpr.c (cxx_eval_component_reference, cxx_eval_bit_field_ref):
Use STRIP_ANY_LOCATION_WRAPPER on CONSTRUCTOR elts.
* g++.dg/cpp0x/constexpr-92015.C: New test.
--- gcc/cp/constexpr.c (revision 277266)
+++ gcc/cp/constexpr.c (revision 277267)
@@ -2887,7 +2887,10 @@ cxx_eval_component_reference (const cons
: field == part)
{
if (value)
- return value;
+ {
+ STRIP_ANY_LOCATION_WRAPPER (value);
+ return value;
+ }
else
/* We're in the middle of initializing it. */
break;
@@ -2977,6 +2980,7 @@ cxx_eval_bit_field_ref (const constexpr_
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
{
tree bitpos = bit_position (field);
+ STRIP_ANY_LOCATION_WRAPPER (value);
if (bitpos == start && DECL_SIZE (field) == TREE_OPERAND (t, 1))
return value;
if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE
--- gcc/testsuite/g++.dg/cpp0x/constexpr-92015.C (nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-92015.C (revision 277267)
@@ -0,0 +1,7 @@
+// PR c++/92015
+// { dg-do compile { target c++11 } }
+
+struct S1 { char c[6] {'h', 'e', 'l', 'l', 'o', 0}; };
+struct S2 { char c[6] = "hello"; };
+static_assert (S1{}.c[0] == 'h', "");
+static_assert (S2{}.c[0] == 'h', "");
[-- Attachment #3: r277291 --]
[-- Type: text/plain, Size: 1105 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-10-22 Tamar Christina <tamar.christina@arm.com>
PR sanitizer/92154
* sanitizer_common/sanitizer_platform_limits_posix.cc:
Cherry-pick compiler-rt revision r375220.
--- libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc (revision 277290)
+++ libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc (revision 277291)
@@ -1126,8 +1126,12 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
-#if !defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)
+#if (!defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \
+ !defined(__arm__)
/* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */
+/* On Arm glibc 2.31 and later provide a different mode field, this field is
+ never used by libsanitizer so we can simply ignore this assert for all glibc
+ versions. */
CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
#endif
[-- Attachment #4: r277293 --]
[-- Type: text/plain, Size: 1028 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-10-22 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/85887
* decl.c (expand_static_init): Drop ECF_LEAF from __cxa_guard_acquire
and __cxa_guard_release.
--- gcc/cp/decl.c (revision 277292)
+++ gcc/cp/decl.c (revision 277293)
@@ -8589,14 +8589,14 @@ expand_static_init (tree decl, tree init
(acquire_name, build_function_type_list (integer_type_node,
TREE_TYPE (guard_addr),
NULL_TREE),
- NULL_TREE, ECF_NOTHROW | ECF_LEAF);
+ NULL_TREE, ECF_NOTHROW);
if (!release_fn || !abort_fn)
vfntype = build_function_type_list (void_type_node,
TREE_TYPE (guard_addr),
NULL_TREE);
if (!release_fn)
release_fn = push_library_fn (release_name, vfntype, NULL_TREE,
- ECF_NOTHROW | ECF_LEAF);
+ ECF_NOTHROW);
if (!abort_fn)
abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE,
ECF_NOTHROW | ECF_LEAF);
[-- Attachment #5: r277492 --]
[-- Type: text/plain, Size: 540 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-10-27 Jakub Jelinek <jakub@redhat.com>
* locales.c (iso_3166): Add missing comma after "United-States".
--- gcc/ada/locales.c (revision 277491)
+++ gcc/ada/locales.c (revision 277492)
@@ -529,7 +529,7 @@ static char* iso_3166[] =
"UM", "United States Minor Outlying Islands",
"US", "United States",
"US", "United States of America",
- "US", "United-States"
+ "US", "United-States",
"UY", "Uruguay",
"UZ", "Uzbekistan",
[-- Attachment #6: r277552 --]
[-- Type: text/plain, Size: 749 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-10-29 Jakub Jelinek <jakub@redhat.com>
* doc/install.texi (--enable-offload-targets): Fix up a typo in the
example, use actual names of supported offload targets.
--- gcc/doc/install.texi (revision 277551)
+++ gcc/doc/install.texi (revision 277552)
@@ -2158,7 +2158,7 @@ specifying paths @var{path1}, @dots{}, @
@smallexample
% @var{srcdir}/configure \
- --enable-offload-target=i686-unknown-linux-gnu=/path/to/i686/compiler,x86_64-pc-linux-gnu
+ --enable-offload-targets=x86_64-intelmicemul-linux-gnu=/path/to/x86_64/compiler,nvptx-none,hsa
@end smallexample
If @samp{hsa} is specified as one of the targets, the compiler will be
[-- Attachment #7: r277656 --]
[-- Type: text/plain, Size: 7079 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-10-31 Jakub Jelinek <jakub@redhat.com>
PR c++/90947
* tree.h (type_initializer_zero_p): Remove.
* tree.c (type_initializer_zero_p): Remove.
* cp-tree.h (type_initializer_zero_p): Declare.
* decl.c (reshape_init_array_1): Formatting fix.
* tree.c (type_initializer_zero_p): New function. Moved from
../tree.c, use next_initializable_field, formatting fix. Return
false for TYPE_NON_AGGREGATE_CLASS types.
--- gcc/tree.c (revision 277655)
+++ gcc/tree.c (revision 277656)
@@ -11123,73 +11123,6 @@ initializer_each_zero_or_onep (const_tre
}
}
-/* Given an initializer INIT for a TYPE, return true if INIT is zero
- so that it can be replaced by value initialization. This function
- distinguishes betwen empty strings as initializers for arrays and
- for pointers (which make it return false). */
-
-bool
-type_initializer_zero_p (tree type, tree init)
-{
- if (type == error_mark_node || init == error_mark_node)
- return false;
-
- STRIP_NOPS (init);
-
- if (POINTER_TYPE_P (type))
- return TREE_CODE (init) != STRING_CST && initializer_zerop (init);
-
- if (TREE_CODE (init) != CONSTRUCTOR)
- return initializer_zerop (init);
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree elt_type = TREE_TYPE (type);
- elt_type = TYPE_MAIN_VARIANT (elt_type);
- if (elt_type == char_type_node)
- return initializer_zerop (init);
-
- tree elt_init;
- unsigned HOST_WIDE_INT i;
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init)
- if (!type_initializer_zero_p (elt_type, elt_init))
- return false;
- return true;
- }
-
- if (TREE_CODE (type) != RECORD_TYPE)
- return initializer_zerop (init);
-
- tree fld = TYPE_FIELDS (type);
-
- tree fld_init;
- unsigned HOST_WIDE_INT i;
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init)
- {
- /* Advance to the next member, skipping over everything that
- canot be initialized (including unnamed bit-fields). */
- while (TREE_CODE (fld) != FIELD_DECL
- || DECL_ARTIFICIAL (fld)
- || (DECL_BIT_FIELD (fld) && !DECL_NAME (fld)))
- {
- fld = DECL_CHAIN (fld);
- if (!fld)
- return true;
- continue;
- }
-
- tree fldtype = TREE_TYPE (fld);
- if (!type_initializer_zero_p (fldtype, fld_init))
- return false;
-
- fld = DECL_CHAIN (fld);
- if (!fld)
- break;
- }
-
- return true;
-}
-
/* Check if vector VEC consists of all the equal elements and
that the number of elements corresponds to the type of VEC.
The function returns first element of the vector
--- gcc/tree.h (revision 277655)
+++ gcc/tree.h (revision 277656)
@@ -4690,12 +4690,6 @@ extern tree first_field (const_tree);
extern bool initializer_zerop (const_tree, bool * = NULL);
extern bool initializer_each_zero_or_onep (const_tree);
-/* Analogous to initializer_zerop but also examines the type for
- which the initializer is being used. Unlike initializer_zerop,
- considers empty strings to be zero initializers for arrays and
- non-zero for pointers. */
-extern bool type_initializer_zero_p (tree, tree);
-
extern wide_int vector_cst_int_elt (const_tree, unsigned int);
extern tree vector_cst_elt (const_tree, unsigned int);
--- gcc/cp/decl.c (revision 277655)
+++ gcc/cp/decl.c (revision 277656)
@@ -5973,9 +5973,8 @@ reshape_init_array_1 (tree elt_type, tre
/* Pointers initialized to strings must be treated as non-zero
even if the string is empty. */
tree init_type = TREE_TYPE (elt_init);
- if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)))
- last_nonzero = index;
- else if (!type_initializer_zero_p (elt_type, elt_init))
+ if (POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)
+ || !type_initializer_zero_p (elt_type, elt_init))
last_nonzero = index;
/* This can happen with an invalid initializer (c++/54501). */
--- gcc/cp/tree.c (revision 277655)
+++ gcc/cp/tree.c (revision 277656)
@@ -5540,6 +5540,68 @@ maybe_warn_zero_as_null_pointer_constant
return false;
}
\f
+/* Given an initializer INIT for a TYPE, return true if INIT is zero
+ so that it can be replaced by value initialization. This function
+ distinguishes betwen empty strings as initializers for arrays and
+ for pointers (which make it return false). */
+
+bool
+type_initializer_zero_p (tree type, tree init)
+{
+ if (type == error_mark_node || init == error_mark_node)
+ return false;
+
+ STRIP_NOPS (init);
+
+ if (POINTER_TYPE_P (type))
+ return TREE_CODE (init) != STRING_CST && initializer_zerop (init);
+
+ if (TREE_CODE (init) != CONSTRUCTOR)
+ return initializer_zerop (init);
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree elt_type = TREE_TYPE (type);
+ elt_type = TYPE_MAIN_VARIANT (elt_type);
+ if (elt_type == char_type_node)
+ return initializer_zerop (init);
+
+ tree elt_init;
+ unsigned HOST_WIDE_INT i;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init)
+ if (!type_initializer_zero_p (elt_type, elt_init))
+ return false;
+ return true;
+ }
+
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return initializer_zerop (init);
+
+ if (TYPE_NON_AGGREGATE_CLASS (type))
+ return false;
+
+ tree fld = TYPE_FIELDS (type);
+
+ tree fld_init;
+ unsigned HOST_WIDE_INT i;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init)
+ {
+ fld = next_initializable_field (fld);
+ if (!fld)
+ return true;
+
+ tree fldtype = TREE_TYPE (fld);
+ if (!type_initializer_zero_p (fldtype, fld_init))
+ return false;
+
+ fld = DECL_CHAIN (fld);
+ if (!fld)
+ break;
+ }
+
+ return true;
+}
+\f
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree
node has been accessed improperly. */
--- gcc/cp/cp-tree.h (revision 277655)
+++ gcc/cp/cp-tree.h (revision 277656)
@@ -7382,6 +7382,11 @@ extern tree cxx_copy_lang_qualifiers (c
extern void cxx_print_statistics (void);
extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t);
+/* Analogous to initializer_zerop but also examines the type for
+ which the initializer is being used. Unlike initializer_zerop,
+ considers empty strings to be zero initializers for arrays and
+ non-zero for pointers. */
+extern bool type_initializer_zero_p (tree, tree);
/* in ptree.c */
extern void cxx_print_xnode (FILE *, tree, int);
--- gcc/testsuite/g++.dg/init/array54.C (nonexistent)
+++ gcc/testsuite/g++.dg/init/array54.C (revision 277656)
@@ -0,0 +1,13 @@
+// PR c++/90947
+// { dg-do run { target c++11 } }
+
+#include <atomic>
+
+static std::atomic<int> a[1] { {1} };
+
+int
+main ()
+{
+ if (a[0].load () != 1)
+ __builtin_abort ();
+}
[-- Attachment #8: r277660 --]
[-- Type: text/plain, Size: 3251 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-10-31 Jakub Jelinek <jakub@redhat.com>
PR middle-end/92231
* tree.h (fndecl_built_in_p): Use fndecl_built_in_p instead of
DECL_BUILT_IN in comment. Remove redundant ()s around return
argument.
* tree.c (free_lang_data_in_decl): Check if var is FUNCTION_DECL
before calling fndecl_built_in_p.
* gimple-fold.c (gimple_fold_stmt_to_constant_1): Check if
TREE_OPERAND (fn, 0) is a FUNCTION_DECL before calling
fndecl_built_in_p on it.
* lto-lang.c (handle_const_attribute): Don't call fndecl_built_in_p
on *node that is not FUNCTION_DECL.
* gcc.c-torture/compile/pr92231.c: New test.
--- gcc/tree.c (revision 277659)
+++ gcc/tree.c (revision 277660)
@@ -5805,7 +5805,8 @@ free_lang_data_in_decl (tree decl, class
while (*nextp)
{
tree var = *nextp;
- if (fndecl_built_in_p (var))
+ if (TREE_CODE (var) == FUNCTION_DECL
+ && fndecl_built_in_p (var))
*nextp = TREE_CHAIN (var);
else
nextp = &TREE_CHAIN (var);
--- gcc/tree.h (revision 277659)
+++ gcc/tree.h (revision 277660)
@@ -6119,12 +6119,12 @@ type_has_mode_precision_p (const_tree t)
Note that it is different from the DECL_IS_BUILTIN accessor. For
instance, user declared prototypes of C library functions are not
- DECL_IS_BUILTIN but may be DECL_BUILT_IN. */
+ DECL_IS_BUILTIN but may be fndecl_built_in_p. */
inline bool
fndecl_built_in_p (const_tree node)
{
- return (DECL_BUILT_IN_CLASS (node) != NOT_BUILT_IN);
+ return DECL_BUILT_IN_CLASS (node) != NOT_BUILT_IN;
}
/* Return true if a FUNCTION_DECL NODE is a GCC built-in function
@@ -6133,7 +6133,7 @@ fndecl_built_in_p (const_tree node)
inline bool
fndecl_built_in_p (const_tree node, built_in_class klass)
{
- return (fndecl_built_in_p (node) && DECL_BUILT_IN_CLASS (node) == klass);
+ return fndecl_built_in_p (node) && DECL_BUILT_IN_CLASS (node) == klass;
}
/* Return true if a FUNCTION_DECL NODE is a GCC built-in function
--- gcc/gimple-fold.c (revision 277659)
+++ gcc/gimple-fold.c (revision 277660)
@@ -6439,6 +6439,7 @@ gimple_fold_stmt_to_constant_1 (gimple *
fn = (*valueize) (gimple_call_fn (stmt));
if (TREE_CODE (fn) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& fndecl_built_in_p (TREE_OPERAND (fn, 0))
&& gimple_builtin_call_types_compatible_p (stmt,
TREE_OPERAND (fn, 0)))
--- gcc/lto/lto-lang.c (revision 277659)
+++ gcc/lto/lto-lang.c (revision 277660)
@@ -305,7 +305,8 @@ handle_const_attribute (tree *node, tree
tree ARG_UNUSED (args), int ARG_UNUSED (flags),
bool * ARG_UNUSED (no_add_attrs))
{
- if (!fndecl_built_in_p (*node))
+ if (TREE_CODE (*node) != FUNCTION_DECL
+ || !fndecl_built_in_p (*node))
inform (UNKNOWN_LOCATION, "%s:%s: %E: %E", __FILE__, __func__, *node, name);
tree type = TREE_TYPE (*node);
--- gcc/testsuite/gcc.c-torture/compile/pr92231.c (nonexistent)
+++ gcc/testsuite/gcc.c-torture/compile/pr92231.c (revision 277660)
@@ -0,0 +1,9 @@
+/* PR middle-end/92231 */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+ return (&bar + 4096) ();
+}
[-- Attachment #9: r277685 --]
[-- Type: text/plain, Size: 7124 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-10-31 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/92296
* internal.h (struct def_pragma_macro): Add is_builtin bitfield.
(_cpp_restore_special_builtin): Declare.
* init.c (_cpp_restore_special_builtin): New function.
* directives.c (do_pragma_push_macro): For NT_BUILTIN_MACRO
set is_builtin and don't try to grab definition.
(cpp_pop_definition): Use _cpp_restore_special_builtin to restore
builtin macros.
* c-c++-common/cpp/pr92296-1.c: New test.
* c-c++-common/cpp/pr92296-2.c: New test.
--- libcpp/directives.c (revision 277684)
+++ libcpp/directives.c (revision 277685)
@@ -1582,6 +1582,8 @@ do_pragma_push_macro (cpp_reader *pfile)
node = _cpp_lex_identifier (pfile, c->name);
if (node->type == NT_VOID)
c->is_undef = 1;
+ else if (node->type == NT_BUILTIN_MACRO)
+ c->is_builtin = 1;
else
{
defn = cpp_macro_definition (pfile, node);
@@ -2470,6 +2472,11 @@ cpp_pop_definition (cpp_reader *pfile, s
if (c->is_undef)
return;
+ if (c->is_builtin)
+ {
+ _cpp_restore_special_builtin (pfile, c);
+ return;
+ }
{
size_t namelen;
--- libcpp/init.c (revision 277684)
+++ libcpp/init.c (revision 277685)
@@ -497,6 +497,25 @@ cpp_init_special_builtins (cpp_reader *p
}
}
+/* Restore macro C to builtin macro definition. */
+
+void
+_cpp_restore_special_builtin (cpp_reader *pfile, struct def_pragma_macro *c)
+{
+ size_t len = strlen (c->name);
+
+ for (const struct builtin_macro *b = builtin_array;
+ b < builtin_array + ARRAY_SIZE (builtin_array); b++)
+ if (b->len == len && memcmp (c->name, b->name, len + 1) == 0)
+ {
+ cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
+ hp->type = NT_BUILTIN_MACRO;
+ if (b->always_warn_if_redefined)
+ hp->flags |= NODE_WARN;
+ hp->value.builtin = (enum cpp_builtin_type) b->value;
+ }
+}
+
/* Read the builtins table above and enter them, and language-specific
macros, into the hash table. HOSTED is true if this is a hosted
environment. */
--- libcpp/internal.h (revision 277684)
+++ libcpp/internal.h (revision 277685)
@@ -391,6 +391,8 @@ struct def_pragma_macro {
/* Mark if we save an undefined macro. */
unsigned int is_undef : 1;
+ /* Nonzero if it was a builtin macro. */
+ unsigned int is_builtin : 1;
};
/* A cpp_reader encapsulates the "state" of a pre-processor run.
@@ -722,6 +724,8 @@ extern void *_cpp_commit_buff (cpp_reade
/* In init.c. */
extern void _cpp_maybe_push_include_file (cpp_reader *);
extern const char *cpp_named_operator2name (enum cpp_ttype type);
+extern void _cpp_restore_special_builtin (cpp_reader *pfile,
+ struct def_pragma_macro *);
/* In directives.c */
extern int _cpp_test_assertion (cpp_reader *, unsigned int *);
--- gcc/testsuite/c-c++-common/cpp/pr92296-1.c (nonexistent)
+++ gcc/testsuite/c-c++-common/cpp/pr92296-1.c (revision 277685)
@@ -0,0 +1,32 @@
+/* PR preprocessor/92296 */
+/* { dg-do preprocess } */
+
+#pragma push_macro("__TIMESTAMP__")
+#pragma pop_macro("__TIMESTAMP__")
+
+#pragma push_macro("__TIME__")
+#pragma pop_macro("__TIME__")
+
+#pragma push_macro("__DATE__")
+#pragma pop_macro("__DATE__")
+
+#pragma push_macro("__FILE__")
+#pragma pop_macro("__FILE__")
+
+#pragma push_macro("__BASE_FILE__")
+#pragma pop_macro("__BASE_FILE__")
+
+#pragma push_macro("__LINE__")
+#pragma pop_macro("__LINE__")
+
+#pragma push_macro("__INCLUDE_LEVEL__")
+#pragma pop_macro("__INCLUDE_LEVEL__")
+
+#pragma push_macro("__COUNTER__")
+#pragma pop_macro("__COUNTER__")
+
+#pragma push_macro("__has_attribute")
+#pragma pop_macro("__has_attribute")
+
+#pragma push_macro("__has_cpp_attribute")
+#pragma pop_macro("__has_cpp_attribute")
--- gcc/testsuite/c-c++-common/cpp/pr92296-2.c (nonexistent)
+++ gcc/testsuite/c-c++-common/cpp/pr92296-2.c (revision 277685)
@@ -0,0 +1,73 @@
+/* PR preprocessor/92296 */
+/* { dg-do preprocess } */
+/* { dg-options "-Wno-builtin-macro-redefined" } */
+
+#pragma push_macro("__TIMESTAMP__")
+#undef __TIMESTAMP__
+#define __TIMESTAMP__ "Thu Oct 31 12:00:00 2019"
+timestamp1 = __TIMESTAMP__
+#pragma pop_macro("__TIMESTAMP__")
+timestamp2 = __TIMESTAMP__
+
+#pragma push_macro("__TIME__")
+#undef __TIME__
+#define __TIME__ "12:00:00"
+time1 = __TIME__
+#pragma pop_macro("__TIME__")
+time2 = __TIME__
+
+#pragma push_macro("__DATE__")
+#undef __DATE__
+#define __DATE__ "Oct 31 2019"
+date1 = __DATE__
+#pragma pop_macro("__DATE__")
+date2 = __DATE__
+
+#pragma push_macro("__FILE__")
+#undef __FILE__
+#define __FILE__ "pr92296-3.c"
+file1 = __FILE__ /* { dg-final { scan-file pr92296-2.i "file1 = \"pr92296-3.c\"" } } */
+#pragma pop_macro("__FILE__")
+file2 = __FILE__ /* { dg-final { scan-file-not pr92296-2.i "file2 = \"pr92296-3.c\"" } } */
+
+#pragma push_macro("__BASE_FILE__")
+#undef __BASE_FILE__
+#define __BASE_FILE__ "pr92296-4.c"
+filebase1 = __BASE_FILE__ /* { dg-final { scan-file pr92296-2.i "filebase1 = \"pr92296-4.c\"" } } */
+#pragma pop_macro("__BASE_FILE__")
+filebase2 = __BASE_FILE__ /* { dg-final { scan-file-not pr92296-2.i "filebase2 = \"pr92296-4.c\"" } } */
+
+#pragma push_macro("__LINE__")
+#undef __LINE__ /* { dg-warning "undefining" } */
+#define __LINE__ 142
+line1 = __LINE__ /* { dg-final { scan-file pr92296-2.i "line1 = 142" } } */
+#pragma pop_macro("__LINE__")
+line2 = __LINE__ /* { dg-final { scan-file pr92296-2.i "line2 = 45" } } */
+
+#pragma push_macro("__INCLUDE_LEVEL__")
+#undef __INCLUDE_LEVEL__ /* { dg-warning "undefining" } */
+#define __INCLUDE_LEVEL__ 42
+includelevel1 = __INCLUDE_LEVEL__ /* { dg-final { scan-file pr92296-2.i "includelevel1 = 42" } } */
+#pragma pop_macro("__INCLUDE_LEVEL__")
+includelevel2 = __INCLUDE_LEVEL__ /* { dg-final { scan-file pr92296-2.i "includelevel2 = 0" } } */
+
+#pragma push_macro("__COUNTER__")
+#undef __COUNTER__ /* { dg-warning "undefining" } */
+#define __COUNTER__ 172
+counter1 = __COUNTER__ /* { dg-final { scan-file pr92296-2.i "counter1 = 172" } } */
+#pragma pop_macro("__COUNTER__")
+counter2 = __COUNTER__ /* { dg-final { scan-file-not pr92296-2.i "counter2 = 172" } } */
+
+#pragma push_macro("__has_attribute")
+#undef __has_attribute /* { dg-warning "undefining" } */
+#define __has_attribute(x) 0
+hasattr1 = __has_attribute(noreturn) /* { dg-final { scan-file pr92296-2.i "hasattr1 = 0" } } */
+#pragma pop_macro("__has_attribute")
+hasattr2 = __has_attribute(noreturn) /* { dg-final { scan-file-not pr92296-2.i "hasattr2 = 0" } } */
+
+#pragma push_macro("__has_cpp_attribute")
+#undef __has_cpp_attribute /* { dg-warning "undefining" } */
+#define __has_cpp_attribute(x) 0
+hasattrcpp1 = __has_cpp_attribute(noreturn) /* { dg-final { scan-file pr92296-2.i "hasattrcpp1 = 0" } } */
+#pragma pop_macro("__has_cpp_attribute")
+hasattrcpp2 = __has_cpp_attribute(noreturn) /* { dg-final { scan-file-not pr92296-2.i "hasattrcpp2 = 0" } } */
[-- Attachment #10: r277819 --]
[-- Type: text/plain, Size: 1198 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-11-05 Jakub Jelinek <jakub@redhat.com>
PR c++/92343
* constexpr.c (potential_constant_expression_1): Return true rather
than false for PREDICT_EXPR.
* g++.dg/cpp2a/attr-likely6.C: New test.
--- gcc/cp/constexpr.c (revision 277818)
+++ gcc/cp/constexpr.c (revision 277819)
@@ -6493,6 +6493,7 @@ potential_constant_expression_1 (tree t,
case LABEL_DECL:
case LABEL_EXPR:
case CASE_LABEL_EXPR:
+ case PREDICT_EXPR:
case CONST_DECL:
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@@ -7354,7 +7355,6 @@ potential_constant_expression_1 (tree t,
return true;
case EMPTY_CLASS_EXPR:
- case PREDICT_EXPR:
return false;
case GOTO_EXPR:
--- gcc/testsuite/g++.dg/cpp2a/attr-likely6.C (nonexistent)
+++ gcc/testsuite/g++.dg/cpp2a/attr-likely6.C (revision 277819)
@@ -0,0 +1,14 @@
+// PR c++/92343
+// { dg-do compile { target c++14 } }
+
+constexpr bool
+foo (bool x)
+{
+ if (x)
+ [[unlikely]] return true;
+ else
+ [[likely]] return false;
+}
+
+static_assert (foo (true), "");
+static_assert (!foo (false), "");
[-- Attachment #11: r277962 --]
[-- Type: text/plain, Size: 2986 bytes --]
2019-11-08 Jakub Jelinek <jakub@redhat.com>
PR c++/92384
* function.c (assign_parm_setup_block, assign_parm_setup_stack): Don't
copy TYPE_EMPTY_P arguments from data->entry_parm to data->stack_parm
slot.
(assign_parms): For TREE_ADDRESSABLE parms with TYPE_EMPTY_P type
force creation of a unique data.stack_parm slot.
* g++.dg/torture/pr92384.C: New test.
--- gcc/function.c (revision 277961)
+++ gcc/function.c (revision 277962)
@@ -3087,7 +3087,7 @@ assign_parm_setup_block (struct assign_p
move_block_from_reg (REGNO (entry_parm), mem,
size_stored / UNITS_PER_WORD);
}
- else if (data->stack_parm == 0)
+ else if (data->stack_parm == 0 && !TYPE_EMPTY_P (data->passed_type))
{
push_to_sequence2 (all->first_conversion_insn, all->last_conversion_insn);
emit_block_move (stack_parm, data->entry_parm, GEN_INT (size),
@@ -3488,7 +3488,9 @@ assign_parm_setup_stack (struct assign_p
dest = validize_mem (copy_rtx (data->stack_parm));
src = validize_mem (copy_rtx (data->entry_parm));
- if (MEM_P (src))
+ if (TYPE_EMPTY_P (data->passed_type))
+ /* Empty types don't really need to be copied. */;
+ else if (MEM_P (src))
{
/* Use a block move to handle potentially misaligned entry_parm. */
if (!to_conversion)
@@ -3643,6 +3645,16 @@ assign_parms (tree fndecl)
{
assign_parm_find_stack_rtl (parm, &data);
assign_parm_adjust_entry_rtl (&data);
+ /* For arguments that occupy no space in the parameter
+ passing area, have non-zero size and have address taken,
+ force creation of a stack slot so that they have distinct
+ address from other parameters. */
+ if (TYPE_EMPTY_P (data.passed_type)
+ && TREE_ADDRESSABLE (parm)
+ && data.entry_parm == data.stack_parm
+ && MEM_P (data.entry_parm)
+ && int_size_in_bytes (data.passed_type))
+ data.stack_parm = NULL_RTX;
}
/* Record permanently how this parm was passed. */
if (data.arg.pass_by_reference)
--- gcc/testsuite/g++.dg/torture/pr92384.C (nonexistent)
+++ gcc/testsuite/g++.dg/torture/pr92384.C (revision 277962)
@@ -0,0 +1,38 @@
+// PR c++/92384
+// { dg-do run }
+
+struct S {};
+struct T : public S { S a, b, c, d, e, f, g, h, i, j, k, l, m; };
+struct U { long long a, b, c; };
+
+U
+foo (S, S, S, T, T, T, U g)
+{
+ return g;
+}
+
+__attribute__((noipa)) bool
+bar (S a, S b, S c, T d, T e, T f, U g, void **h)
+{
+ h[0] = (void *) &a;
+ h[1] = (void *) &b;
+ h[2] = (void *) &c;
+ h[3] = (void *) &d;
+ h[4] = (void *) &e;
+ h[5] = (void *) &f;
+ h[6] = (void *) &g;
+ asm volatile ("" : : "r" (h) : "memory");
+ return (h[0] != h[1] && h[1] != h[2] && h[2] != h[3]
+ && h[3] != h[4] && h[4] != h[5] && h[5] != h[6]);
+}
+
+int
+main ()
+{
+ S a;
+ T b;
+ U c = { 1, 2, 3 };
+ void *d[7];
+ if (!bar (a, a, a, b, b, b, c, d))
+ __builtin_abort ();
+}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Backports to gcc-9-branch
@ 2019-08-01 6:34 Jakub Jelinek
0 siblings, 0 replies; 4+ messages in thread
From: Jakub Jelinek @ 2019-08-01 6:34 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 150 bytes --]
Hi!
I've backported following 5 patches from trunk to 9.2,
bootstrapped/regtested on x86_64-linux and i686-linux, committed to
gcc-9-branch.
Jakub
[-- Attachment #2: r273543 --]
[-- Type: text/plain, Size: 6416 bytes --]
2019-08-01 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-07-17 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/91157
* tree-vect-generic.c (expand_vector_comparison): Handle lhs being
a vector boolean with scalar mode.
(expand_vector_condition): Handle first operand being a vector boolean
with scalar mode.
(expand_vector_operations_1): For comparisons, don't bail out early
if the return type is vector boolean with scalar mode, but comparison
operand type is not.
* gcc.target/i386/avx512f-pr91157.c: New test.
* gcc.target/i386/avx512bw-pr91157.c: New test.
--- gcc/tree-vect-generic.c (revision 273542)
+++ gcc/tree-vect-generic.c (revision 273545)
@@ -382,8 +382,47 @@ expand_vector_comparison (gimple_stmt_it
tree t;
if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code)
&& !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code))
- t = expand_vector_piecewise (gsi, do_compare, type,
- TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
+ {
+ if (VECTOR_BOOLEAN_TYPE_P (type)
+ && SCALAR_INT_MODE_P (TYPE_MODE (type))
+ && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
+ TYPE_VECTOR_SUBPARTS (type)
+ * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
+ (TREE_TYPE (type)))))
+ {
+ tree inner_type = TREE_TYPE (TREE_TYPE (op0));
+ tree part_width = TYPE_SIZE (inner_type);
+ tree index = bitsize_int (0);
+ int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0));
+ int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type));
+ tree ret_type = build_nonstandard_integer_type (prec, 1);
+ tree ret_inner_type = boolean_type_node;
+ int i;
+ location_t loc = gimple_location (gsi_stmt (*gsi));
+ t = build_zero_cst (ret_type);
+
+ if (TYPE_PRECISION (ret_inner_type) != 1)
+ ret_inner_type = build_nonstandard_integer_type (1, 1);
+ warning_at (loc, OPT_Wvector_operation_performance,
+ "vector operation will be expanded piecewise");
+ for (i = 0; i < nunits;
+ i++, index = int_const_binop (PLUS_EXPR, index, part_width))
+ {
+ tree a = tree_vec_extract (gsi, inner_type, op0, part_width,
+ index);
+ tree b = tree_vec_extract (gsi, inner_type, op1, part_width,
+ index);
+ tree result = gimplify_build2 (gsi, code, ret_inner_type, a, b);
+ t = gimplify_build3 (gsi, BIT_INSERT_EXPR, ret_type, t, result,
+ bitsize_int (i));
+ }
+ t = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
+ }
+ else
+ t = expand_vector_piecewise (gsi, do_compare, type,
+ TREE_TYPE (TREE_TYPE (op0)), op0, op1,
+ code);
+ }
else
t = NULL_TREE;
@@ -879,6 +918,7 @@ expand_vector_condition (gimple_stmt_ite
tree a1 = a;
tree a2 = NULL_TREE;
bool a_is_comparison = false;
+ bool a_is_scalar_bitmask = false;
tree b = gimple_assign_rhs2 (stmt);
tree c = gimple_assign_rhs3 (stmt);
vec<constructor_elt, va_gc> *v;
@@ -942,6 +982,20 @@ expand_vector_condition (gimple_stmt_ite
warning_at (loc, OPT_Wvector_operation_performance,
"vector condition will be expanded piecewise");
+ if (!a_is_comparison
+ && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))
+ && SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a)))
+ && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (a))
+ * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
+ (TREE_TYPE (TREE_TYPE (a))))))
+ {
+ a_is_scalar_bitmask = true;
+ int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a)));
+ tree atype = build_nonstandard_integer_type (prec, 1);
+ a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a);
+ }
+
int nunits = nunits_for_known_piecewise_op (type);
vec_alloc (v, nunits);
for (i = 0; i < nunits; i++)
@@ -957,6 +1011,14 @@ expand_vector_condition (gimple_stmt_ite
comp_width, comp_index);
aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2);
}
+ else if (a_is_scalar_bitmask)
+ {
+ wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a)));
+ result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a),
+ a, wide_int_to_tree (TREE_TYPE (a), w));
+ aa = fold_build2 (NE_EXPR, boolean_type_node, result,
+ build_zero_cst (TREE_TYPE (a)));
+ }
else
aa = tree_vec_extract (gsi, cond_type, a, width, index);
result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
@@ -1941,7 +2003,11 @@ expand_vector_operations_1 (gimple_stmt_
/* A scalar operation pretending to be a vector one. */
if (VECTOR_BOOLEAN_TYPE_P (type)
&& !VECTOR_MODE_P (TYPE_MODE (type))
- && TYPE_MODE (type) != BLKmode)
+ && TYPE_MODE (type) != BLKmode
+ && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison
+ || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))
+ && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1)))
+ && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode)))
return;
/* If the vector operation is operating on all same vector elements
--- gcc/testsuite/gcc.target/i386/avx512bw-pr91157.c (nonexistent)
+++ gcc/testsuite/gcc.target/i386/avx512bw-pr91157.c (revision 273543)
@@ -0,0 +1,6 @@
+/* PR tree-optimization/91157 */
+/* { dg-do run { target { avx512bw && lp64 } } } */
+/* { dg-options "-O2 -mavx512bw -fexceptions -fnon-call-exceptions -fsignaling-nans" } */
+
+#define AVX512BW
+#include "avx512f-pr91157.c"
--- gcc/testsuite/gcc.target/i386/avx512f-pr91157.c (nonexistent)
+++ gcc/testsuite/gcc.target/i386/avx512f-pr91157.c (revision 273543)
@@ -0,0 +1,29 @@
+/* PR tree-optimization/91157 */
+/* { dg-do run { target { avx512f && lp64 } } } */
+/* { dg-options "-O2 -mavx512f -fexceptions -fnon-call-exceptions -fsignaling-nans" } */
+
+#include "avx512f-helper.h"
+
+typedef long double V __attribute__ ((vector_size (4 * sizeof (long double))));
+typedef __int128 W __attribute__ ((vector_size (4 * sizeof (__int128))));
+
+__attribute__((noipa)) W
+foo (V x)
+{
+ return x == 0;
+}
+
+static void
+test_512 (void)
+{
+ V a = { 5.0L, 0.0L, -0.0L, -17.0L };
+ V b = { -0.0L, 16.0L, 0.0L, 18.0L };
+ V c = { 6.0L, 7.0L, 8.0L, 0.0L };
+ W ar = foo (a);
+ W br = foo (b);
+ W cr = foo (c);
+ if (ar[0] != 0 || ar[1] != -1 || ar[2] != -1 || ar[3] != 0
+ || br[0] != -1 || br[1] != 0 || br[2] != -1 || br[3] != 0
+ || cr[0] != 0 || cr[1] != 0 || cr[2] != 0 || cr[3] != -1)
+ __builtin_abort ();
+}
[-- Attachment #3: r273897 --]
[-- Type: text/plain, Size: 2176 bytes --]
2019-08-01 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-07-30 Jakub Jelinek <jakub@redhat.com>
PR target/91150
* config/i386/i386.c (expand_vec_perm_blend): Change mask type
from unsigned to unsigned HOST_WIDE_INT. For E_V64QImode cast
comparison to unsigned HOST_WIDE_INT before shifting it left.
* gcc.target/i386/avx512bw-pr91150.c: New test.
--- gcc/config/i386/i386.c (revision 273896)
+++ gcc/config/i386/i386.c (revision 273897)
@@ -16385,7 +16385,8 @@ static bool
expand_vec_perm_blend (struct expand_vec_perm_d *d)
{
machine_mode mmode, vmode = d->vmode;
- unsigned i, mask, nelt = d->nelt;
+ unsigned i, nelt = d->nelt;
+ unsigned HOST_WIDE_INT mask;
rtx target, op0, op1, maskop, x;
rtx rperm[32], vperm;
@@ -16439,7 +16440,7 @@ expand_vec_perm_blend (struct expand_vec
case E_V16SImode:
case E_V8DImode:
for (i = 0; i < nelt; ++i)
- mask |= (d->perm[i] >= nelt) << i;
+ mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
break;
case E_V2DImode:
--- gcc/testsuite/gcc.target/i386/avx512bw-pr91150.c (nonexistent)
+++ gcc/testsuite/gcc.target/i386/avx512bw-pr91150.c (revision 273897)
@@ -0,0 +1,37 @@
+/* PR target/91150 */
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512bw" } */
+/* { dg-require-effective-target avx512bw } */
+
+#include "avx512bw-check.h"
+
+typedef unsigned char V __attribute__((vector_size (64)));
+
+__attribute__((noipa)) void
+foo (V *x, V *y, V *z)
+{
+ *x = __builtin_shuffle (*y, *z, (V) { 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127 });
+}
+
+static void
+avx512bw_test (void)
+{
+ union U { unsigned char a[64]; V v; } a, b, c;
+ int i;
+ for (i = 0; i < 64; i++)
+ {
+ b.a[i] = i + 1;
+ c.a[i] = i + 65;
+ }
+ foo (&a.v, &b.v, &c.v);
+ for (i = 0; i < 64; i++)
+ if (a.a[i] != (i < 16 ? i + 1 : i + 65))
+ __builtin_abort ();
+}
[-- Attachment #4: r273898 --]
[-- Type: text/plain, Size: 3428 bytes --]
2019-08-01 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-07-30 Jakub Jelinek <jakub@redhat.com>
PR middle-end/91216
* omp-low.c (global_nonaddressable_vars): New variable.
(use_pointer_for_field): For global decls, if they are non-addressable,
remember it in the global_nonaddressable_vars bitmap, if they are
addressable and in the global_nonaddressable_vars bitmap, ignore their
TREE_ADDRESSABLE bit.
(omp_copy_decl_2): Clear TREE_ADDRESSABLE also on private copies of
vars in global_nonaddressable_vars bitmap.
(execute_lower_omp): Free global_nonaddressable_vars bitmap.
* gcc.dg/gomp/pr91216.c: New test.
--- gcc/omp-low.c (revision 273897)
+++ gcc/omp-low.c (revision 273898)
@@ -162,6 +162,7 @@ static splay_tree all_contexts;
static int taskreg_nesting_level;
static int target_nesting_level;
static bitmap task_shared_vars;
+static bitmap global_nonaddressable_vars;
static vec<omp_context *> taskreg_contexts;
static void scan_omp (gimple_seq *, omp_context *);
@@ -426,7 +427,26 @@ use_pointer_for_field (tree decl, omp_co
/* Do not use copy-in/copy-out for variables that have their
address taken. */
- if (TREE_ADDRESSABLE (decl))
+ if (is_global_var (decl))
+ {
+ /* For file scope vars, track whether we've seen them as
+ non-addressable initially and in that case, keep the same
+ answer for the duration of the pass, even when they are made
+ addressable later on e.g. through reduction expansion. Global
+ variables which weren't addressable before the pass will not
+ have their privatized copies address taken. See PR91216. */
+ if (!TREE_ADDRESSABLE (decl))
+ {
+ if (!global_nonaddressable_vars)
+ global_nonaddressable_vars = BITMAP_ALLOC (NULL);
+ bitmap_set_bit (global_nonaddressable_vars, DECL_UID (decl));
+ }
+ else if (!global_nonaddressable_vars
+ || !bitmap_bit_p (global_nonaddressable_vars,
+ DECL_UID (decl)))
+ return true;
+ }
+ else if (TREE_ADDRESSABLE (decl))
return true;
/* lower_send_shared_vars only uses copy-in, but not copy-out
@@ -504,8 +524,10 @@ omp_copy_decl_2 (tree var, tree name, tr
it's address. But we don't need to take address of privatizations
from that var. */
if (TREE_ADDRESSABLE (var)
- && task_shared_vars
- && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
+ && ((task_shared_vars
+ && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
+ || (global_nonaddressable_vars
+ && bitmap_bit_p (global_nonaddressable_vars, DECL_UID (var)))))
TREE_ADDRESSABLE (copy) = 0;
ctx->block_vars = copy;
@@ -12730,6 +12752,7 @@ execute_lower_omp (void)
all_contexts = NULL;
}
BITMAP_FREE (task_shared_vars);
+ BITMAP_FREE (global_nonaddressable_vars);
/* If current function is a method, remove artificial dummy VAR_DECL created
for non-static data member privatization, they aren't needed for
--- gcc/testsuite/gcc.dg/gomp/pr91216.c (nonexistent)
+++ gcc/testsuite/gcc.dg/gomp/pr91216.c (revision 273898)
@@ -0,0 +1,20 @@
+/* PR middle-end/91216 */
+
+int r;
+
+void
+foo (int *a)
+{
+ int i;
+ #pragma omp for reduction(+:r)
+ for (i = 0; i < 64; i++)
+ a[i] = i;
+ #pragma omp for private (r)
+ for (i = 0; i < 64; i++)
+ {
+ r = 0;
+ #pragma omp parallel shared(r)
+ #pragma omp master
+ r = r + 1;
+ }
+}
[-- Attachment #5: r273922 --]
[-- Type: text/plain, Size: 7171 bytes --]
2019-08-01 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-07-31 Jakub Jelinek <jakub@redhat.com>
PR middle-end/91301
* gimplify.c (gimplify_omp_for): If for class iterator on
distribute parallel for there is no data sharing clause
on inner_for_stmt, look for private clause on combined
parallel too and if found, move it to inner_for_stmt.
* testsuite/libgomp.c++/for-27.C: New test.
--- gcc/gimplify.c (revision 273921)
+++ gcc/gimplify.c (revision 273922)
@@ -10663,6 +10663,22 @@ gimplify_omp_for (tree *expr_p, gimple_s
&& OMP_CLAUSE_DECL (*pc) == orig_decl)
break;
if (*pc == NULL_TREE)
+ {
+ tree *spc;
+ for (spc = &OMP_PARALLEL_CLAUSES (*data[1]);
+ *spc; spc = &OMP_CLAUSE_CHAIN (*spc))
+ if (OMP_CLAUSE_CODE (*spc) == OMP_CLAUSE_PRIVATE
+ && OMP_CLAUSE_DECL (*spc) == orig_decl)
+ break;
+ if (*spc)
+ {
+ tree c = *spc;
+ *spc = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = NULL_TREE;
+ *pc = c;
+ }
+ }
+ if (*pc == NULL_TREE)
;
else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE)
{
--- libgomp/testsuite/libgomp.c++/for-27.C (nonexistent)
+++ libgomp/testsuite/libgomp.c++/for-27.C (revision 273922)
@@ -0,0 +1,169 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+int a[2000];
+
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+static inline void
+baz (int i)
+{
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp simd
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp distribute parallel for
+ for (i = x; i <= y; i += 6)
+ baz (*i);
+}
+
+void
+f3 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp distribute parallel for private (i)
+ for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+ baz (*i);
+}
+
+void
+f4 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp teams distribute parallel for lastprivate (i)
+ for (i = x + 2000 - 64; i > y + 10; --i)
+ baz (*i);
+}
+
+#define check(expr) \
+ for (int i = 0; i < 2000; i++) \
+ if (expr) \
+ { \
+ if (results[i] != 1) \
+ abort (); \
+ results[i] = 0; \
+ } \
+ else if (results[i]) \
+ abort ()
+
+int
+main ()
+{
+ for (int i = 0; i < 2000; i++)
+ a[i] = i;
+ f1 ();
+ check (1);
+ #pragma omp teams
+ f2 (&a[10], &a[1990]);
+ check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+ #pragma omp teams
+ f3 (&a[0], &a[1999]);
+ check (i < 1998 && (i & 1) == 0);
+ f4 (&a[0], &a[30]);
+ check (i > 40 && i <= 2000 - 64);
+}
[-- Attachment #6: r273935 --]
[-- Type: text/plain, Size: 767 bytes --]
2019-08-01 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-07-31 Jakub Jelinek <jakub@redhat.com>
PR c/91192
* c-parser.c (c_parser_sizeof_expression): Call set_c_expr_source_range
even if finish is UNKNOWN_LOCATION, just use start as finish in that
case.
--- gcc/c/c-parser.c (revision 273934)
+++ gcc/c/c-parser.c (revision 273935)
@@ -7477,8 +7477,9 @@ c_parser_sizeof_expression (c_parser *pa
error_at (expr_loc, "%<sizeof%> applied to a bit-field");
result = c_expr_sizeof_expr (expr_loc, expr);
}
- if (finish != UNKNOWN_LOCATION)
- set_c_expr_source_range (&result, start, finish);
+ if (finish == UNKNOWN_LOCATION)
+ finish = start;
+ set_c_expr_source_range (&result, start, finish);
return result;
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Backports to gcc-9-branch
@ 2019-05-17 20:00 Jakub Jelinek
0 siblings, 0 replies; 4+ messages in thread
From: Jakub Jelinek @ 2019-05-17 20:00 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 144 bytes --]
Hi!
I've backported following 11 patches from trunk to gcc-9-branch,
bootstrapped/regtested on x86_64-linux and i686-linux, committed.
Jakub
[-- Attachment #2: r270606 --]
[-- Type: text/plain, Size: 9616 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-04-26 Jakub Jelinek <jakub@redhat.com>
PR debug/90197
* c-tree.h (c_finish_loop): Add 2 further location_t arguments.
* c-parser.c (c_parser_while_statement): Adjust c_finish_loop caller.
(c_parser_do_statement): Likewise.
(c_parser_for_statement): Likewise. Formatting fixes.
* c-typeck.c (c_finish_loop): Add COND_LOCUS and INCR_LOCUS arguments,
emit DEBUG_BEGIN_STMTs if needed.
--- gcc/c/c-tree.h (revision 270605)
+++ gcc/c/c-tree.h (revision 270606)
@@ -694,7 +694,8 @@ extern int c_types_compatible_p (tree, t
extern tree c_begin_compound_stmt (bool);
extern tree c_end_compound_stmt (location_t, tree, bool);
extern void c_finish_if_stmt (location_t, tree, tree, tree);
-extern void c_finish_loop (location_t, tree, tree, tree, tree, tree, bool);
+extern void c_finish_loop (location_t, location_t, tree, location_t, tree,
+ tree, tree, tree, bool);
extern tree c_begin_stmt_expr (void);
extern tree c_finish_stmt_expr (location_t, tree);
extern tree c_process_expr_stmt (location_t, tree);
--- gcc/c/c-parser.c (revision 270605)
+++ gcc/c/c-parser.c (revision 270606)
@@ -6001,7 +6001,8 @@ c_parser_while_statement (c_parser *pars
location_t loc_after_labels;
bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
- c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
+ c_finish_loop (loc, loc, cond, UNKNOWN_LOCATION, NULL, body,
+ c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_parser_maybe_reclassify_token (parser);
@@ -6046,6 +6047,7 @@ c_parser_do_statement (c_parser *parser,
c_break_label = save_break;
new_cont = c_cont_label;
c_cont_label = save_cont;
+ location_t cond_loc = c_parser_peek_token (parser)->location;
cond = c_parser_paren_condition (parser);
if (ivdep && cond != error_mark_node)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
@@ -6059,7 +6061,8 @@ c_parser_do_statement (c_parser *parser,
build_int_cst (integer_type_node, unroll));
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
c_parser_skip_to_end_of_block_or_statement (parser);
- c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
+ c_finish_loop (loc, cond_loc, cond, UNKNOWN_LOCATION, NULL, body,
+ new_break, new_cont, false);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
@@ -6132,7 +6135,9 @@ c_parser_for_statement (c_parser *parser
/* Silence the bogus uninitialized warning. */
tree collection_expression = NULL;
location_t loc = c_parser_peek_token (parser)->location;
- location_t for_loc = c_parser_peek_token (parser)->location;
+ location_t for_loc = loc;
+ location_t cond_loc = UNKNOWN_LOCATION;
+ location_t incr_loc = UNKNOWN_LOCATION;
bool is_foreach_statement = false;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
token_indent_info for_tinfo
@@ -6166,7 +6171,8 @@ c_parser_for_statement (c_parser *parser
c_parser_consume_token (parser);
is_foreach_statement = true;
if (check_for_loop_decls (for_loc, true) == NULL_TREE)
- c_parser_error (parser, "multiple iterating variables in fast enumeration");
+ c_parser_error (parser, "multiple iterating variables in "
+ "fast enumeration");
}
else
check_for_loop_decls (for_loc, flag_isoc99);
@@ -6196,7 +6202,8 @@ c_parser_for_statement (c_parser *parser
c_parser_consume_token (parser);
is_foreach_statement = true;
if (check_for_loop_decls (for_loc, true) == NULL_TREE)
- c_parser_error (parser, "multiple iterating variables in fast enumeration");
+ c_parser_error (parser, "multiple iterating variables in "
+ "fast enumeration");
}
else
check_for_loop_decls (for_loc, flag_isoc99);
@@ -6218,15 +6225,18 @@ c_parser_for_statement (c_parser *parser
c_parser_consume_token (parser);
is_foreach_statement = true;
if (! lvalue_p (init_expression))
- c_parser_error (parser, "invalid iterating variable in fast enumeration");
- object_expression = c_fully_fold (init_expression, false, NULL);
+ c_parser_error (parser, "invalid iterating variable in "
+ "fast enumeration");
+ object_expression
+ = c_fully_fold (init_expression, false, NULL);
}
else
{
ce = convert_lvalue_to_rvalue (loc, ce, true, false);
init_expression = ce.value;
c_finish_expr_stmt (loc, init_expression);
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ c_parser_skip_until_found (parser, CPP_SEMICOLON,
+ "expected %<;%>");
}
}
}
@@ -6235,18 +6245,19 @@ c_parser_for_statement (c_parser *parser
gcc_assert (!parser->objc_could_be_foreach_context);
if (!is_foreach_statement)
{
+ cond_loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
if (ivdep)
{
- c_parser_error (parser, "missing loop condition in loop with "
- "%<GCC ivdep%> pragma");
+ c_parser_error (parser, "missing loop condition in loop "
+ "with %<GCC ivdep%> pragma");
cond = error_mark_node;
}
else if (unroll)
{
- c_parser_error (parser, "missing loop condition in loop with "
- "%<GCC unroll%> pragma");
+ c_parser_error (parser, "missing loop condition in loop "
+ "with %<GCC unroll%> pragma");
cond = error_mark_node;
}
else
@@ -6275,11 +6286,13 @@ c_parser_for_statement (c_parser *parser
/* Parse the increment expression (the third expression in a
for-statement). In the case of a foreach-statement, this is
the expression that follows the 'in'. */
+ loc = incr_loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
if (is_foreach_statement)
{
- c_parser_error (parser, "missing collection in fast enumeration");
+ c_parser_error (parser,
+ "missing collection in fast enumeration");
collection_expression = error_mark_node;
}
else
@@ -6288,8 +6301,8 @@ c_parser_for_statement (c_parser *parser
else
{
if (is_foreach_statement)
- collection_expression = c_fully_fold (c_parser_expression (parser).value,
- false, NULL);
+ collection_expression
+ = c_fully_fold (c_parser_expression (parser).value, false, NULL);
else
{
struct c_expr ce = c_parser_expression (parser);
@@ -6312,10 +6325,14 @@ c_parser_for_statement (c_parser *parser
body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
if (is_foreach_statement)
- objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
+ objc_finish_foreach_loop (for_loc, object_expression,
+ collection_expression, body, c_break_label,
+ c_cont_label);
else
- c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
- add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
+ c_finish_loop (for_loc, cond_loc, cond, incr_loc, incr, body,
+ c_break_label, c_cont_label, true);
+ add_stmt (c_end_compound_stmt (for_loc, block,
+ flag_isoc99 || c_dialect_objc ()));
c_parser_maybe_reclassify_token (parser);
token_indent_info next_tinfo
--- gcc/c/c-typeck.c (revision 270605)
+++ gcc/c/c-typeck.c (revision 270606)
@@ -10858,11 +10858,14 @@ c_finish_if_stmt (location_t if_locus, t
the beginning of the loop. COND is the loop condition. COND_IS_FIRST
is false for DO loops. INCR is the FOR increment expression. BODY is
the statement controlled by the loop. BLAB is the break label. CLAB is
- the continue label. Everything is allowed to be NULL. */
+ the continue label. Everything is allowed to be NULL.
+ COND_LOCUS is the location of the loop condition, INCR_LOCUS is the
+ location of the FOR increment expression. */
void
-c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
- tree blab, tree clab, bool cond_is_first)
+c_finish_loop (location_t start_locus, location_t cond_locus, tree cond,
+ location_t incr_locus, tree incr, tree body, tree blab,
+ tree clab, bool cond_is_first)
{
tree entry = NULL, exit = NULL, t;
@@ -10904,12 +10907,8 @@ c_finish_loop (location_t start_locus, t
}
t = build_and_jump (&blab);
- if (cond_is_first)
- exit = fold_build3_loc (start_locus,
- COND_EXPR, void_type_node, cond, exit, t);
- else
- exit = fold_build3_loc (input_location,
- COND_EXPR, void_type_node, cond, exit, t);
+ exit = fold_build3_loc (cond_is_first ? start_locus : input_location,
+ COND_EXPR, void_type_node, cond, exit, t);
}
else
{
@@ -10930,9 +10929,23 @@ c_finish_loop (location_t start_locus, t
if (clab)
add_stmt (build1 (LABEL_EXPR, void_type_node, clab));
if (incr)
- add_stmt (incr);
+ {
+ if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
+ {
+ t = build0 (DEBUG_BEGIN_STMT, void_type_node);
+ SET_EXPR_LOCATION (t, incr_locus);
+ add_stmt (t);
+ }
+ add_stmt (incr);
+ }
if (entry)
add_stmt (entry);
+ if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
+ {
+ t = build0 (DEBUG_BEGIN_STMT, void_type_node);
+ SET_EXPR_LOCATION (t, cond_locus);
+ add_stmt (t);
+ }
if (exit)
add_stmt (exit);
if (blab)
[-- Attachment #3: r270835 --]
[-- Type: text/plain, Size: 1397 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-03 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/90303
* ipa-devirt.c (obj_type_ref_class, get_odr_type): Don't use
TYPE_CANONICAL for TYPE_STRUCTURAL_EQUALITY_P types in !in_lto_p mode.
* g++.target/i386/pr90303.C: New test.
--- gcc/ipa-devirt.c (revision 270834)
+++ gcc/ipa-devirt.c (revision 270835)
@@ -2020,7 +2020,7 @@ obj_type_ref_class (const_tree ref)
ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
tree ret = TREE_TYPE (ref);
- if (!in_lto_p)
+ if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (ret))
ret = TYPE_CANONICAL (ret);
else
ret = get_odr_type (ret)->type;
@@ -2042,7 +2042,7 @@ get_odr_type (tree type, bool insert)
int base_id = -1;
type = TYPE_MAIN_VARIANT (type);
- if (!in_lto_p)
+ if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type))
type = TYPE_CANONICAL (type);
gcc_checking_assert (can_be_name_hashed_p (type)
--- gcc/testsuite/g++.target/i386/pr90303.C (nonexistent)
+++ gcc/testsuite/g++.target/i386/pr90303.C (revision 270835)
@@ -0,0 +1,8 @@
+// PR tree-optimization/90303
+// { dg-do compile { target ia32 } }
+// { dg-additional-options "-O2" }
+
+struct A { virtual void foo (); };
+template <class> class B : A {};
+typedef void (__attribute__((fastcall)) F) ();
+B<F> e;
[-- Attachment #4: r271055 --]
[-- Type: text/plain, Size: 3308 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-10 Jakub Jelinek <jakub@redhat.com>
PR pch/90326
cp/
* config-lang.in (gtfiles): Remove c-family/c-lex.c, add
c-family/c-cppbuiltin.c.
objc/
* config-lang.in (gtfiles): Add c-family/c-format.c.
objcp/
* config-lang.in (gtfiles): Don't add c-family/c-cppbuiltin.c.
testsuite/
* g++.dg/pch/pr90326.C: New test.
* g++.dg/pch/pr90326.Hs: New file.
--- gcc/cp/config-lang.in (revision 271054)
+++ gcc/cp/config-lang.in (revision 271055)
@@ -37,7 +37,7 @@ gtfiles="\
\$(srcdir)/c-family/c-pragma.h \$(srcdir)/cp/decl.h \
\$(srcdir)/cp/parser.h \
\$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-format.c \
-\$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.c \
+\$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.c \
\$(srcdir)/cp/call.c \$(srcdir)/cp/class.c \$(srcdir)/cp/constexpr.c \
\$(srcdir)/cp/cp-gimplify.c \
\$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/cp-objcp-common.c \
--- gcc/objc/config-lang.in (revision 271054)
+++ gcc/objc/config-lang.in (revision 271055)
@@ -35,4 +35,4 @@ lang_requires="c"
# Order is important. If you change this list, make sure you test
# building without C++ as well; that is, remove the gcc/cp directory,
# and build with --enable-languages=c,objc.
-gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
+gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c-family/c-format.c"
--- gcc/objcp/config-lang.in (revision 271054)
+++ gcc/objcp/config-lang.in (revision 271055)
@@ -52,7 +52,6 @@ gtfiles="$(. $srcdir/cp/config-lang.in ;
gtfiles="$gtfiles \
\$(srcdir)/objc/objc-act.h \
\$(srcdir)/objc/objc-map.h \
-\$(srcdir)/c-family/c-cppbuiltin.c \
\$(srcdir)/objc/objc-act.c \
\$(srcdir)/objc/objc-gnu-runtime-abi-01.c \
\$(srcdir)/objc/objc-next-runtime-abi-01.c \
--- gcc/testsuite/g++.dg/pch/pr90326.Hs (nonexistent)
+++ gcc/testsuite/g++.dg/pch/pr90326.Hs (revision 271055)
@@ -0,0 +1 @@
+// empty
--- gcc/testsuite/g++.dg/pch/pr90326.C (nonexistent)
+++ gcc/testsuite/g++.dg/pch/pr90326.C (revision 271055)
@@ -0,0 +1,9 @@
+#include "pr90326.H"
+
+int main()
+{
+ float f = __FLT_MAX__;
+ if (f == 0.0)
+ __builtin_abort ();
+ return 0;
+}
[-- Attachment #5: r271058 --]
[-- Type: text/plain, Size: 3893 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-10 Jakub Jelinek <jakub@redhat.com>
PR c++/90383
* tree-inline.h (struct copy_body_data): Add do_not_fold member.
* tree-inline.c (remap_gimple_op_r): Avoid folding expressions if
id->do_not_fold.
(copy_tree_body_r): Likewise.
(copy_fn): Set id.do_not_fold to true.
* g++.dg/cpp1y/constexpr-90383-1.C: New test.
* g++.dg/cpp1y/constexpr-90383-2.C: New test.
--- gcc/tree-inline.h (revision 271057)
+++ gcc/tree-inline.h (revision 271058)
@@ -113,6 +113,9 @@ struct copy_body_data
/* True if trees may not be unshared. */
bool do_not_unshare;
+ /* True if trees should not be folded during the copying. */
+ bool do_not_fold;
+
/* True if new declarations may not be created during type remapping. */
bool prevent_decl_creation_for_types;
--- gcc/tree-inline.c (revision 271057)
+++ gcc/tree-inline.c (revision 271058)
@@ -1101,7 +1101,7 @@ remap_gimple_op_r (tree *tp, int *walk_s
/* Otherwise, just copy the node. Note that copy_tree_r already
knows not to copy VAR_DECLs, etc., so this is safe. */
- if (TREE_CODE (*tp) == MEM_REF)
+ if (TREE_CODE (*tp) == MEM_REF && !id->do_not_fold)
{
/* We need to re-canonicalize MEM_REFs from inline substitutions
that can happen when a pointer argument is an ADDR_EXPR.
@@ -1327,11 +1327,11 @@ copy_tree_body_r (tree *tp, int *walk_su
tree type = TREE_TYPE (*tp);
tree ptr = id->do_not_unshare ? *n : unshare_expr (*n);
tree old = *tp;
- *tp = gimple_fold_indirect_ref (ptr);
+ *tp = id->do_not_fold ? NULL : gimple_fold_indirect_ref (ptr);
if (! *tp)
{
type = remap_type (type, id);
- if (TREE_CODE (ptr) == ADDR_EXPR)
+ if (TREE_CODE (ptr) == ADDR_EXPR && !id->do_not_fold)
{
*tp
= fold_indirect_ref_1 (EXPR_LOCATION (ptr), type, ptr);
@@ -1360,7 +1360,7 @@ copy_tree_body_r (tree *tp, int *walk_su
return NULL;
}
}
- else if (TREE_CODE (*tp) == MEM_REF)
+ else if (TREE_CODE (*tp) == MEM_REF && !id->do_not_fold)
{
/* We need to re-canonicalize MEM_REFs from inline substitutions
that can happen when a pointer argument is an ADDR_EXPR.
@@ -1432,7 +1432,8 @@ copy_tree_body_r (tree *tp, int *walk_su
/* Handle the case where we substituted an INDIRECT_REF
into the operand of the ADDR_EXPR. */
- if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF)
+ if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF
+ && !id->do_not_fold)
{
tree t = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0);
if (TREE_TYPE (t) != TREE_TYPE (*tp))
@@ -6370,6 +6371,7 @@ copy_fn (tree fn, tree& parms, tree& res
since front-end specific mechanisms may rely on sharing. */
id.regimplify = false;
id.do_not_unshare = true;
+ id.do_not_fold = true;
/* We're not inside any EH region. */
id.eh_lp_nr = 0;
--- gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C (revision 271058)
@@ -0,0 +1,15 @@
+// PR c++/90383
+// { dg-do compile { target c++14 } }
+
+struct alignas(8) A { constexpr A (bool x) : a(x) {} A () = delete; bool a; };
+struct B { A b; };
+
+constexpr bool
+foo ()
+{
+ B w{A (true)};
+ w.b = A (true);
+ return w.b.a;
+}
+
+static_assert (foo (), "");
--- gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C (revision 271058)
@@ -0,0 +1,22 @@
+// PR c++/90383
+// { dg-do run { target c++14 } }
+// { dg-options "-O2" }
+
+extern "C" void abort ();
+struct alignas(8) A { constexpr A (bool x) : a(x) {} A () = default; bool a; };
+struct B { A b; };
+
+constexpr bool
+foo ()
+{
+ B w{A (true)};
+ w.b = A (true);
+ return w.b.a;
+}
+
+int
+main ()
+{
+ if (!foo ())
+ abort ();
+}
[-- Attachment #6: r271059 --]
[-- Type: text/plain, Size: 1354 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-10 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/90385
* tree-parloops.c (try_create_reduction_list): Punt on non-SSA_NAME
arguments of the exit phis.
* gfortran.dg/pr90385.f90: New test.
--- gcc/tree-parloops.c (revision 271058)
+++ gcc/tree-parloops.c (revision 271059)
@@ -2794,8 +2794,16 @@ try_create_reduction_list (loop_p loop,
gimple *reduc_phi;
tree val = PHI_ARG_DEF_FROM_EDGE (phi, exit);
- if (TREE_CODE (val) == SSA_NAME && !virtual_operand_p (val))
+ if (!virtual_operand_p (val))
{
+ if (TREE_CODE (val) != SSA_NAME)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " FAILED: exit PHI argument invariant.\n");
+ return false;
+ }
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "phi is ");
--- gcc/testsuite/gfortran.dg/pr90385.f90 (nonexistent)
+++ gcc/testsuite/gfortran.dg/pr90385.f90 (revision 271059)
@@ -0,0 +1,6 @@
+! PR tree-optimization/90385
+! { dg-do compile }
+! { dg-require-effective-target pthread }
+! { dg-options "-O1 -ftree-parallelize-loops=2 -fno-tree-ccp -fno-tree-ch -fno-tree-copy-prop -fno-tree-forwprop -fno-tree-sink --param parloops-min-per-thread=5" }
+
+include 'array_constructor_47.f90'
[-- Attachment #7: r271269 --]
[-- Type: text/plain, Size: 2343 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-15 Jakub Jelinek <jakub@redhat.com>
PR debug/90197
* cp-gimplify.c (genericize_cp_loop): Emit a DEBUG_BEGIN_STMT
before the condition (or if missing or constant non-zero at the end
of the loop. Emit a DEBUG_BEGIN_STMT before the increment expression
if any. Don't call protected_set_expr_location on incr if it already
has a location.
--- gcc/cp/cp-gimplify.c (revision 271268)
+++ gcc/cp/cp-gimplify.c (revision 271269)
@@ -241,8 +241,10 @@ genericize_cp_loop (tree *stmt_p, locati
tree blab, clab;
tree exit = NULL;
tree stmt_list = NULL;
+ tree debug_begin = NULL;
- protected_set_expr_location (incr, start_locus);
+ if (EXPR_LOCATION (incr) == UNKNOWN_LOCATION)
+ protected_set_expr_location (incr, start_locus);
cp_walk_tree (&cond, cp_genericize_r, data, NULL);
cp_walk_tree (&incr, cp_genericize_r, data, NULL);
@@ -253,6 +255,13 @@ genericize_cp_loop (tree *stmt_p, locati
cp_walk_tree (&body, cp_genericize_r, data, NULL);
*walk_subtrees = 0;
+ if (MAY_HAVE_DEBUG_MARKER_STMTS
+ && (!cond || !integer_zerop (cond)))
+ {
+ debug_begin = build0 (DEBUG_BEGIN_STMT, void_type_node);
+ SET_EXPR_LOCATION (debug_begin, cp_expr_loc_or_loc (cond, start_locus));
+ }
+
if (cond && TREE_CODE (cond) != INTEGER_CST)
{
/* If COND is constant, don't bother building an exit. If it's false,
@@ -265,10 +274,24 @@ genericize_cp_loop (tree *stmt_p, locati
}
if (exit && cond_is_first)
- append_to_statement_list (exit, &stmt_list);
+ {
+ append_to_statement_list (debug_begin, &stmt_list);
+ debug_begin = NULL_TREE;
+ append_to_statement_list (exit, &stmt_list);
+ }
append_to_statement_list (body, &stmt_list);
finish_bc_block (&stmt_list, bc_continue, clab);
- append_to_statement_list (incr, &stmt_list);
+ if (incr)
+ {
+ if (MAY_HAVE_DEBUG_MARKER_STMTS)
+ {
+ tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
+ SET_EXPR_LOCATION (d, cp_expr_loc_or_loc (incr, start_locus));
+ append_to_statement_list (d, &stmt_list);
+ }
+ append_to_statement_list (incr, &stmt_list);
+ }
+ append_to_statement_list (debug_begin, &stmt_list);
if (exit && !cond_is_first)
append_to_statement_list (exit, &stmt_list);
[-- Attachment #8: r271270 --]
[-- Type: text/plain, Size: 3006 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-15 Jakub Jelinek <jakub@redhat.com>
* omp-low.c (lower_rec_input_clauses): For if (0) or simdlen (1) set
max_vf to 1.
* omp-expand.c (expand_omp_simd): For if (0) or simdlen (1) clear
safelen_int and set loop->dont_vectorize.
* c-c++-common/gomp/simd8.c: New test.
--- gcc/omp-low.c (revision 271269)
+++ gcc/omp-low.c (revision 271270)
@@ -3811,6 +3811,14 @@ lower_rec_input_clauses (tree clauses, g
|| is_variable_sized (OMP_CLAUSE_DECL (c)))
sctx.max_vf = 1;
break;
+ case OMP_CLAUSE_IF:
+ if (integer_zerop (OMP_CLAUSE_IF_EXPR (c)))
+ sctx.max_vf = 1;
+ break;
+ case OMP_CLAUSE_SIMDLEN:
+ if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
+ sctx.max_vf = 1;
+ break;
default:
continue;
}
--- gcc/omp-expand.c (revision 271269)
+++ gcc/omp-expand.c (revision 271270)
@@ -4664,10 +4664,15 @@ expand_omp_simd (struct omp_region *regi
tree *counts = NULL;
int i;
int safelen_int = INT_MAX;
+ bool dont_vectorize = false;
tree safelen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
OMP_CLAUSE_SAFELEN);
tree simduid = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
OMP_CLAUSE__SIMDUID_);
+ tree ifc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE_IF);
+ tree simdlen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE_SIMDLEN);
tree n1, n2;
if (safelen)
@@ -4681,6 +4686,12 @@ expand_omp_simd (struct omp_region *regi
if (safelen_int == 1)
safelen_int = 0;
}
+ if ((ifc && integer_zerop (OMP_CLAUSE_IF_EXPR (ifc)))
+ || (simdlen && integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (simdlen))))
+ {
+ safelen_int = 0;
+ dont_vectorize = true;
+ }
type = TREE_TYPE (fd->loop.v);
entry_bb = region->entry;
cont_bb = region->cont;
@@ -4965,6 +4976,8 @@ expand_omp_simd (struct omp_region *regi
loop->force_vectorize = true;
cfun->has_force_vectorize_loops = true;
}
+ else if (dont_vectorize)
+ loop->dont_vectorize = true;
}
else if (simduid)
cfun->has_simduid_loops = true;
--- gcc/testsuite/c-c++-common/gomp/simd8.c (nonexistent)
+++ gcc/testsuite/c-c++-common/gomp/simd8.c (revision 271270)
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -O3 -fdump-tree-vect-details" } */
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops in function" 4 "vect" } } */
+
+int a[1024];
+
+void
+foo (void)
+{
+ #pragma omp simd if (0)
+ for (int i = 0; i < 1024; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+bar (void)
+{
+ #pragma omp simd if (0) safelen (256) simdlen (8)
+ for (int i = 0; i < 512; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+baz (void)
+{
+ #pragma omp simd safelen (256) simdlen (1)
+ for (int i = 0; i < 512; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+qux (void)
+{
+ #pragma omp simd simdlen (1) if (1)
+ for (int i = 0; i < 512; ++i)
+ a[i] = a[i] + 1;
+}
[-- Attachment #9: r271298 --]
[-- Type: text/plain, Size: 11857 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-16 Jakub Jelinek <jakub@redhat.com>
* omp-low.c (lower_rec_input_clauses): If OMP_CLAUSE_IF
has non-constant expression, force sctx.lane and use two
argument IFN_GOMP_SIMD_LANE instead of single argument.
* tree-ssa-dce.c (eliminate_unnecessary_stmts): Don't DCE
two argument IFN_GOMP_SIMD_LANE without lhs.
* tree-vectorizer.h (struct _loop_vec_info): Add simd_if_cond
member.
(LOOP_VINFO_SIMD_IF_COND, LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND):
Define.
(LOOP_REQUIRES_VERSIONING): Or in
LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND.
* tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Initialize
simd_if_cond.
(vect_analyze_loop_2): Punt if LOOP_VINFO_SIMD_IF_COND is constant 0.
* tree-vect-loop-manip.c (vect_loop_versioning): Add runtime check
from simd if clause if needed.
* gcc.dg/vect/vect-simd-1.c: New test.
* gcc.dg/vect/vect-simd-2.c: New test.
* gcc.dg/vect/vect-simd-3.c: New test.
* gcc.dg/vect/vect-simd-4.c: New test.
--- gcc/omp-low.c (revision 271297)
+++ gcc/omp-low.c (revision 271298)
@@ -3783,6 +3783,7 @@ lower_rec_input_clauses (tree clauses, g
tree simt_lane = NULL_TREE, simtrec = NULL_TREE;
tree ivar = NULL_TREE, lvar = NULL_TREE, uid = NULL_TREE;
gimple_seq llist[3] = { };
+ tree nonconst_simd_if = NULL_TREE;
copyin_seq = NULL;
sctx.is_simt = is_simd && omp_find_clause (clauses, OMP_CLAUSE__SIMT_);
@@ -3814,6 +3815,8 @@ lower_rec_input_clauses (tree clauses, g
case OMP_CLAUSE_IF:
if (integer_zerop (OMP_CLAUSE_IF_EXPR (c)))
sctx.max_vf = 1;
+ else if (TREE_CODE (OMP_CLAUSE_IF_EXPR (c)) != INTEGER_CST)
+ nonconst_simd_if = OMP_CLAUSE_IF_EXPR (c);
break;
case OMP_CLAUSE_SIMDLEN:
if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
@@ -5190,6 +5193,17 @@ lower_rec_input_clauses (tree clauses, g
if (known_eq (sctx.max_vf, 1U))
sctx.is_simt = false;
+ if (nonconst_simd_if)
+ {
+ if (sctx.lane == NULL_TREE)
+ {
+ sctx.idx = create_tmp_var (unsigned_type_node);
+ sctx.lane = create_tmp_var (unsigned_type_node);
+ }
+ /* FIXME: For now. */
+ sctx.is_simt = false;
+ }
+
if (sctx.lane || sctx.is_simt)
{
uid = create_tmp_var (ptr_type_node, "simduid");
@@ -5219,8 +5233,9 @@ lower_rec_input_clauses (tree clauses, g
}
if (sctx.lane)
{
- gimple *g
- = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
+ gimple *g = gimple_build_call_internal (IFN_GOMP_SIMD_LANE,
+ 1 + (nonconst_simd_if != NULL),
+ uid, nonconst_simd_if);
gimple_call_set_lhs (g, sctx.lane);
gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
--- gcc/tree-vect-loop-manip.c (revision 271297)
+++ gcc/tree-vect-loop-manip.c (revision 271298)
@@ -3009,6 +3009,8 @@ vect_loop_versioning (loop_vec_info loop
bool version_align = LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo);
bool version_alias = LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo);
bool version_niter = LOOP_REQUIRES_VERSIONING_FOR_NITERS (loop_vinfo);
+ tree version_simd_if_cond
+ = LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND (loop_vinfo);
if (check_profitability)
cond_expr = fold_build2 (GE_EXPR, boolean_type_node, scalar_loop_iters,
@@ -3044,6 +3046,31 @@ vect_loop_versioning (loop_vec_info loop
vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr);
}
+ if (version_simd_if_cond)
+ {
+ gcc_assert (dom_info_available_p (CDI_DOMINATORS));
+ if (flag_checking)
+ if (basic_block bb
+ = gimple_bb (SSA_NAME_DEF_STMT (version_simd_if_cond)))
+ gcc_assert (bb != loop->header
+ && dominated_by_p (CDI_DOMINATORS, loop->header, bb)
+ && (scalar_loop == NULL
+ || (bb != scalar_loop->header
+ && dominated_by_p (CDI_DOMINATORS,
+ scalar_loop->header, bb))));
+ tree zero = build_zero_cst (TREE_TYPE (version_simd_if_cond));
+ tree c = fold_build2 (NE_EXPR, boolean_type_node,
+ version_simd_if_cond, zero);
+ if (cond_expr)
+ cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+ c, cond_expr);
+ else
+ cond_expr = c;
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "created versioning for simd if condition check.\n");
+ }
+
cond_expr = force_gimple_operand_1 (unshare_expr (cond_expr),
&gimplify_stmt_list,
is_gimple_condexpr, NULL_TREE);
--- gcc/tree-vectorizer.h (revision 271297)
+++ gcc/tree-vectorizer.h (revision 271298)
@@ -428,6 +428,13 @@ typedef struct _loop_vec_info : public v
loops. */
tree mask_compare_type;
+ /* For #pragma omp simd if (x) loops the x expression. If constant 0,
+ the loop should not be vectorized, if constant non-zero, simd_if_cond
+ shouldn't be set and loop vectorized normally, if SSA_NAME, the loop
+ should be versioned on that condition, using scalar loop if the condition
+ is false and vectorized loop otherwise. */
+ tree simd_if_cond;
+
/* Unknown DRs according to which loop was peeled. */
struct dr_vec_info *unaligned_dr;
@@ -591,6 +598,7 @@ typedef struct _loop_vec_info : public v
#define LOOP_VINFO_SCALAR_ITERATION_COST(L) (L)->scalar_cost_vec
#define LOOP_VINFO_SINGLE_SCALAR_ITERATION_COST(L) (L)->single_scalar_iteration_cost
#define LOOP_VINFO_ORIG_LOOP_INFO(L) (L)->orig_loop_info
+#define LOOP_VINFO_SIMD_IF_COND(L) (L)->simd_if_cond
#define LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT(L) \
((L)->may_misalign_stmts.length () > 0)
@@ -600,10 +608,13 @@ typedef struct _loop_vec_info : public v
|| (L)->lower_bounds.length () > 0)
#define LOOP_REQUIRES_VERSIONING_FOR_NITERS(L) \
(LOOP_VINFO_NITERS_ASSUMPTIONS (L))
+#define LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND(L) \
+ (LOOP_VINFO_SIMD_IF_COND (L))
#define LOOP_REQUIRES_VERSIONING(L) \
(LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (L) \
|| LOOP_REQUIRES_VERSIONING_FOR_ALIAS (L) \
- || LOOP_REQUIRES_VERSIONING_FOR_NITERS (L))
+ || LOOP_REQUIRES_VERSIONING_FOR_NITERS (L) \
+ || LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND (L))
#define LOOP_VINFO_NITERS_KNOWN_P(L) \
(tree_fits_shwi_p ((L)->num_iters) && tree_to_shwi ((L)->num_iters) > 0)
--- gcc/tree-vect-loop.c (revision 271297)
+++ gcc/tree-vect-loop.c (revision 271298)
@@ -819,6 +819,7 @@ _loop_vec_info::_loop_vec_info (struct l
max_vectorization_factor (0),
mask_skip_niters (NULL_TREE),
mask_compare_type (NULL_TREE),
+ simd_if_cond (NULL_TREE),
unaligned_dr (NULL),
peeling_for_alignment (0),
ptr_mask (0),
@@ -862,6 +863,26 @@ _loop_vec_info::_loop_vec_info (struct l
gimple *stmt = gsi_stmt (si);
gimple_set_uid (stmt, 0);
add_stmt (stmt);
+ /* If .GOMP_SIMD_LANE call for the current loop has 2 arguments, the
+ second argument is the #pragma omp simd if (x) condition, when 0,
+ loop shouldn't be vectorized, when non-zero constant, it should
+ be vectorized normally, otherwise versioned with vectorized loop
+ done if the condition is non-zero at runtime. */
+ if (loop_in->simduid
+ && is_gimple_call (stmt)
+ && gimple_call_internal_p (stmt)
+ && gimple_call_internal_fn (stmt) == IFN_GOMP_SIMD_LANE
+ && gimple_call_num_args (stmt) >= 2
+ && TREE_CODE (gimple_call_arg (stmt, 0)) == SSA_NAME
+ && (loop_in->simduid
+ == SSA_NAME_VAR (gimple_call_arg (stmt, 0))))
+ {
+ tree arg = gimple_call_arg (stmt, 1);
+ if (integer_zerop (arg) || TREE_CODE (arg) == SSA_NAME)
+ simd_if_cond = arg;
+ else
+ gcc_assert (integer_nonzerop (arg));
+ }
}
}
}
@@ -1769,6 +1790,11 @@ vect_analyze_loop_2 (loop_vec_info loop_
/* The first group of checks is independent of the vector size. */
fatal = true;
+ if (LOOP_VINFO_SIMD_IF_COND (loop_vinfo)
+ && integer_zerop (LOOP_VINFO_SIMD_IF_COND (loop_vinfo)))
+ return opt_result::failure_at (vect_location,
+ "not vectorized: simd if(0)\n");
+
/* Find all data references in the loop (which correspond to vdefs/vuses)
and analyze their evolution in the loop. */
--- gcc/tree-ssa-dce.c (revision 271297)
+++ gcc/tree-ssa-dce.c (revision 271298)
@@ -1328,12 +1328,16 @@ eliminate_unnecessary_stmts (void)
update_stmt (stmt);
release_ssa_name (name);
- /* GOMP_SIMD_LANE or ASAN_POISON without lhs is not
- needed. */
+ /* GOMP_SIMD_LANE (unless two argument) or ASAN_POISON
+ without lhs is not needed. */
if (gimple_call_internal_p (stmt))
switch (gimple_call_internal_fn (stmt))
{
case IFN_GOMP_SIMD_LANE:
+ if (gimple_call_num_args (stmt) >= 2
+ && !integer_nonzerop (gimple_call_arg (stmt, 1)))
+ break;
+ /* FALLTHRU */
case IFN_ASAN_POISON:
remove_dead_stmt (&gsi, bb, to_remove_edges);
break;
--- gcc/testsuite/gcc.dg/vect/vect-simd-1.c (nonexistent)
+++ gcc/testsuite/gcc.dg/vect/vect-simd-1.c (revision 271298)
@@ -0,0 +1,64 @@
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+#include "tree-vect.h"
+
+#define N 1024
+int a[N];
+int x;
+
+__attribute__((noipa)) int
+bar (void)
+{
+ return x;
+}
+
+__attribute__((noipa)) void
+foo (void)
+{
+ #pragma omp simd if (bar ())
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+__attribute__((noipa)) void
+baz (void)
+{
+ int c = 0;
+ #pragma omp simd if (c)
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+__attribute__((noipa)) void
+qux (void)
+{
+ int c = 1;
+ #pragma omp simd if (c)
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+int
+main ()
+{
+ check_vect ();
+ foo ();
+ for (int i = 0; i < N; ++i)
+ if (a[i] != 1)
+ abort ();
+ x = 1;
+ foo ();
+ for (int i = 0; i < N; ++i)
+ if (a[i] != 2)
+ abort ();
+ baz ();
+ for (int i = 0; i < N; ++i)
+ if (a[i] != 3)
+ abort ();
+ qux ();
+ for (int i = 0; i < N; ++i)
+ if (a[i] != 4)
+ abort ();
+ return 0;
+}
--- gcc/testsuite/gcc.dg/vect/vect-simd-2.c (nonexistent)
+++ gcc/testsuite/gcc.dg/vect/vect-simd-2.c (revision 271298)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#define N 1024
+int a[N];
+int bar (void);
+
+void
+foo (void)
+{
+ #pragma omp simd if (bar ())
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "created versioning for simd if condition check" 1 "vect" } } */
--- gcc/testsuite/gcc.dg/vect/vect-simd-3.c (nonexistent)
+++ gcc/testsuite/gcc.dg/vect/vect-simd-3.c (revision 271298)
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#define N 1024
+int a[N];
+
+void
+foo (void)
+{
+ int c = 0;
+ #pragma omp simd if (c)
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */
--- gcc/testsuite/gcc.dg/vect/vect-simd-4.c (nonexistent)
+++ gcc/testsuite/gcc.dg/vect/vect-simd-4.c (revision 271298)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#define N 1024
+int a[N];
+
+void
+foo (void)
+{
+ int c = 1;
+ #pragma omp simd if (c)
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-not "created versioning for simd if condition check" "vect" } } */
[-- Attachment #10: r271299 --]
[-- Type: text/plain, Size: 877 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2019-05-16 Jakub Jelinek <jakub@redhat.com>
PR c++/90484
* tree-ssa-scopedtables.c (equal_mem_array_ref_p): Don't assert that
sz0 is equal to sz1, instead return false in that case.
--- gcc/tree-ssa-scopedtables.c (revision 271298)
+++ gcc/tree-ssa-scopedtables.c (revision 271299)
@@ -537,13 +537,10 @@ equal_mem_array_ref_p (tree t0, tree t1)
|| maybe_ne (sz1, max1))
return false;
- if (rev0 != rev1)
+ if (rev0 != rev1 || maybe_ne (sz0, sz1) || maybe_ne (off0, off1))
return false;
- /* Types were compatible, so this is a sanity check. */
- gcc_assert (known_eq (sz0, sz1));
-
- return known_eq (off0, off1) && operand_equal_p (base0, base1, 0);
+ return operand_equal_p (base0, base1, 0);
}
/* Compare two hashable_expr structures for equivalence. They are
[-- Attachment #11: r271334 --]
[-- Type: text/plain, Size: 524 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
PR fortran/54613
* gfortran.map (GFORTRAN_9.2): New symbol version, export
_gfortran_{,m,s}findloc0_i2 in it.
--- libgfortran/gfortran.map (revision 271333)
+++ libgfortran/gfortran.map (revision 271334)
@@ -1590,3 +1590,9 @@ GFORTRAN_9 {
__ieee_arithmetic_MOD_ieee_support_subnormal_8;
__ieee_arithmetic_MOD_ieee_support_subnormal_noarg;
} GFORTRAN_8;
+
+GFORTRAN_9.2 {
+ _gfortran_findloc0_i2;
+ _gfortran_mfindloc0_i2;
+ _gfortran_sfindloc0_i2;
+} GFORTRAN_9;
[-- Attachment #12: r271335 --]
[-- Type: text/plain, Size: 32031 bytes --]
2019-05-17 Jakub Jelinek <jakub@redhat.com>
PR fortran/54613
* gfortran.map (GFORTRAN_9.2): Export _gfortran_{,m,s}findloc{0,1}_r10.
* Makefile.am (i_findloc0_c): Add $(srcdir)/generated/findloc0_r10.c.
(i_findloc1_c): Add $(srcdir)/generated/findloc1_r10.c.
* Makefile.in: Regenerated.
* generated/findloc0_r10.c: Generated.
* generated/findloc1_r10.c: Generated.
--- libgfortran/gfortran.map (revision 271334)
+++ libgfortran/gfortran.map (revision 271335)
@@ -1593,6 +1593,12 @@ GFORTRAN_9 {
GFORTRAN_9.2 {
_gfortran_findloc0_i2;
+ _gfortran_findloc0_r10;
_gfortran_mfindloc0_i2;
+ _gfortran_mfindloc0_r10;
_gfortran_sfindloc0_i2;
+ _gfortran_sfindloc0_r10;
+ _gfortran_findloc1_r10;
+ _gfortran_mfindloc1_r10;
+ _gfortran_sfindloc1_r10;
} GFORTRAN_9;
--- libgfortran/Makefile.am (revision 271334)
+++ libgfortran/Makefile.am (revision 271335)
@@ -278,6 +278,7 @@ $(srcdir)/generated/findloc0_i8.c \
$(srcdir)/generated/findloc0_i16.c \
$(srcdir)/generated/findloc0_r4.c \
$(srcdir)/generated/findloc0_r8.c \
+$(srcdir)/generated/findloc0_r10.c \
$(srcdir)/generated/findloc0_r16.c \
$(srcdir)/generated/findloc0_c4.c \
$(srcdir)/generated/findloc0_c8.c \
@@ -295,6 +296,7 @@ $(srcdir)/generated/findloc1_i8.c \
$(srcdir)/generated/findloc1_i16.c \
$(srcdir)/generated/findloc1_r4.c \
$(srcdir)/generated/findloc1_r8.c \
+$(srcdir)/generated/findloc1_r10.c \
$(srcdir)/generated/findloc1_r16.c \
$(srcdir)/generated/findloc1_c4.c \
$(srcdir)/generated/findloc1_c8.c \
--- libgfortran/Makefile.in (revision 271334)
+++ libgfortran/Makefile.in (revision 271335)
@@ -371,11 +371,13 @@ am__objects_45 = maxval1_s1.lo maxval1_s
am__objects_46 = minval1_s1.lo minval1_s4.lo
am__objects_47 = findloc0_i1.lo findloc0_i2.lo findloc0_i4.lo \
findloc0_i8.lo findloc0_i16.lo findloc0_r4.lo findloc0_r8.lo \
- findloc0_r16.lo findloc0_c4.lo findloc0_c8.lo findloc0_c16.lo
+ findloc0_r10.lo findloc0_r16.lo findloc0_c4.lo findloc0_c8.lo \
+ findloc0_c16.lo
am__objects_48 = findloc0_s1.lo findloc0_s4.lo
am__objects_49 = findloc1_i1.lo findloc1_i2.lo findloc1_i4.lo \
findloc1_i8.lo findloc1_i16.lo findloc1_r4.lo findloc1_r8.lo \
- findloc1_r16.lo findloc1_c4.lo findloc1_c8.lo findloc1_c16.lo
+ findloc1_r10.lo findloc1_r16.lo findloc1_c4.lo findloc1_c8.lo \
+ findloc1_c16.lo
am__objects_50 = findloc1_s1.lo findloc1_s4.lo
am__objects_51 = findloc2_s1.lo findloc2_s4.lo
am__objects_52 = ISO_Fortran_binding.lo
@@ -836,6 +838,7 @@ $(srcdir)/generated/findloc0_i8.c \
$(srcdir)/generated/findloc0_i16.c \
$(srcdir)/generated/findloc0_r4.c \
$(srcdir)/generated/findloc0_r8.c \
+$(srcdir)/generated/findloc0_r10.c \
$(srcdir)/generated/findloc0_r16.c \
$(srcdir)/generated/findloc0_c4.c \
$(srcdir)/generated/findloc0_c8.c \
@@ -853,6 +856,7 @@ $(srcdir)/generated/findloc1_i8.c \
$(srcdir)/generated/findloc1_i16.c \
$(srcdir)/generated/findloc1_r4.c \
$(srcdir)/generated/findloc1_r8.c \
+$(srcdir)/generated/findloc1_r10.c \
$(srcdir)/generated/findloc1_r16.c \
$(srcdir)/generated/findloc1_c4.c \
$(srcdir)/generated/findloc1_c8.c \
@@ -1824,6 +1828,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc0_i2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc0_i4.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc0_i8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc0_r10.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc0_r16.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc0_r4.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc0_r8.Plo@am__quote@
@@ -1837,6 +1842,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc1_i2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc1_i4.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc1_i8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc1_r10.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc1_r16.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc1_r4.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findloc1_r8.Plo@am__quote@
@@ -5949,6 +5955,13 @@ findloc0_r8.lo: $(srcdir)/generated/find
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o findloc0_r8.lo `test -f '$(srcdir)/generated/findloc0_r8.c' || echo '$(srcdir)/'`$(srcdir)/generated/findloc0_r8.c
+findloc0_r10.lo: $(srcdir)/generated/findloc0_r10.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT findloc0_r10.lo -MD -MP -MF $(DEPDIR)/findloc0_r10.Tpo -c -o findloc0_r10.lo `test -f '$(srcdir)/generated/findloc0_r10.c' || echo '$(srcdir)/'`$(srcdir)/generated/findloc0_r10.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/findloc0_r10.Tpo $(DEPDIR)/findloc0_r10.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/generated/findloc0_r10.c' object='findloc0_r10.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o findloc0_r10.lo `test -f '$(srcdir)/generated/findloc0_r10.c' || echo '$(srcdir)/'`$(srcdir)/generated/findloc0_r10.c
+
findloc0_r16.lo: $(srcdir)/generated/findloc0_r16.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT findloc0_r16.lo -MD -MP -MF $(DEPDIR)/findloc0_r16.Tpo -c -o findloc0_r16.lo `test -f '$(srcdir)/generated/findloc0_r16.c' || echo '$(srcdir)/'`$(srcdir)/generated/findloc0_r16.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/findloc0_r16.Tpo $(DEPDIR)/findloc0_r16.Plo
@@ -6040,6 +6053,13 @@ findloc1_r8.lo: $(srcdir)/generated/find
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o findloc1_r8.lo `test -f '$(srcdir)/generated/findloc1_r8.c' || echo '$(srcdir)/'`$(srcdir)/generated/findloc1_r8.c
+findloc1_r10.lo: $(srcdir)/generated/findloc1_r10.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT findloc1_r10.lo -MD -MP -MF $(DEPDIR)/findloc1_r10.Tpo -c -o findloc1_r10.lo `test -f '$(srcdir)/generated/findloc1_r10.c' || echo '$(srcdir)/'`$(srcdir)/generated/findloc1_r10.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/findloc1_r10.Tpo $(DEPDIR)/findloc1_r10.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/generated/findloc1_r10.c' object='findloc1_r10.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o findloc1_r10.lo `test -f '$(srcdir)/generated/findloc1_r10.c' || echo '$(srcdir)/'`$(srcdir)/generated/findloc1_r10.c
+
findloc1_r16.lo: $(srcdir)/generated/findloc1_r16.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT findloc1_r16.lo -MD -MP -MF $(DEPDIR)/findloc1_r16.Tpo -c -o findloc1_r16.lo `test -f '$(srcdir)/generated/findloc1_r16.c' || echo '$(srcdir)/'`$(srcdir)/generated/findloc1_r16.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/findloc1_r16.Tpo $(DEPDIR)/findloc1_r16.Plo
--- libgfortran/generated/findloc0_r10.c (nonexistent)
+++ libgfortran/generated/findloc0_r10.c (revision 271336)
@@ -0,0 +1,375 @@
+
+/* Implementation of the FINDLOC intrinsic
+ Copyright (C) 2018-2019 Free Software Foundation, Inc.
+ Contributed by Thomas König <tk@tkoenig.net>
+
+This file is part of the GNU Fortran 95 runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "libgfortran.h"
+#include <assert.h>
+
+#if defined (HAVE_GFC_REAL_10)
+extern void findloc0_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ GFC_LOGICAL_4);
+export_proto(findloc0_r10);
+
+void
+findloc0_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ GFC_LOGICAL_4 back)
+{
+ index_type count[GFC_MAX_DIMENSIONS];
+ index_type extent[GFC_MAX_DIMENSIONS];
+ index_type sstride[GFC_MAX_DIMENSIONS];
+ index_type dstride;
+ const GFC_REAL_10 *base;
+ index_type * restrict dest;
+ index_type rank;
+ index_type n;
+ index_type sz;
+
+ rank = GFC_DESCRIPTOR_RANK (array);
+ if (rank <= 0)
+ runtime_error ("Rank of array needs to be > 0");
+
+ if (retarray->base_addr == NULL)
+ {
+ GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+ retarray->dtype.rank = 1;
+ retarray->offset = 0;
+ retarray->base_addr = xmallocarray (rank, sizeof (index_type));
+ }
+ else
+ {
+ if (unlikely (compile_options.bounds_check))
+ bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+ "FINDLOC");
+ }
+
+ dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+ dest = retarray->base_addr;
+
+ /* Set the return value. */
+ for (n = 0; n < rank; n++)
+ dest[n * dstride] = 0;
+
+ sz = 1;
+ for (n = 0; n < rank; n++)
+ {
+ sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+ sz *= extent[n];
+ if (extent[n] <= 0)
+ return;
+ }
+
+ for (n = 0; n < rank; n++)
+ count[n] = 0;
+
+ if (back)
+ {
+ base = array->base_addr + (sz - 1) * 1;
+
+ while (1)
+ {
+ do
+ {
+ if (unlikely(*base == value))
+ {
+ for (n = 0; n < rank; n++)
+ dest[n * dstride] = extent[n] - count[n];
+
+ return;
+ }
+ base -= sstride[0] * 1;
+ } while(++count[0] != extent[0]);
+
+ n = 0;
+ do
+ {
+ /* When we get to the end of a dimension, reset it and increment
+ the next dimension. */
+ count[n] = 0;
+ /* We could precalculate these products, but this is a less
+ frequently used path so probably not worth it. */
+ base += sstride[n] * extent[n] * 1;
+ n++;
+ if (n >= rank)
+ return;
+ else
+ {
+ count[n]++;
+ base -= sstride[n] * 1;
+ }
+ } while (count[n] == extent[n]);
+ }
+ }
+ else
+ {
+ base = array->base_addr;
+ while (1)
+ {
+ do
+ {
+ if (unlikely(*base == value))
+ {
+ for (n = 0; n < rank; n++)
+ dest[n * dstride] = count[n] + 1;
+
+ return;
+ }
+ base += sstride[0] * 1;
+ } while(++count[0] != extent[0]);
+
+ n = 0;
+ do
+ {
+ /* When we get to the end of a dimension, reset it and increment
+ the next dimension. */
+ count[n] = 0;
+ /* We could precalculate these products, but this is a less
+ frequently used path so probably not worth it. */
+ base -= sstride[n] * extent[n] * 1;
+ n++;
+ if (n >= rank)
+ return;
+ else
+ {
+ count[n]++;
+ base += sstride[n] * 1;
+ }
+ } while (count[n] == extent[n]);
+ }
+ }
+ return;
+}
+
+extern void mfindloc0_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ gfc_array_l1 *const restrict, GFC_LOGICAL_4);
+export_proto(mfindloc0_r10);
+
+void
+mfindloc0_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ gfc_array_l1 *const restrict mask, GFC_LOGICAL_4 back)
+{
+ index_type count[GFC_MAX_DIMENSIONS];
+ index_type extent[GFC_MAX_DIMENSIONS];
+ index_type sstride[GFC_MAX_DIMENSIONS];
+ index_type mstride[GFC_MAX_DIMENSIONS];
+ index_type dstride;
+ const GFC_REAL_10 *base;
+ index_type * restrict dest;
+ GFC_LOGICAL_1 *mbase;
+ index_type rank;
+ index_type n;
+ int mask_kind;
+ index_type sz;
+
+ rank = GFC_DESCRIPTOR_RANK (array);
+ if (rank <= 0)
+ runtime_error ("Rank of array needs to be > 0");
+
+ if (retarray->base_addr == NULL)
+ {
+ GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+ retarray->dtype.rank = 1;
+ retarray->offset = 0;
+ retarray->base_addr = xmallocarray (rank, sizeof (index_type));
+ }
+ else
+ {
+ if (unlikely (compile_options.bounds_check))
+ {
+ bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+ "FINDLOC");
+ bounds_equal_extents ((array_t *) mask, (array_t *) array,
+ "MASK argument", "FINDLOC");
+ }
+ }
+
+ mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+ mbase = mask->base_addr;
+
+ if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
+#ifdef HAVE_GFC_LOGICAL_16
+ || mask_kind == 16
+#endif
+ )
+ mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
+ else
+ internal_error (NULL, "Funny sized logical array");
+
+ dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+ dest = retarray->base_addr;
+
+ /* Set the return value. */
+ for (n = 0; n < rank; n++)
+ dest[n * dstride] = 0;
+
+ sz = 1;
+ for (n = 0; n < rank; n++)
+ {
+ sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
+ mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+ sz *= extent[n];
+ if (extent[n] <= 0)
+ return;
+ }
+
+ for (n = 0; n < rank; n++)
+ count[n] = 0;
+
+ if (back)
+ {
+ base = array->base_addr + (sz - 1) * 1;
+ mbase = mbase + (sz - 1) * mask_kind;
+ while (1)
+ {
+ do
+ {
+ if (unlikely(*mbase && *base == value))
+ {
+ for (n = 0; n < rank; n++)
+ dest[n * dstride] = extent[n] - count[n];
+
+ return;
+ }
+ base -= sstride[0] * 1;
+ mbase -= mstride[0];
+ } while(++count[0] != extent[0]);
+
+ n = 0;
+ do
+ {
+ /* When we get to the end of a dimension, reset it and increment
+ the next dimension. */
+ count[n] = 0;
+ /* We could precalculate these products, but this is a less
+ frequently used path so probably not worth it. */
+ base += sstride[n] * extent[n] * 1;
+ mbase -= mstride[n] * extent[n];
+ n++;
+ if (n >= rank)
+ return;
+ else
+ {
+ count[n]++;
+ base -= sstride[n] * 1;
+ mbase += mstride[n];
+ }
+ } while (count[n] == extent[n]);
+ }
+ }
+ else
+ {
+ base = array->base_addr;
+ while (1)
+ {
+ do
+ {
+ if (unlikely(*mbase && *base == value))
+ {
+ for (n = 0; n < rank; n++)
+ dest[n * dstride] = count[n] + 1;
+
+ return;
+ }
+ base += sstride[0] * 1;
+ mbase += mstride[0];
+ } while(++count[0] != extent[0]);
+
+ n = 0;
+ do
+ {
+ /* When we get to the end of a dimension, reset it and increment
+ the next dimension. */
+ count[n] = 0;
+ /* We could precalculate these products, but this is a less
+ frequently used path so probably not worth it. */
+ base -= sstride[n] * extent[n] * 1;
+ mbase -= mstride[n] * extent[n];
+ n++;
+ if (n >= rank)
+ return;
+ else
+ {
+ count[n]++;
+ base += sstride[n]* 1;
+ mbase += mstride[n];
+ }
+ } while (count[n] == extent[n]);
+ }
+ }
+ return;
+}
+
+extern void sfindloc0_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ GFC_LOGICAL_4 *, GFC_LOGICAL_4);
+export_proto(sfindloc0_r10);
+
+void
+sfindloc0_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
+{
+ index_type rank;
+ index_type dstride;
+ index_type * restrict dest;
+ index_type n;
+
+ if (mask == NULL || *mask)
+ {
+ findloc0_r10 (retarray, array, value, back);
+ return;
+ }
+
+ rank = GFC_DESCRIPTOR_RANK (array);
+
+ if (rank <= 0)
+ internal_error (NULL, "Rank of array needs to be > 0");
+
+ if (retarray->base_addr == NULL)
+ {
+ GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+ retarray->dtype.rank = 1;
+ retarray->offset = 0;
+ retarray->base_addr = xmallocarray (rank, sizeof (index_type));
+ }
+ else if (unlikely (compile_options.bounds_check))
+ {
+ bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+ "FINDLOC");
+ }
+
+ dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+ dest = retarray->base_addr;
+ for (n = 0; n<rank; n++)
+ dest[n * dstride] = 0 ;
+}
+
+#endif
--- libgfortran/generated/findloc1_r10.c (nonexistent)
+++ libgfortran/generated/findloc1_r10.c (revision 271336)
@@ -0,0 +1,523 @@
+/* Implementation of the FINDLOC intrinsic
+ Copyright (C) 2018-2019 Free Software Foundation, Inc.
+ Contributed by Thomas König <tk@tkoenig.net>
+
+This file is part of the GNU Fortran 95 runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "libgfortran.h"
+#include <assert.h>
+
+#if defined (HAVE_GFC_REAL_10)
+extern void findloc1_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ const index_type * restrict pdim, GFC_LOGICAL_4 back);
+export_proto(findloc1_r10);
+
+extern void
+findloc1_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ const index_type * restrict pdim, GFC_LOGICAL_4 back)
+{
+ index_type count[GFC_MAX_DIMENSIONS];
+ index_type extent[GFC_MAX_DIMENSIONS];
+ index_type sstride[GFC_MAX_DIMENSIONS];
+ index_type dstride[GFC_MAX_DIMENSIONS];
+ const GFC_REAL_10 * restrict base;
+ index_type * restrict dest;
+ index_type rank;
+ index_type n;
+ index_type len;
+ index_type delta;
+ index_type dim;
+ int continue_loop;
+
+ /* Make dim zero based to avoid confusion. */
+ rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
+ len = GFC_DESCRIPTOR_EXTENT(array,dim);
+ if (len < 0)
+ len = 0;
+ delta = GFC_DESCRIPTOR_STRIDE(array,dim);
+
+ for (n = 0; n < dim; n++)
+ {
+ sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+ if (extent[n] < 0)
+ extent[n] = 0;
+ }
+ for (n = dim; n < rank; n++)
+ {
+ sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+ if (extent[n] < 0)
+ extent[n] = 0;
+ }
+
+ if (retarray->base_addr == NULL)
+ {
+ size_t alloc_size, str;
+
+ for (n = 0; n < rank; n++)
+ {
+ if (n == 0)
+ str = 1;
+ else
+ str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
+
+ GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
+
+ }
+
+ retarray->offset = 0;
+ retarray->dtype.rank = rank;
+
+ alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+ retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
+ if (alloc_size == 0)
+ {
+ /* Make sure we have a zero-sized array. */
+ GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
+ return;
+ }
+ }
+ else
+ {
+ if (rank != GFC_DESCRIPTOR_RANK (retarray))
+ runtime_error ("rank of return array incorrect in"
+ " FINDLOC intrinsic: is %ld, should be %ld",
+ (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+ (long int) rank);
+
+ if (unlikely (compile_options.bounds_check))
+ bounds_ifunction_return ((array_t *) retarray, extent,
+ "return value", "FINDLOC");
+ }
+
+ for (n = 0; n < rank; n++)
+ {
+ count[n] = 0;
+ dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+ if (extent[n] <= 0)
+ return;
+ }
+
+ dest = retarray->base_addr;
+ continue_loop = 1;
+
+ base = array->base_addr;
+ while (continue_loop)
+ {
+ const GFC_REAL_10 * restrict src;
+ index_type result;
+
+ result = 0;
+ if (back)
+ {
+ src = base + (len - 1) * delta * 1;
+ for (n = len; n > 0; n--, src -= delta * 1)
+ {
+ if (*src == value)
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ else
+ {
+ src = base;
+ for (n = 1; n <= len; n++, src += delta * 1)
+ {
+ if (*src == value)
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ *dest = result;
+
+ count[0]++;
+ base += sstride[0] * 1;
+ dest += dstride[0];
+ n = 0;
+ while (count[n] == extent[n])
+ {
+ count[n] = 0;
+ base -= sstride[n] * extent[n] * 1;
+ dest -= dstride[n] * extent[n];
+ n++;
+ if (n >= rank)
+ {
+ continue_loop = 0;
+ break;
+ }
+ else
+ {
+ count[n]++;
+ base += sstride[n] * 1;
+ dest += dstride[n];
+ }
+ }
+ }
+}
+extern void mfindloc1_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
+ GFC_LOGICAL_4 back);
+export_proto(mfindloc1_r10);
+
+extern void
+mfindloc1_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ const index_type * restrict pdim, gfc_array_l1 *const restrict mask,
+ GFC_LOGICAL_4 back)
+{
+ index_type count[GFC_MAX_DIMENSIONS];
+ index_type extent[GFC_MAX_DIMENSIONS];
+ index_type sstride[GFC_MAX_DIMENSIONS];
+ index_type mstride[GFC_MAX_DIMENSIONS];
+ index_type dstride[GFC_MAX_DIMENSIONS];
+ const GFC_REAL_10 * restrict base;
+ const GFC_LOGICAL_1 * restrict mbase;
+ index_type * restrict dest;
+ index_type rank;
+ index_type n;
+ index_type len;
+ index_type delta;
+ index_type mdelta;
+ index_type dim;
+ int mask_kind;
+ int continue_loop;
+
+ /* Make dim zero based to avoid confusion. */
+ rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
+ len = GFC_DESCRIPTOR_EXTENT(array,dim);
+ if (len < 0)
+ len = 0;
+
+ delta = GFC_DESCRIPTOR_STRIDE(array,dim);
+ mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+ mbase = mask->base_addr;
+
+ mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+ if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
+#ifdef HAVE_GFC_LOGICAL_16
+ || mask_kind == 16
+#endif
+ )
+ mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
+ else
+ internal_error (NULL, "Funny sized logical array");
+
+ for (n = 0; n < dim; n++)
+ {
+ sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
+ mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+ if (extent[n] < 0)
+ extent[n] = 0;
+ }
+ for (n = dim; n < rank; n++)
+ {
+ sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
+ mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+ if (extent[n] < 0)
+ extent[n] = 0;
+ }
+
+ if (retarray->base_addr == NULL)
+ {
+ size_t alloc_size, str;
+
+ for (n = 0; n < rank; n++)
+ {
+ if (n == 0)
+ str = 1;
+ else
+ str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
+
+ GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
+
+ }
+
+ retarray->offset = 0;
+ retarray->dtype.rank = rank;
+
+ alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+ retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
+ if (alloc_size == 0)
+ {
+ /* Make sure we have a zero-sized array. */
+ GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
+ return;
+ }
+ }
+ else
+ {
+ if (rank != GFC_DESCRIPTOR_RANK (retarray))
+ runtime_error ("rank of return array incorrect in"
+ " FINDLOC intrinsic: is %ld, should be %ld",
+ (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+ (long int) rank);
+
+ if (unlikely (compile_options.bounds_check))
+ bounds_ifunction_return ((array_t *) retarray, extent,
+ "return value", "FINDLOC");
+ }
+
+ for (n = 0; n < rank; n++)
+ {
+ count[n] = 0;
+ dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+ if (extent[n] <= 0)
+ return;
+ }
+
+ dest = retarray->base_addr;
+ continue_loop = 1;
+
+ base = array->base_addr;
+ while (continue_loop)
+ {
+ const GFC_REAL_10 * restrict src;
+ const GFC_LOGICAL_1 * restrict msrc;
+ index_type result;
+
+ result = 0;
+ if (back)
+ {
+ src = base + (len - 1) * delta * 1;
+ msrc = mbase + (len - 1) * mdelta;
+ for (n = len; n > 0; n--, src -= delta * 1, msrc -= mdelta)
+ {
+ if (*msrc && *src == value)
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ else
+ {
+ src = base;
+ msrc = mbase;
+ for (n = 1; n <= len; n++, src += delta * 1, msrc += mdelta)
+ {
+ if (*msrc && *src == value)
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ *dest = result;
+
+ count[0]++;
+ base += sstride[0] * 1;
+ mbase += mstride[0];
+ dest += dstride[0];
+ n = 0;
+ while (count[n] == extent[n])
+ {
+ count[n] = 0;
+ base -= sstride[n] * extent[n] * 1;
+ mbase -= mstride[n] * extent[n];
+ dest -= dstride[n] * extent[n];
+ n++;
+ if (n >= rank)
+ {
+ continue_loop = 0;
+ break;
+ }
+ else
+ {
+ count[n]++;
+ base += sstride[n] * 1;
+ dest += dstride[n];
+ }
+ }
+ }
+}
+extern void sfindloc1_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
+ GFC_LOGICAL_4 back);
+export_proto(sfindloc1_r10);
+
+extern void
+sfindloc1_r10 (gfc_array_index_type * const restrict retarray,
+ gfc_array_r10 * const restrict array, GFC_REAL_10 value,
+ const index_type * restrict pdim, GFC_LOGICAL_4 *const restrict mask,
+ GFC_LOGICAL_4 back)
+{
+ index_type count[GFC_MAX_DIMENSIONS];
+ index_type extent[GFC_MAX_DIMENSIONS];
+ index_type dstride[GFC_MAX_DIMENSIONS];
+ index_type * restrict dest;
+ index_type rank;
+ index_type n;
+ index_type len;
+ index_type dim;
+ bool continue_loop;
+
+ if (mask == NULL || *mask)
+ {
+ findloc1_r10 (retarray, array, value, pdim, back);
+ return;
+ }
+ /* Make dim zero based to avoid confusion. */
+ rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
+ len = GFC_DESCRIPTOR_EXTENT(array,dim);
+ if (len < 0)
+ len = 0;
+
+ for (n = 0; n < dim; n++)
+ {
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+ if (extent[n] <= 0)
+ extent[n] = 0;
+ }
+
+ for (n = dim; n < rank; n++)
+ {
+ extent[n] =
+ GFC_DESCRIPTOR_EXTENT(array,n + 1);
+
+ if (extent[n] <= 0)
+ extent[n] = 0;
+ }
+
+
+ if (retarray->base_addr == NULL)
+ {
+ size_t alloc_size, str;
+
+ for (n = 0; n < rank; n++)
+ {
+ if (n == 0)
+ str = 1;
+ else
+ str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
+
+ GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
+ }
+
+ retarray->offset = 0;
+ retarray->dtype.rank = rank;
+
+ alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+ retarray->base_addr = xmallocarray (alloc_size, sizeof (index_type));
+ if (alloc_size == 0)
+ {
+ /* Make sure we have a zero-sized array. */
+ GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
+ return;
+ }
+ }
+ else
+ {
+ if (rank != GFC_DESCRIPTOR_RANK (retarray))
+ runtime_error ("rank of return array incorrect in"
+ " FINDLOC intrinsic: is %ld, should be %ld",
+ (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+ (long int) rank);
+
+ if (unlikely (compile_options.bounds_check))
+ bounds_ifunction_return ((array_t *) retarray, extent,
+ "return value", "FINDLOC");
+ }
+
+ for (n = 0; n < rank; n++)
+ {
+ count[n] = 0;
+ dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+ if (extent[n] <= 0)
+ return;
+ }
+ dest = retarray->base_addr;
+ continue_loop = 1;
+
+ while (continue_loop)
+ {
+ *dest = 0;
+
+ count[0]++;
+ dest += dstride[0];
+ n = 0;
+ while (count[n] == extent[n])
+ {
+ count[n] = 0;
+ dest -= dstride[n] * extent[n];
+ n++;
+ if (n >= rank)
+ {
+ continue_loop = 0;
+ break;
+ }
+ else
+ {
+ count[n]++;
+ dest += dstride[n];
+ }
+ }
+ }
+}
+#endif
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2019-11-08 19:30 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-05 12:24 Backports to gcc-9-branch Jakub Jelinek
-- strict thread matches above, loose matches on Subject: below --
2019-11-08 19:30 Jakub Jelinek
2019-08-01 6:34 Jakub Jelinek
2019-05-17 20:00 Jakub Jelinek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).