summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordoko <doko@6ca36cf4-e1d1-0310-8c6f-e303bb2178ca>2014-08-01 15:22:15 +0000
committerdoko <doko@6ca36cf4-e1d1-0310-8c6f-e303bb2178ca>2014-08-01 15:22:15 +0000
commit58c6d0e2da5be692c258997797c212f0d82cde62 (patch)
tree8ee80e05048bbfb94795e845ad04c869fb832c71
parent525a0893a750b6a99050c77e26612cd6ebd014b5 (diff)
downloadgcc-49-58c6d0e2da5be692c258997797c212f0d82cde62.tar.gz
* Update to SVN 20140731 (r213317) from the gcc-4_9-branch.
- Fix PR tree-optimization/61964. LP: #1347147. git-svn-id: svn://svn.debian.org/svn/gcccvs/branches/sid/gcc-4.9@7550 6ca36cf4-e1d1-0310-8c6f-e303bb2178ca
-rw-r--r--debian/changelog7
-rw-r--r--debian/patches/svn-updates.diff970
2 files changed, 962 insertions, 15 deletions
diff --git a/debian/changelog b/debian/changelog
index d8b8241..87686eb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+gcc-4.9 (4.9.1-5) UNRELEASED; urgency=medium
+
+ * Update to SVN 20140731 (r213317) from the gcc-4_9-branch.
+ - Fix PR tree-optimization/61964. LP: #1347147.
+
+ -- Matthias Klose <doko@debian.org> Fri, 01 Aug 2014 17:20:58 +0200
+
gcc-4.9 (4.9.1-4) unstable; urgency=high
* Update to SVN 20140731 (r213317) from the gcc-4_9-branch.
diff --git a/debian/patches/svn-updates.diff b/debian/patches/svn-updates.diff
index f096fdf..dd917a4 100644
--- a/debian/patches/svn-updates.diff
+++ b/debian/patches/svn-updates.diff
@@ -1,10 +1,10 @@
-# DP: updates from the 4.9 branch upto 20140731 (r213317).
+# DP: updates from the 4.9 branch upto 20140801 (r213487).
last_update()
{
cat > ${dir}LAST_UPDATED <EOF
-Thu Jul 31 09:55:11 CEST 2014
-Thu Jul 31 07:55:11 UTC 2014 (revision 213317)
+Fri Aug 1 17:14:05 CEST 2014
+Fri Aug 1 15:14:05 UTC 2014 (revision 213487)
EOF
}
@@ -185,6 +185,689 @@ Index: libitm/config/aarch64/target.h
+}
+
+} // namespace GTM
+Index: libgomp/libgomp.h
+===================================================================
+--- a/src/libgomp/libgomp.h (.../tags/gcc_4_9_1_release)
++++ b/src/libgomp/libgomp.h (.../branches/gcc-4_9-branch)
+@@ -274,6 +274,7 @@
+ struct gomp_task *task;
+ bool is_in;
+ bool redundant;
++ bool redundant_out;
+ };
+
+ struct gomp_dependers_vec
+@@ -283,6 +284,17 @@
+ struct gomp_task *elem[];
+ };
+
++/* Used when in GOMP_taskwait or in gomp_task_maybe_wait_for_dependencies. */
++
++struct gomp_taskwait
++{
++ bool in_taskwait;
++ bool in_depend_wait;
++ size_t n_depend;
++ struct gomp_task *last_parent_depends_on;
++ gomp_sem_t taskwait_sem;
++};
++
+ /* This structure describes a "task" to be run by a thread. */
+
+ struct gomp_task
+@@ -298,6 +310,7 @@
+ struct gomp_taskgroup *taskgroup;
+ struct gomp_dependers_vec *dependers;
+ struct htab *depend_hash;
++ struct gomp_taskwait *taskwait;
+ size_t depend_count;
+ size_t num_dependees;
+ struct gomp_task_icv icv;
+@@ -304,11 +317,10 @@
+ void (*fn) (void *);
+ void *fn_data;
+ enum gomp_task_kind kind;
+- bool in_taskwait;
+ bool in_tied_task;
+ bool final_task;
+ bool copy_ctors_done;
+- gomp_sem_t taskwait_sem;
++ bool parent_depends_on;
+ struct gomp_task_depend_entry depend[];
+ };
+
+@@ -582,7 +594,6 @@
+ {
+ if (__builtin_expect (task->depend_hash != NULL, 0))
+ free (task->depend_hash);
+- gomp_sem_destroy (&task->taskwait_sem);
+ }
+
+ /* team.c */
+Index: libgomp/task.c
+===================================================================
+--- a/src/libgomp/task.c (.../tags/gcc_4_9_1_release)
++++ b/src/libgomp/task.c (.../branches/gcc-4_9-branch)
+@@ -66,16 +66,16 @@
+ task->parent = parent_task;
+ task->icv = *prev_icv;
+ task->kind = GOMP_TASK_IMPLICIT;
+- task->in_taskwait = false;
++ task->taskwait = NULL;
+ task->in_tied_task = false;
+ task->final_task = false;
+ task->copy_ctors_done = false;
++ task->parent_depends_on = false;
+ task->children = NULL;
+ task->taskgroup = NULL;
+ task->dependers = NULL;
+ task->depend_hash = NULL;
+ task->depend_count = 0;
+- gomp_sem_init (&task->taskwait_sem, 0);
+ }
+
+ /* Clean up a task, after completing it. */
+@@ -104,6 +104,8 @@
+ while (task != children);
+ }
+
++static void gomp_task_maybe_wait_for_dependencies (void **depend);
++
+ /* Called when encountering an explicit task directive. If IF_CLAUSE is
+ false, then we must not delay in executing the task. If UNTIED is true,
+ then the task may be executed by any member of the team. */
+@@ -141,35 +143,12 @@
+
+ /* If there are depend clauses and earlier deferred sibling tasks
+ with depend clauses, check if there isn't a dependency. If there
+- is, fall through to the deferred task handling, as we can't
+- schedule such tasks right away. There is no need to handle
++ is, we need to wait for them. There is no need to handle
+ depend clauses for non-deferred tasks other than this, because
+ the parent task is suspended until the child task finishes and thus
+ it can't start further child tasks. */
+ if ((flags & 8) && thr->task && thr->task->depend_hash)
+- {
+- struct gomp_task *parent = thr->task;
+- struct gomp_task_depend_entry elem, *ent = NULL;
+- size_t ndepend = (uintptr_t) depend[0];
+- size_t nout = (uintptr_t) depend[1];
+- size_t i;
+- gomp_mutex_lock (&team->task_lock);
+- for (i = 0; i < ndepend; i++)
+- {
+- elem.addr = depend[i + 2];
+- ent = htab_find (parent->depend_hash, &elem);
+- for (; ent; ent = ent->next)
+- if (i >= nout && ent->is_in)
+- continue;
+- else
+- break;
+- if (ent)
+- break;
+- }
+- gomp_mutex_unlock (&team->task_lock);
+- if (ent)
+- goto defer;
+- }
++ gomp_task_maybe_wait_for_dependencies (depend);
+
+ gomp_init_task (&task, thr->task, gomp_icv (false));
+ task.kind = GOMP_TASK_IFFALSE;
+@@ -209,7 +188,6 @@
+ }
+ else
+ {
+- defer:;
+ struct gomp_task *task;
+ struct gomp_task *parent = thr->task;
+ struct gomp_taskgroup *taskgroup = parent->taskgroup;
+@@ -275,11 +253,12 @@
+ task->depend[i].task = task;
+ task->depend[i].is_in = i >= nout;
+ task->depend[i].redundant = false;
++ task->depend[i].redundant_out = false;
+
+ hash_entry_type *slot
+ = htab_find_slot (&parent->depend_hash, &task->depend[i],
+ INSERT);
+- hash_entry_type out = NULL;
++ hash_entry_type out = NULL, last = NULL;
+ if (*slot)
+ {
+ /* If multiple depends on the same task are the
+@@ -294,6 +273,11 @@
+ }
+ for (ent = *slot; ent; ent = ent->next)
+ {
++ if (ent->redundant_out)
++ break;
++
++ last = ent;
++
+ /* depend(in:...) doesn't depend on earlier
+ depend(in:...). */
+ if (i >= nout && ent->is_in)
+@@ -341,7 +325,8 @@
+ *slot = &task->depend[i];
+
+ /* There is no need to store more than one depend({,in}out:)
+- task per address in the hash table chain, because each out
++ task per address in the hash table chain for the purpose
++ of creation of deferred tasks, because each out
+ depends on all earlier outs, thus it is enough to record
+ just the last depend({,in}out:). For depend(in:), we need
+ to keep all of the previous ones not terminated yet, because
+@@ -348,14 +333,23 @@
+ a later depend({,in}out:) might need to depend on all of
+ them. So, if the new task's clause is depend({,in}out:),
+ we know there is at most one other depend({,in}out:) clause
+- in the list (out) and to maintain the invariant we now
+- need to remove it from the list. */
++ in the list (out). For non-deferred tasks we want to see
++ all outs, so they are moved to the end of the chain,
++ after first redundant_out entry all following entries
++ should be redundant_out. */
+ if (!task->depend[i].is_in && out)
+ {
+- if (out->next)
+- out->next->prev = out->prev;
+- out->prev->next = out->next;
+- out->redundant = true;
++ if (out != last)
++ {
++ out->next->prev = out->prev;
++ out->prev->next = out->next;
++ out->next = last->next;
++ out->prev = last;
++ last->next = out;
++ if (out->next)
++ out->next->prev = out;
++ }
++ out->redundant_out = true;
+ }
+ }
+ if (task->num_dependees)
+@@ -421,8 +415,20 @@
+ gomp_task_run_pre (struct gomp_task *child_task, struct gomp_task *parent,
+ struct gomp_taskgroup *taskgroup, struct gomp_team *team)
+ {
+- if (parent && parent->children == child_task)
+- parent->children = child_task->next_child;
++ if (parent)
++ {
++ if (parent->children == child_task)
++ parent->children = child_task->next_child;
++ if (__builtin_expect (child_task->parent_depends_on, 0)
++ && parent->taskwait->last_parent_depends_on == child_task)
++ {
++ if (child_task->prev_child->kind == GOMP_TASK_WAITING
++ && child_task->prev_child->parent_depends_on)
++ parent->taskwait->last_parent_depends_on = child_task->prev_child;
++ else
++ parent->taskwait->last_parent_depends_on = NULL;
++ }
++ }
+ if (taskgroup && taskgroup->children == child_task)
+ taskgroup->children = child_task->next_taskgroup;
+ child_task->prev_queue->next_queue = child_task->next_queue;
+@@ -489,8 +495,23 @@
+ {
+ if (parent->children)
+ {
+- task->next_child = parent->children;
+- task->prev_child = parent->children->prev_child;
++ /* If parent is in gomp_task_maybe_wait_for_dependencies
++ and it doesn't need to wait for this task, put it after
++ all ready to run tasks it needs to wait for. */
++ if (parent->taskwait && parent->taskwait->last_parent_depends_on
++ && !task->parent_depends_on)
++ {
++ struct gomp_task *last_parent_depends_on
++ = parent->taskwait->last_parent_depends_on;
++ task->next_child = last_parent_depends_on->next_child;
++ task->prev_child = last_parent_depends_on;
++ }
++ else
++ {
++ task->next_child = parent->children;
++ task->prev_child = parent->children->prev_child;
++ parent->children = task;
++ }
+ task->next_child->prev_child = task;
+ task->prev_child->next_child = task;
+ }
+@@ -498,12 +519,23 @@
+ {
+ task->next_child = task;
+ task->prev_child = task;
++ parent->children = task;
+ }
+- parent->children = task;
+- if (parent->in_taskwait)
++ if (parent->taskwait)
+ {
+- parent->in_taskwait = false;
+- gomp_sem_post (&parent->taskwait_sem);
++ if (parent->taskwait->in_taskwait)
++ {
++ parent->taskwait->in_taskwait = false;
++ gomp_sem_post (&parent->taskwait->taskwait_sem);
++ }
++ else if (parent->taskwait->in_depend_wait)
++ {
++ parent->taskwait->in_depend_wait = false;
++ gomp_sem_post (&parent->taskwait->taskwait_sem);
++ }
++ if (parent->taskwait->last_parent_depends_on == NULL
++ && task->parent_depends_on)
++ parent->taskwait->last_parent_depends_on = task;
+ }
+ }
+ if (taskgroup)
+@@ -575,6 +607,13 @@
+ struct gomp_task *parent = child_task->parent;
+ if (parent == NULL)
+ return;
++ if (__builtin_expect (child_task->parent_depends_on, 0)
++ && --parent->taskwait->n_depend == 0
++ && parent->taskwait->in_depend_wait)
++ {
++ parent->taskwait->in_depend_wait = false;
++ gomp_sem_post (&parent->taskwait->taskwait_sem);
++ }
+ child_task->prev_child->next_child = child_task->next_child;
+ child_task->next_child->prev_child = child_task->prev_child;
+ if (parent->children != child_task)
+@@ -589,10 +628,10 @@
+ written by child_task->fn above is flushed
+ before the NULL is written. */
+ __atomic_store_n (&parent->children, NULL, MEMMODEL_RELEASE);
+- if (parent->in_taskwait)
++ if (parent->taskwait && parent->taskwait->in_taskwait)
+ {
+- parent->in_taskwait = false;
+- gomp_sem_post (&parent->taskwait_sem);
++ parent->taskwait->in_taskwait = false;
++ gomp_sem_post (&parent->taskwait->taskwait_sem);
+ }
+ }
+ }
+@@ -736,6 +775,7 @@
+ struct gomp_task *task = thr->task;
+ struct gomp_task *child_task = NULL;
+ struct gomp_task *to_free = NULL;
++ struct gomp_taskwait taskwait;
+ int do_wake = 0;
+
+ /* The acquire barrier on load of task->children here synchronizes
+@@ -748,6 +788,7 @@
+ || __atomic_load_n (&task->children, MEMMODEL_ACQUIRE) == NULL)
+ return;
+
++ memset (&taskwait, 0, sizeof (taskwait));
+ gomp_mutex_lock (&team->task_lock);
+ while (1)
+ {
+@@ -754,6 +795,8 @@
+ bool cancelled = false;
+ if (task->children == NULL)
+ {
++ bool destroy_taskwait = task->taskwait != NULL;
++ task->taskwait = NULL;
+ gomp_mutex_unlock (&team->task_lock);
+ if (to_free)
+ {
+@@ -760,6 +803,8 @@
+ gomp_finish_task (to_free);
+ free (to_free);
+ }
++ if (destroy_taskwait)
++ gomp_sem_destroy (&taskwait.taskwait_sem);
+ return;
+ }
+ if (task->children->kind == GOMP_TASK_WAITING)
+@@ -780,9 +825,180 @@
+ }
+ }
+ else
++ {
++ /* All tasks we are waiting for are already running
++ in other threads. Wait for them. */
++ if (task->taskwait == NULL)
++ {
++ taskwait.in_depend_wait = false;
++ gomp_sem_init (&taskwait.taskwait_sem, 0);
++ task->taskwait = &taskwait;
++ }
++ taskwait.in_taskwait = true;
++ }
++ gomp_mutex_unlock (&team->task_lock);
++ if (do_wake)
++ {
++ gomp_team_barrier_wake (&team->barrier, do_wake);
++ do_wake = 0;
++ }
++ if (to_free)
++ {
++ gomp_finish_task (to_free);
++ free (to_free);
++ to_free = NULL;
++ }
++ if (child_task)
++ {
++ thr->task = child_task;
++ child_task->fn (child_task->fn_data);
++ thr->task = task;
++ }
++ else
++ gomp_sem_wait (&taskwait.taskwait_sem);
++ gomp_mutex_lock (&team->task_lock);
++ if (child_task)
++ {
++ finish_cancelled:;
++ size_t new_tasks
++ = gomp_task_run_post_handle_depend (child_task, team);
++ child_task->prev_child->next_child = child_task->next_child;
++ child_task->next_child->prev_child = child_task->prev_child;
++ if (task->children == child_task)
++ {
++ if (child_task->next_child != child_task)
++ task->children = child_task->next_child;
++ else
++ task->children = NULL;
++ }
++ gomp_clear_parent (child_task->children);
++ gomp_task_run_post_remove_taskgroup (child_task);
++ to_free = child_task;
++ child_task = NULL;
++ team->task_count--;
++ if (new_tasks > 1)
++ {
++ do_wake = team->nthreads - team->task_running_count
++ - !task->in_tied_task;
++ if (do_wake > new_tasks)
++ do_wake = new_tasks;
++ }
++ }
++ }
++}
++
++/* This is like GOMP_taskwait, but we only wait for tasks that the
++ upcoming task depends on. */
++
++static void
++gomp_task_maybe_wait_for_dependencies (void **depend)
++{
++ struct gomp_thread *thr = gomp_thread ();
++ struct gomp_task *task = thr->task;
++ struct gomp_team *team = thr->ts.team;
++ struct gomp_task_depend_entry elem, *ent = NULL;
++ struct gomp_taskwait taskwait;
++ struct gomp_task *last_parent_depends_on = NULL;
++ size_t ndepend = (uintptr_t) depend[0];
++ size_t nout = (uintptr_t) depend[1];
++ size_t i;
++ size_t num_awaited = 0;
++ struct gomp_task *child_task = NULL;
++ struct gomp_task *to_free = NULL;
++ int do_wake = 0;
++
++ gomp_mutex_lock (&team->task_lock);
++ for (i = 0; i < ndepend; i++)
++ {
++ elem.addr = depend[i + 2];
++ ent = htab_find (task->depend_hash, &elem);
++ for (; ent; ent = ent->next)
++ if (i >= nout && ent->is_in)
++ continue;
++ else
++ {
++ struct gomp_task *tsk = ent->task;
++ if (!tsk->parent_depends_on)
++ {
++ tsk->parent_depends_on = true;
++ ++num_awaited;
++ if (tsk->num_dependees == 0 && tsk->kind == GOMP_TASK_WAITING)
++ {
++ /* If a task we need to wait for is not already
++ running and is ready to be scheduled, move it
++ to front, so that we run it as soon as possible. */
++ if (last_parent_depends_on)
++ {
++ tsk->prev_child->next_child = tsk->next_child;
++ tsk->next_child->prev_child = tsk->prev_child;
++ tsk->prev_child = last_parent_depends_on;
++ tsk->next_child = last_parent_depends_on->next_child;
++ tsk->prev_child->next_child = tsk;
++ tsk->next_child->prev_child = tsk;
++ }
++ else if (tsk != task->children)
++ {
++ tsk->prev_child->next_child = tsk->next_child;
++ tsk->next_child->prev_child = tsk->prev_child;
++ tsk->prev_child = task->children;
++ tsk->next_child = task->children->next_child;
++ task->children = tsk;
++ tsk->prev_child->next_child = tsk;
++ tsk->next_child->prev_child = tsk;
++ }
++ last_parent_depends_on = tsk;
++ }
++ }
++ }
++ }
++ if (num_awaited == 0)
++ {
++ gomp_mutex_unlock (&team->task_lock);
++ return;
++ }
++
++ memset (&taskwait, 0, sizeof (taskwait));
++ taskwait.n_depend = num_awaited;
++ taskwait.last_parent_depends_on = last_parent_depends_on;
++ gomp_sem_init (&taskwait.taskwait_sem, 0);
++ task->taskwait = &taskwait;
++
++ while (1)
++ {
++ bool cancelled = false;
++ if (taskwait.n_depend == 0)
++ {
++ task->taskwait = NULL;
++ gomp_mutex_unlock (&team->task_lock);
++ if (to_free)
++ {
++ gomp_finish_task (to_free);
++ free (to_free);
++ }
++ gomp_sem_destroy (&taskwait.taskwait_sem);
++ return;
++ }
++ if (task->children->kind == GOMP_TASK_WAITING)
++ {
++ child_task = task->children;
++ cancelled
++ = gomp_task_run_pre (child_task, task, child_task->taskgroup,
++ team);
++ if (__builtin_expect (cancelled, 0))
++ {
++ if (to_free)
++ {
++ gomp_finish_task (to_free);
++ free (to_free);
++ to_free = NULL;
++ }
++ goto finish_cancelled;
++ }
++ }
++ else
+ /* All tasks we are waiting for are already running
+ in other threads. Wait for them. */
+- task->in_taskwait = true;
++ taskwait.in_depend_wait = true;
+ gomp_mutex_unlock (&team->task_lock);
+ if (do_wake)
+ {
+@@ -802,7 +1018,7 @@
+ thr->task = task;
+ }
+ else
+- gomp_sem_wait (&task->taskwait_sem);
++ gomp_sem_wait (&taskwait.taskwait_sem);
+ gomp_mutex_lock (&team->task_lock);
+ if (child_task)
+ {
+@@ -809,6 +1025,8 @@
+ finish_cancelled:;
+ size_t new_tasks
+ = gomp_task_run_post_handle_depend (child_task, team);
++ if (child_task->parent_depends_on)
++ --taskwait.n_depend;
+ child_task->prev_child->next_child = child_task->next_child;
+ child_task->next_child->prev_child = child_task->prev_child;
+ if (task->children == child_task)
+Index: libgomp/ChangeLog
+===================================================================
+--- a/src/libgomp/ChangeLog (.../tags/gcc_4_9_1_release)
++++ b/src/libgomp/ChangeLog (.../branches/gcc-4_9-branch)
+@@ -1,3 +1,33 @@
++2014-08-01 Jakub Jelinek <jakub@redhat.com>
++
++ * libgomp.h (struct gomp_task_depend_entry): Add redundant_out field.
++ (struct gomp_taskwait): New type.
++ (struct gomp_task): Add taskwait and parent_depends_on, remove
++ in_taskwait and taskwait_sem fields.
++ (gomp_finish_task): Don't destroy taskwait_sem.
++ * task.c (gomp_init_task): Don't init in_taskwait, instead init
++ taskwait and parent_depends_on.
++ (GOMP_task): For if (0) tasks with depend clause that depend on
++ earlier tasks don't defer them, instead call
++ gomp_task_maybe_wait_for_dependencies to wait for the dependencies.
++ Initialize redundant_out field, for redundant out entries just
++ move them at the end of linked list instead of removing them
++ completely, and set redundant_out flag instead of redundant.
++ (gomp_task_run_pre): Update last_parent_depends_on if scheduling
++ that task.
++ (gomp_task_run_post_handle_dependers): If parent is in
++ gomp_task_maybe_wait_for_dependencies and newly runnable task
++ is not parent_depends_on, queue it in parent->children linked
++ list after all runnable tasks with parent_depends_on set.
++ Adjust for addition of taskwait indirection.
++ (gomp_task_run_post_remove_parent): If parent is in
++ gomp_task_maybe_wait_for_dependencies and task to be removed
++ is parent_depends_on, decrement n_depend and if needed awake
++ parent. Adjust for addition of taskwait indirection.
++ (GOMP_taskwait): Adjust for addition of taskwait indirection.
++ (gomp_task_maybe_wait_for_dependencies): New function.
++ * testsuite/libgomp.c/depend-5.c: New test.
++
+ 2014-07-16 Release Manager
+
+ * GCC 4.9.1 released.
+Index: libgomp/testsuite/libgomp.c/depend-5.c
+===================================================================
+--- a/src/libgomp/testsuite/libgomp.c/depend-5.c (.../tags/gcc_4_9_1_release)
++++ b/src/libgomp/testsuite/libgomp.c/depend-5.c (.../branches/gcc-4_9-branch)
+@@ -0,0 +1,98 @@
++#include <stdlib.h>
++
++__attribute__((noinline, noclone)) void
++f1 (int ifval)
++{
++ int x = 1, y = 2, z = 3;
++ #pragma omp parallel
++ #pragma omp single
++ {
++ #pragma omp task shared (x) depend(out: x)
++ x = 2;
++ #pragma omp task shared (x) depend(inout: x)
++ {
++ if (x != 2)
++ abort ();
++ x = 3;
++ }
++ #pragma omp task shared (x) depend(inout: x)
++ {
++ if (x != 3)
++ abort ();
++ x = 4;
++ }
++ #pragma omp task shared (z) depend(in: z)
++ if (z != 3)
++ abort ();
++ #pragma omp task shared (z) depend(in: z)
++ if (z != 3)
++ abort ();
++ #pragma omp task shared (z) depend(in: z)
++ if (z != 3)
++ abort ();
++ #pragma omp task shared (z) depend(in: z)
++ if (z != 3)
++ abort ();
++ #pragma omp task shared (z) depend(in: z)
++ if (z != 3)
++ abort ();
++ #pragma omp task shared (z) depend(in: z)
++ if (z != 3)
++ abort ();
++ #pragma omp task shared (y) depend(in: y)
++ if (y != 2)
++ abort ();
++ #pragma omp task shared (y) depend(in: y)
++ if (y != 2)
++ abort ();
++ #pragma omp task shared (y) depend(in: y)
++ if (y != 2)
++ abort ();
++ #pragma omp task shared (y) depend(in: y)
++ if (y != 2)
++ abort ();
++ #pragma omp task if (ifval) shared (x, y) depend(in: x) depend(inout: y)
++ {
++ if (x != 4 || y != 2)
++ abort ();
++ y = 3;
++ }
++ if (ifval == 0)
++ {
++ /* The above if (0) task should have waited till all
++ the tasks with x and y dependencies finish. */
++ if (x != 4 || y != 3)
++ abort ();
++ x = 5;
++ y = 4;
++ }
++ #pragma omp task shared (z) depend(inout: z)
++ {
++ if (z != 3)
++ abort ();
++ z = 4;
++ }
++ #pragma omp task shared (z) depend(inout: z)
++ {
++ if (z != 4)
++ abort ();
++ z = 5;
++ }
++ #pragma omp taskwait
++ if (x != (ifval ? 4 : 5) || y != (ifval ? 3 : 4) || z != 5)
++ abort ();
++ #pragma omp task if (ifval) shared (x, y) depend(in: x) depend(inout: y)
++ {
++ if (x != (ifval ? 4 : 5) || y != (ifval ? 3 : 4))
++ abort ();
++ }
++ }
++}
++
++int
++main ()
++{
++ f1 (0);
++ f1 (1);
++ return 0;
++}
Index: libstdc++-v3/include/ext/random.tcc
===================================================================
--- a/src/libstdc++-v3/include/ext/random.tcc (.../tags/gcc_4_9_1_release)
@@ -374,6 +1057,31 @@ Index: configure
hppa*-hp-hpux10*)
host_makefile_frag="config/mh-pa-hpux10"
;;
+Index: gcc/tree-ssa-tail-merge.c
+===================================================================
+--- a/src/gcc/tree-ssa-tail-merge.c (.../tags/gcc_4_9_1_release)
++++ b/src/gcc/tree-ssa-tail-merge.c (.../branches/gcc-4_9-branch)
+@@ -1159,17 +1159,9 @@
+ lhs2 = gimple_get_lhs (s2);
+ if (TREE_CODE (lhs1) != SSA_NAME
+ && TREE_CODE (lhs2) != SSA_NAME)
+- {
+- /* If the vdef is the same, it's the same statement. */
+- if (vn_valueize (gimple_vdef (s1))
+- == vn_valueize (gimple_vdef (s2)))
+- return true;
+-
+- /* Test for structural equality. */
+- return (operand_equal_p (lhs1, lhs2, 0)
+- && gimple_operand_equal_value_p (gimple_assign_rhs1 (s1),
+- gimple_assign_rhs1 (s2)));
+- }
++ return (operand_equal_p (lhs1, lhs2, 0)
++ && gimple_operand_equal_value_p (gimple_assign_rhs1 (s1),
++ gimple_assign_rhs1 (s2)));
+ else if (TREE_CODE (lhs1) == SSA_NAME
+ && TREE_CODE (lhs2) == SSA_NAME)
+ return vn_valueize (lhs1) == vn_valueize (lhs2);
Index: gcc/c-family/c-gimplify.c
===================================================================
--- a/src/gcc/c-family/c-gimplify.c (.../tags/gcc_4_9_1_release)
@@ -413,7 +1121,7 @@ Index: gcc/DATESTAMP
+++ b/src/gcc/DATESTAMP (.../branches/gcc-4_9-branch)
@@ -1 +1 @@
-20140716
-+20140731
++20140801
Index: gcc/omp-low.c
===================================================================
--- a/src/gcc/omp-low.c (.../tags/gcc_4_9_1_release)
@@ -459,7 +1167,35 @@ Index: gcc/ChangeLog
===================================================================
--- a/src/gcc/ChangeLog (.../tags/gcc_4_9_1_release)
+++ b/src/gcc/ChangeLog (.../branches/gcc-4_9-branch)
-@@ -1,3 +1,179 @@
+@@ -1,3 +1,207 @@
++2014-08-01 Thomas Preud'homme <thomas.preudhomme@arm.com>
++
++ Backport from mainline
++ 2014-06-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
++
++ PR tree-optimization/61375
++ * tree-ssa-math-opts.c (find_bswap_or_nop_1): Cancel optimization if
++ symbolic number cannot be represented in an unsigned HOST_WIDE_INT.
++ (execute_optimize_bswap): Cancel optimization if CHAR_BIT != 8.
++
++2014-08-01 Richard Biener <rguenther@suse.de>
++
++ PR tree-optimization/61964
++ * tree-ssa-tail-merge.c (gimple_equal_p): Handle non-SSA LHS solely
++ by structural equality.
++
++2014-07-31 Oleg Endo <olegendo@gcc.gnu.org>
++
++ Backport from mainline
++ 2014-07-31 Oleg Endo <olegendo@gcc.gnu.org>
++
++ PR target/61844
++ * config/sh/sh.c (sh_legitimate_address_p,
++ sh_legitimize_reload_address): Handle reg+reg address modes when
++ ALLOW_INDEXED_ADDRESS is false.
++ * config/sh/predicates.md (general_movsrc_operand,
++ general_movdst_operand): Likewise.
++
+2014-07-25 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
@@ -639,7 +1375,7 @@ Index: gcc/ChangeLog
2014-07-16 Release Manager
* GCC 4.9.1 released.
-@@ -4,14 +183,14 @@
+@@ -4,14 +211,14 @@
2014-07-10 Cary Coutant <ccoutant@google.com>
@@ -658,7 +1394,7 @@ Index: gcc/ChangeLog
2014-07-10 Tom G. Christensen <tgc@jupiterrise.com>
-@@ -33,13 +212,13 @@
+@@ -33,13 +240,13 @@
PR target/61062
* config/arm/arm_neon.h (vtrn_s8, vtrn_s16, vtrn_u8, vtrn_u16, vtrn_p8,
vtrn_p16, vtrn_s32, vtrn_f32, vtrn_u32, vtrnq_s8, vtrnq_s16, vtrnq_s32,
@@ -679,7 +1415,7 @@ Index: gcc/ChangeLog
2014-07-09 Alan Lawrence <alan.lawrence@arm.com>
-@@ -157,11 +336,9 @@
+@@ -157,11 +364,9 @@
2014-06-24 Jakub Jelinek <jakub@redhat.com>
* gimplify.c (gimplify_scan_omp_clauses) <case OMP_CLAUSE_MAP,
@@ -693,7 +1429,7 @@ Index: gcc/ChangeLog
(gimplify_adjust_omp_clauses): Likewise.
* omp-low.c (lower_rec_simd_input_clauses,
lower_rec_input_clauses, expand_omp_simd): Handle non-constant
-@@ -176,9 +353,8 @@
+@@ -176,9 +381,8 @@
2014-06-18 Jakub Jelinek <jakub@redhat.com>
@@ -705,7 +1441,7 @@ Index: gcc/ChangeLog
(struct gimplify_adjust_omp_clauses_data): New type.
(gimplify_adjust_omp_clauses_1): Adjust for data being
a struct gimplify_adjust_omp_clauses_data pointer instead
-@@ -196,14 +372,12 @@
+@@ -196,14 +400,12 @@
gimple_seq * argument to omp_finish_clause hook.
* omp-low.c (scan_sharing_clauses): Call scan_omp_op on
non-DECL_P OMP_CLAUSE_DECL if ctx->outer.
@@ -723,7 +1459,7 @@ Index: gcc/ChangeLog
2014-06-10 Jakub Jelinek <jakub@redhat.com>
-@@ -227,8 +401,7 @@
+@@ -227,8 +429,7 @@
OMP_CLAUSE_LINEAR_STMT.
* omp-low.c (lower_rec_input_clauses): Fix typo.
(maybe_add_implicit_barrier_cancel, lower_omp_1): Add
@@ -733,7 +1469,7 @@ Index: gcc/ChangeLog
2014-06-30 Jason Merrill <jason@redhat.com>
-@@ -279,8 +452,7 @@
+@@ -279,8 +480,7 @@
(aarch64_sqdmlsl_lane<mode>): Likewise.
(aarch64_sqdmull_lane<mode>): Likewise.
(aarch64_sqdmull2_lane<mode>): Likewise.
@@ -907,6 +1643,46 @@ Index: gcc/testsuite/gcc.c-torture/execute/20050604-1.x
+set additional_flags "-Wno-psabi"
return 0
+Index: gcc/testsuite/gcc.c-torture/execute/pr61375.c
+===================================================================
+--- a/src/gcc/testsuite/gcc.c-torture/execute/pr61375.c (.../tags/gcc_4_9_1_release)
++++ b/src/gcc/testsuite/gcc.c-torture/execute/pr61375.c (.../branches/gcc-4_9-branch)
+@@ -0,0 +1,35 @@
++#ifdef __UINT64_TYPE__
++typedef __UINT64_TYPE__ uint64_t;
++#else
++typedef unsigned long long uint64_t;
++#endif
++
++#ifndef __SIZEOF_INT128__
++#define __int128 long long
++#endif
++
++/* Some version of bswap optimization would ICE when analyzing a mask constant
++ too big for an HOST_WIDE_INT (PR61375). */
++
++__attribute__ ((noinline, noclone)) uint64_t
++uint128_central_bitsi_ior (unsigned __int128 in1, uint64_t in2)
++{
++ __int128 mask = (__int128)0xffff << 56;
++ return ((in1 & mask) >> 56) | in2;
++}
++
++int
++main (int argc)
++{
++ __int128 in = 1;
++#ifdef __SIZEOF_INT128__
++ in <<= 64;
++#endif
++ if (sizeof (uint64_t) * __CHAR_BIT__ != 64)
++ return 0;
++ if (sizeof (unsigned __int128) * __CHAR_BIT__ != 128)
++ return 0;
++ if (uint128_central_bitsi_ior (in, 2) != 0x102)
++ __builtin_abort ();
++ return 0;
++}
Index: gcc/testsuite/gcc.c-torture/execute/20050316-1.x
===================================================================
--- a/src/gcc/testsuite/gcc.c-torture/execute/20050316-1.x (.../tags/gcc_4_9_1_release)
@@ -970,6 +1746,55 @@ Index: gcc/testsuite/gnat.dg/pack20_pkg.ads
+ procedure Modify (Fixed : in out String_Ptr);
+
+end Pack20_Pkg;
+Index: gcc/testsuite/gcc.dg/pr51879-18.c
+===================================================================
+--- a/src/gcc/testsuite/gcc.dg/pr51879-18.c (.../tags/gcc_4_9_1_release)
++++ b/src/gcc/testsuite/gcc.dg/pr51879-18.c (.../branches/gcc-4_9-branch)
+@@ -13,5 +13,5 @@
+ *q = foo ();
+ }
+
+-/* { dg-final { scan-tree-dump-times "foo \\(" 1 "pre"} } */
++/* { dg-final { scan-tree-dump-times "foo \\(" 1 "pre" { xfail *-*-* } } } */
+ /* { dg-final { cleanup-tree-dump "pre" } } */
+Index: gcc/testsuite/gcc.dg/torture/pr61964.c
+===================================================================
+--- a/src/gcc/testsuite/gcc.dg/torture/pr61964.c (.../tags/gcc_4_9_1_release)
++++ b/src/gcc/testsuite/gcc.dg/torture/pr61964.c (.../branches/gcc-4_9-branch)
+@@ -0,0 +1,33 @@
++/* { dg-do run } */
++
++extern void abort (void);
++
++struct node { struct node *next, *prev; } node;
++struct head { struct node *first; } heads[5];
++int k = 2;
++struct head *head = &heads[2];
++
++static int __attribute__((noinline))
++foo()
++{
++ node.prev = (void *)head;
++ head->first = &node;
++
++ struct node *n = head->first;
++ struct head *h = &heads[k];
++
++ if (n->prev == (void *)h)
++ h->first = n->next;
++ else
++ n->prev->next = n->next;
++
++ n->next = h->first;
++ return n->next == &node;
++}
++
++int main()
++{
++ if (foo ())
++ abort ();
++ return 0;
++}
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-copyprop-2.c
===================================================================
--- a/src/gcc/testsuite/gcc.dg/tree-ssa/ssa-copyprop-2.c (.../tags/gcc_4_9_1_release)
@@ -1039,7 +1864,21 @@ Index: gcc/testsuite/ChangeLog
===================================================================
--- a/src/gcc/testsuite/ChangeLog (.../tags/gcc_4_9_1_release)
+++ b/src/gcc/testsuite/ChangeLog (.../branches/gcc-4_9-branch)
-@@ -1,3 +1,104 @@
+@@ -1,3 +1,118 @@
++2014-08-01 Thomas Preud'homme <thomas.preudhomme@arm.com>
++
++ Backport from mainline
++ 2014-06-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
++
++ PR tree-optimization/61375
++ * gcc.c-torture/execute/pr61375-1.c: New test.
++
++2014-08-01 Richard Biener <rguenther@suse.de>
++
++ PR tree-optimization/61964
++ * gcc.dg/torture/pr61964.c: New testcase.
++ * gcc.dg/pr51879-18.c: XFAIL.
++
+2014-07-28 Richard Biener <rguenther@suse.de>
+
+ PR rtl-optimization/61801
@@ -1144,7 +1983,7 @@ Index: gcc/testsuite/ChangeLog
2014-07-16 Release Manager
* GCC 4.9.1 released.
-@@ -17,7 +118,8 @@
+@@ -17,7 +132,8 @@
2014-06-09 Alan Lawrence <alan.lawrence@arm.com>
PR target/61062
@@ -1154,7 +1993,7 @@ Index: gcc/testsuite/ChangeLog
2014-07-08 Jakub Jelinek <jakub@redhat.com>
-@@ -34,8 +136,8 @@
+@@ -34,8 +150,8 @@
2014-07-08 Alan Lawrence <alan.lawrence@arm.com>
@@ -1230,6 +2069,37 @@ Index: gcc/testsuite/c-c++-common/pr61741.c
+ __builtin_abort ();
+ return 0;
+}
+Index: gcc/tree-ssa-math-opts.c
+===================================================================
+--- a/src/gcc/tree-ssa-math-opts.c (.../tags/gcc_4_9_1_release)
++++ b/src/gcc/tree-ssa-math-opts.c (.../branches/gcc-4_9-branch)
+@@ -1749,6 +1749,8 @@
+ size = TYPE_PRECISION (n->type);
+ if (size % BITS_PER_UNIT != 0)
+ return NULL_TREE;
++ if (size > HOST_BITS_PER_WIDEST_INT)
++ return NULL_TREE;
+ size /= BITS_PER_UNIT;
+ n->n = (sizeof (HOST_WIDEST_INT) < 8 ? 0 :
+ (unsigned HOST_WIDEST_INT)0x08070605 << 32 | 0x04030201);
+@@ -1792,6 +1794,8 @@
+ type_size = TYPE_PRECISION (type);
+ if (type_size % BITS_PER_UNIT != 0)
+ return NULL_TREE;
++ if (type_size > (int) HOST_BITS_PER_WIDEST_INT)
++ return NULL_TREE;
+
+ /* Sign extension: result is dependent on the value. */
+ old_type_size = TYPE_PRECISION (n->type);
+@@ -1932,7 +1936,7 @@
+ bool changed = false;
+ tree bswap16_type = NULL_TREE, bswap32_type = NULL_TREE, bswap64_type = NULL_TREE;
+
+- if (BITS_PER_UNIT != 8)
++ if (BITS_PER_UNIT != 8 || CHAR_BIT != 8)
+ return 0;
+
+ if (sizeof (HOST_WIDEST_INT) < 8)
Index: gcc/expr.c
===================================================================
--- a/src/gcc/expr.c (.../tags/gcc_4_9_1_release)
@@ -1613,6 +2483,76 @@ Index: gcc/config/i386/i386.c
classes[i] = merge_classes (subclasses[i], classes[i]);
}
}
+Index: gcc/config/sh/predicates.md
+===================================================================
+--- a/src/gcc/config/sh/predicates.md (.../tags/gcc_4_9_1_release)
++++ b/src/gcc/config/sh/predicates.md (.../branches/gcc-4_9-branch)
+@@ -489,6 +489,10 @@
+ rtx mem_rtx = MEM_P (op) ? op : SUBREG_REG (op);
+ rtx x = XEXP (mem_rtx, 0);
+
++ if (! ALLOW_INDEXED_ADDRESS
++ && GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
++ return false;
++
+ if ((mode == QImode || mode == HImode)
+ && GET_CODE (x) == PLUS
+ && REG_P (XEXP (x, 0))
+@@ -567,6 +571,10 @@
+ rtx mem_rtx = MEM_P (op) ? op : SUBREG_REG (op);
+ rtx x = XEXP (mem_rtx, 0);
+
++ if (! ALLOW_INDEXED_ADDRESS
++ && GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
++ return false;
++
+ if ((mode == QImode || mode == HImode)
+ && GET_CODE (x) == PLUS
+ && REG_P (XEXP (x, 0))
+Index: gcc/config/sh/sh.c
+===================================================================
+--- a/src/gcc/config/sh/sh.c (.../tags/gcc_4_9_1_release)
++++ b/src/gcc/config/sh/sh.c (.../branches/gcc-4_9-branch)
+@@ -10207,6 +10207,10 @@
+ static bool
+ sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+ {
++ if (! ALLOW_INDEXED_ADDRESS
++ && GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
++ return false;
++
+ if (REG_P (x) && REGNO (x) == GBR_REG)
+ return true;
+
+@@ -10436,6 +10440,28 @@
+ enum reload_type type = (enum reload_type) itype;
+ const int mode_sz = GET_MODE_SIZE (mode);
+
++ if (! ALLOW_INDEXED_ADDRESS
++ && GET_CODE (*p) == PLUS
++ && REG_P (XEXP (*p, 0)) && REG_P (XEXP (*p, 1)))
++ {
++ *p = copy_rtx (*p);
++ push_reload (*p, NULL_RTX, p, NULL,
++ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, type);
++ return true;
++ }
++
++ if (! ALLOW_INDEXED_ADDRESS
++ && GET_CODE (*p) == PLUS
++ && GET_CODE (XEXP (*p, 0)) == PLUS)
++ {
++ rtx sum = gen_rtx_PLUS (Pmode, XEXP (XEXP (*p, 0), 0),
++ XEXP (XEXP (*p, 0), 1));
++ *p = gen_rtx_PLUS (Pmode, sum, XEXP (*p, 1));
++ push_reload (sum, NULL_RTX, &XEXP (*p, 0), NULL,
++ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, type);
++ return true;
++ }
++
+ if (TARGET_SHMEDIA)
+ return false;
+
Index: gcc/config/nios2/rtems.h
===================================================================
--- a/src/gcc/config/nios2/rtems.h (.../tags/gcc_4_9_1_release)