aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Weigand <Ulrich.Weigand@de.ibm.com>2008-07-21 21:26:37 +0000
committerUlrich Weigand <Ulrich.Weigand@de.ibm.com>2008-07-21 21:26:37 +0000
commit01800875fc3d590722d0be2db95e159c9581e79c (patch)
tree8cd29d044deeee26792ca51ff9c93427bcd9e0fe
parent726b493c1b65045870597ab142d7de73704293cf (diff)
Merge with gcc-4_3-branch up to revision 138037.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/cell-4_3-branch@138044 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog45
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/config/m32c/m32c.c15
-rw-r--r--gcc/config/sh/sh.h12
-rw-r--r--gcc/config/spu/spu.md65
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/call.c4
-rw-r--r--gcc/expr.c6
-rw-r--r--gcc/fortran/ChangeLog7
-rw-r--r--gcc/fortran/resolve.c44
-rw-r--r--gcc/fwprop.c113
-rw-r--r--gcc/omp-low.c1
-rw-r--r--gcc/reload.c2
-rw-r--r--gcc/testsuite/ChangeLog20
-rw-r--r--gcc/testsuite/g++.dg/conversion/op5.C20
-rw-r--r--gcc/testsuite/gcc.dg/gomp/atomic-11.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr35281.c19
-rw-r--r--gcc/testsuite/gfortran.dg/used_types_20.f9049
18 files changed, 361 insertions, 86 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 878b6792a71..2918d5d3085 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -17,6 +17,51 @@
(rs6000_cpu_cpp_builtins): Enable context-sensitive macros if not
compiling an ISO C dialect.
+2008-07-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/spu/spu.md ("div<mode>3"): Convert into expander, move
+ original insn and splitter contents into ...
+ ("*div<mode>3_fast"): ... this new pattern. Enable only if
+ flag_unsafe_math_optimizations. Add dummy scratch register.
+ ("*div<mode>3_adjusted"): New insn and splitter. Enable only if
+ !flag_unsafe_math_optimizations. Returns number with next
+ highest magnitude if this is still less or equal to the true
+ quotient in magnitude.
+
+2008-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/36877
+ * omp-low.c (expand_omp_atomic_fetch_op): Make sure the
+ return value of the builtin is ignored.
+
+2008-07-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR target/36780
+ PR target/36827
+ * reload.c (find_reloads_subreg_address): Only reload address if
+ reloaded == 0, not for reloaded != 1.
+
+ Revert:
+ 2008-07-16 Joseph Myers <joseph@codesourcery.com>
+ * config/m32c/m32c.c (BIG_FB_ADJ): Move definition earlier.
+ (m32c_legitimate_address_p): Handle "++rii" addresses created by
+ m32c_legitimize_reload_address.
+
+ 2008-07-15 Kaz Kojima <kkojima@gcc.gnu.org>
+ * config/sh/sh.h (GO_IF_LEGITIMATE_ADDRESS): Allow
+ (plus (plus (reg) (const_int)) (const_int)) when reload_in_progress.
+
+2008-07-18 Paolo Bonzini <bonzini@gnu.org>
+
+ PR rtl-optimization/35281
+ * expr.c (convert_move): Use a new pseudo for the intermediate
+ from_mode->word_mode result.
+ * fwprop.c (PR_CAN_APPEAR, PR_HANDLE_MEM): New.
+ (propagate_rtx_1): Handle PR_HANDLE_MEM.
+ (propagate_rtx): Pass PR_HANDLE_MEM if appropriate.
+ (varying_mem_p): Move above propagate_rtx.
+ (all_uses_available_at): Do not check MEMs.
+
2008-07-17 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Backport from mainline:
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index bf4dc5b288f..10b4941f285 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20080717
+20080721
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 8e347deb52d..2b3bab54ffc 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -1777,8 +1777,6 @@ m32c_init_libfuncs (void)
/* Addressing Modes */
-#define BIG_FB_ADJ 0
-
/* Used by GO_IF_LEGITIMATE_ADDRESS. The r8c/m32c family supports a
wide range of non-orthogonal addressing modes, including the
ability to double-indirect on *some* of them. Not all insns
@@ -1896,17 +1894,6 @@ m32c_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
return 0;
}
}
- if (RTX_IS ("++rii"))
- {
- rtx reg = patternr[2];
- HOST_WIDE_INT offs = INTVAL (patternr[3]);
-
- /* Avoid reloads for addresses generated by
- m32c_legitimize_reload_address being generated by
- find_reloads_subreg_address. */
- if (REGNO (reg) == FB_REGNO && offs == -BIG_FB_ADJ)
- return 1;
- }
return 0;
}
@@ -1954,6 +1941,8 @@ m32c_reg_ok_for_base_p (rtx x, int strict)
frame, so the third case seems best. Note that we subtract the
zero, but detect that in the addhi3 pattern. */
+#define BIG_FB_ADJ 0
+
/* Implements LEGITIMIZE_ADDRESS. The only address we really have to
worry about is frame base offsets, as $fb has a limited
displacement range. We deal with this by attempting to reload $fb
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 1c0db4b535f..2eb0a2276cb 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -2496,18 +2496,6 @@ struct sh_args {
goto LABEL; \
} \
} \
- /* When reload in progress, find_reloads_subreg_address tries to \
- make a new reload for some types of address. Unfortunately it \
- generates wrong code on SH. See PR36780. The following is to \
- avoid this issue. */ \
- if (!TARGET_SHMEDIA && reload_in_progress \
- && GET_CODE (X) == PLUS \
- && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8) \
- && GET_CODE (XEXP ((X), 0)) == PLUS \
- && GET_CODE (XEXP (XEXP ((X), 0), 1)) == CONST_INT \
- && BASE_REGISTER_RTX_P (XEXP (XEXP ((X), 0), 0)) \
- && GET_CODE (XEXP ((X), 1)) == CONST_INT) \
- goto LABEL; \
}
/* Try machine-dependent ways of modifying an illegitimate address
diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md
index a89ab15b953..8feeca451a5 100644
--- a/gcc/config/spu/spu.md
+++ b/gcc/config/spu/spu.md
@@ -1718,20 +1718,33 @@
[(set_attr "type" "multi0")
(set_attr "length" "80")])
-(define_insn_and_split "div<mode>3"
+(define_expand "div<mode>3"
+ [(parallel
+ [(set (match_operand:VSF 0 "spu_reg_operand" "")
+ (div:VSF (match_operand:VSF 1 "spu_reg_operand" "")
+ (match_operand:VSF 2 "spu_reg_operand" "")))
+ (clobber (match_scratch:VSF 3 ""))
+ (clobber (match_scratch:VSF 4 ""))
+ (clobber (match_scratch:VSF 5 ""))])]
+ ""
+ "")
+
+(define_insn_and_split "*div<mode>3_fast"
[(set (match_operand:VSF 0 "spu_reg_operand" "=r")
(div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
(match_operand:VSF 2 "spu_reg_operand" "r")))
(clobber (match_scratch:VSF 3 "=&r"))
- (clobber (match_scratch:VSF 4 "=&r"))]
- ""
+ (clobber (match_scratch:VSF 4 "=&r"))
+ (clobber (scratch:VSF))]
+ "flag_unsafe_math_optimizations"
"#"
"reload_completed"
[(set (match_dup:VSF 0)
(div:VSF (match_dup:VSF 1)
(match_dup:VSF 2)))
(clobber (match_dup:VSF 3))
- (clobber (match_dup:VSF 4))]
+ (clobber (match_dup:VSF 4))
+ (clobber (scratch:VSF))]
{
emit_insn (gen_frest_<mode>(operands[3], operands[2]));
emit_insn (gen_fi_<mode>(operands[3], operands[2], operands[3]));
@@ -1741,6 +1754,50 @@
DONE;
})
+(define_insn_and_split "*div<mode>3_adjusted"
+ [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
+ (div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
+ (match_operand:VSF 2 "spu_reg_operand" "r")))
+ (clobber (match_scratch:VSF 3 "=&r"))
+ (clobber (match_scratch:VSF 4 "=&r"))
+ (clobber (match_scratch:VSF 5 "=&r"))]
+ "!flag_unsafe_math_optimizations"
+ "#"
+ "reload_completed"
+ [(set (match_dup:VSF 0)
+ (div:VSF (match_dup:VSF 1)
+ (match_dup:VSF 2)))
+ (clobber (match_dup:VSF 3))
+ (clobber (match_dup:VSF 4))
+ (clobber (match_dup:VSF 5))]
+ {
+ emit_insn (gen_frest_<mode> (operands[3], operands[2]));
+ emit_insn (gen_fi_<mode> (operands[3], operands[2], operands[3]));
+ emit_insn (gen_mul<mode>3 (operands[4], operands[1], operands[3]));
+ emit_insn (gen_fnms_<mode> (operands[5], operands[4], operands[2], operands[1]));
+ emit_insn (gen_fma_<mode> (operands[3], operands[5], operands[3], operands[4]));
+
+ /* Due to truncation error, the quotient result may be low by 1 ulp.
+ Conditionally add one if the estimate is too small in magnitude. */
+
+ emit_move_insn (gen_lowpart (<F2I>mode, operands[4]),
+ spu_const (<F2I>mode, 0x80000000ULL));
+ emit_move_insn (gen_lowpart (<F2I>mode, operands[5]),
+ spu_const (<F2I>mode, 0x3f800000ULL));
+ emit_insn (gen_selb (operands[5], operands[5], operands[1], operands[4]));
+
+ emit_insn (gen_add<f2i>3 (gen_lowpart (<F2I>mode, operands[4]),
+ gen_lowpart (<F2I>mode, operands[3]),
+ spu_const (<F2I>mode, 1)));
+ emit_insn (gen_fnms_<mode> (operands[0], operands[2], operands[4], operands[1]));
+ emit_insn (gen_mul<mode>3 (operands[0], operands[0], operands[5]));
+ emit_insn (gen_cgt_<f2i> (gen_lowpart (<F2I>mode, operands[0]),
+ gen_lowpart (<F2I>mode, operands[0]),
+ spu_const (<F2I>mode, -1)));
+ emit_insn (gen_selb (operands[0], operands[3], operands[4], operands[0]));
+ DONE;
+ })
+
;; Taken from STI's gcc
;; Does not correctly handle INF or NAN.
(define_expand "divdf3"
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8a5004f74eb..951d38d2126 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2008-07-18 Dodji Seketeli <dseketel@redhat.com>
+
+ PR c++/36407
+ * gcc/cp/call.c (convert_like_real): Don't take the error code path
+ when a rvalue or base conversion has the bad_p field set.
+
2008-07-07 Simon Martin <simartin@users.sourceforge.net>
PR c++/34963
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 023cb7bfff9..13560e21817 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4354,7 +4354,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (convs->bad_p
&& convs->kind != ck_user
&& convs->kind != ck_ambig
- && convs->kind != ck_ref_bind)
+ && convs->kind != ck_ref_bind
+ && convs->kind != ck_rvalue
+ && convs->kind != ck_base)
{
conversion *t = convs;
for (; t; t = convs->u.next)
diff --git a/gcc/expr.c b/gcc/expr.c
index e985e3c3990..5dd79d66ebe 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -552,15 +552,15 @@ convert_move (rtx to, rtx from, int unsignedp)
&& ((code = can_extend_p (to_mode, word_mode, unsignedp))
!= CODE_FOR_nothing))
{
+ rtx word_to = gen_reg_rtx (word_mode);
if (REG_P (to))
{
if (reg_overlap_mentioned_p (to, from))
from = force_reg (from_mode, from);
emit_insn (gen_rtx_CLOBBER (VOIDmode, to));
}
- convert_move (gen_lowpart (word_mode, to), from, unsignedp);
- emit_unop_insn (code, to,
- gen_lowpart (word_mode, to), equiv_code);
+ convert_move (word_to, from, unsignedp);
+ emit_unop_insn (code, to, word_to, equiv_code);
return;
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 67d4598ada1..de910ee28f3 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,10 @@
+2008-07-19 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/36366
+ * resolve.c (add_dt_to_dt_list): New function.
+ (resolve_fl_derived): Call new function for pointer components
+ and when derived type resolved.
+
2008-07-17 Tobias Burnus <burnus@net-b.de>
PR fortran/36824
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index f897110510f..ceec21f4673 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -7467,13 +7467,33 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
}
+/* Add a derived type to the dt_list. The dt_list is used in trans-types.c
+ to give all identical derived types the same backend_decl. */
+static void
+add_dt_to_dt_list (gfc_symbol *derived)
+{
+ gfc_dt_list *dt_list;
+
+ for (dt_list = gfc_derived_types; dt_list; dt_list = dt_list->next)
+ if (derived == dt_list->derived)
+ break;
+
+ if (dt_list == NULL)
+ {
+ dt_list = gfc_get_dt_list ();
+ dt_list->next = gfc_derived_types;
+ dt_list->derived = derived;
+ gfc_derived_types = dt_list;
+ }
+}
+
+
/* Resolve the components of a derived type. */
static try
resolve_fl_derived (gfc_symbol *sym)
{
gfc_component *c;
- gfc_dt_list * dt_list;
int i;
for (c = sym->components; c != NULL; c = c->next)
@@ -7525,6 +7545,16 @@ resolve_fl_derived (gfc_symbol *sym)
return FAILURE;
}
+ /* Ensure that all the derived type components are put on the
+ derived type list; even in formal namespaces, where derived type
+ pointer components might not have been declared. */
+ if (c->ts.type == BT_DERIVED
+ && c->ts.derived
+ && c->ts.derived->components
+ && c->pointer
+ && sym != c->ts.derived)
+ add_dt_to_dt_list (c->ts.derived);
+
if (c->pointer || c->allocatable || c->as == NULL)
continue;
@@ -7546,17 +7576,7 @@ resolve_fl_derived (gfc_symbol *sym)
}
/* Add derived type to the derived type list. */
- for (dt_list = gfc_derived_types; dt_list; dt_list = dt_list->next)
- if (sym == dt_list->derived)
- break;
-
- if (dt_list == NULL)
- {
- dt_list = gfc_get_dt_list ();
- dt_list->next = gfc_derived_types;
- dt_list->derived = sym;
- gfc_derived_types = dt_list;
- }
+ add_dt_to_dt_list (sym);
return SUCCESS;
}
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index d43f43447e5..fa4281a0462 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -208,47 +208,76 @@ should_replace_address (rtx old, rtx new, enum machine_mode mode)
return (gain > 0);
}
+
+/* Flags for the last parameter of propagate_rtx_1. */
+
+enum {
+ /* If PR_CAN_APPEAR is true, propagate_rtx_1 always returns true;
+ if it is false, propagate_rtx_1 returns false if, for at least
+ one occurrence OLD, it failed to collapse the result to a constant.
+ For example, (mult:M (reg:M A) (minus:M (reg:M B) (reg:M A))) may
+ collapse to zero if replacing (reg:M B) with (reg:M A).
+
+ PR_CAN_APPEAR is disregarded inside MEMs: in that case,
+ propagate_rtx_1 just tries to make cheaper and valid memory
+ addresses. */
+ PR_CAN_APPEAR = 1,
+
+ /* If PR_HANDLE_MEM is not set, propagate_rtx_1 won't attempt any replacement
+ outside memory addresses. This is needed because propagate_rtx_1 does
+ not do any analysis on memory; thus it is very conservative and in general
+ it will fail if non-read-only MEMs are found in the source expression.
+
+ PR_HANDLE_MEM is set when the source of the propagation was not
+ another MEM. Then, it is safe not to treat non-read-only MEMs as
+ ``opaque'' objects. */
+ PR_HANDLE_MEM = 2,
+};
+
+
/* Replace all occurrences of OLD in *PX with NEW and try to simplify the
resulting expression. Replace *PX with a new RTL expression if an
occurrence of OLD was found.
- If CAN_APPEAR is true, we always return true; if it is false, we
- can return false if, for at least one occurrence OLD, we failed to
- collapse the result to a constant. For example, (mult:M (reg:M A)
- (minus:M (reg:M B) (reg:M A))) may collapse to zero if replacing
- (reg:M B) with (reg:M A).
-
- CAN_APPEAR is disregarded inside MEMs: in that case, we always return
- true if the simplification is a cheaper and valid memory address.
-
This is only a wrapper around simplify-rtx.c: do not add any pattern
matching code here. (The sole exception is the handling of LO_SUM, but
that is because there is no simplify_gen_* function for LO_SUM). */
static bool
-propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
+propagate_rtx_1 (rtx *px, rtx old, rtx new, int flags)
{
rtx x = *px, tem = NULL_RTX, op0, op1, op2;
enum rtx_code code = GET_CODE (x);
enum machine_mode mode = GET_MODE (x);
enum machine_mode op_mode;
+ bool can_appear = (flags & PR_CAN_APPEAR) != 0;
bool valid_ops = true;
- /* If X is OLD_RTX, return NEW_RTX. Otherwise, if this is an expression,
- try to build a new expression from recursive substitution. */
+ if (!(flags & PR_HANDLE_MEM) && MEM_P (x) && !MEM_READONLY_P (x))
+ {
+ /* If unsafe, change MEMs to CLOBBERs or SCRATCHes (to preserve whether
+ they have side effects or not). */
+ *px = (side_effects_p (x)
+ ? gen_rtx_CLOBBER (GET_MODE (x), const0_rtx)
+ : gen_rtx_SCRATCH (GET_MODE (x)));
+ return false;
+ }
+ /* If X is OLD_RTX, return NEW_RTX. But not if replacing only within an
+ address, and we are *not* inside one. */
if (x == old)
{
*px = new;
return can_appear;
}
+ /* If this is an expression, try recursive substitution. */
switch (GET_RTX_CLASS (code))
{
case RTX_UNARY:
op0 = XEXP (x, 0);
op_mode = GET_MODE (op0);
- valid_ops &= propagate_rtx_1 (&op0, old, new, can_appear);
+ valid_ops &= propagate_rtx_1 (&op0, old, new, flags);
if (op0 == XEXP (x, 0))
return true;
tem = simplify_gen_unary (code, mode, op0, op_mode);
@@ -258,8 +287,8 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
case RTX_COMM_ARITH:
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
- valid_ops &= propagate_rtx_1 (&op0, old, new, can_appear);
- valid_ops &= propagate_rtx_1 (&op1, old, new, can_appear);
+ valid_ops &= propagate_rtx_1 (&op0, old, new, flags);
+ valid_ops &= propagate_rtx_1 (&op1, old, new, flags);
if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
return true;
tem = simplify_gen_binary (code, mode, op0, op1);
@@ -270,8 +299,8 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
- valid_ops &= propagate_rtx_1 (&op0, old, new, can_appear);
- valid_ops &= propagate_rtx_1 (&op1, old, new, can_appear);
+ valid_ops &= propagate_rtx_1 (&op0, old, new, flags);
+ valid_ops &= propagate_rtx_1 (&op1, old, new, flags);
if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
return true;
tem = simplify_gen_relational (code, mode, op_mode, op0, op1);
@@ -283,9 +312,9 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
op1 = XEXP (x, 1);
op2 = XEXP (x, 2);
op_mode = GET_MODE (op0);
- valid_ops &= propagate_rtx_1 (&op0, old, new, can_appear);
- valid_ops &= propagate_rtx_1 (&op1, old, new, can_appear);
- valid_ops &= propagate_rtx_1 (&op2, old, new, can_appear);
+ valid_ops &= propagate_rtx_1 (&op0, old, new, flags);
+ valid_ops &= propagate_rtx_1 (&op1, old, new, flags);
+ valid_ops &= propagate_rtx_1 (&op2, old, new, flags);
if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2))
return true;
if (op_mode == VOIDmode)
@@ -298,7 +327,7 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
if (code == SUBREG)
{
op0 = XEXP (x, 0);
- valid_ops &= propagate_rtx_1 (&op0, old, new, can_appear);
+ valid_ops &= propagate_rtx_1 (&op0, old, new, flags);
if (op0 == XEXP (x, 0))
return true;
tem = simplify_gen_subreg (mode, op0, GET_MODE (SUBREG_REG (x)),
@@ -317,7 +346,8 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
return true;
op0 = new_op0 = targetm.delegitimize_address (op0);
- valid_ops &= propagate_rtx_1 (&new_op0, old, new, true);
+ valid_ops &= propagate_rtx_1 (&new_op0, old, new,
+ flags | PR_CAN_APPEAR);
/* Dismiss transformation that we do not want to carry on. */
if (!valid_ops
@@ -344,8 +374,8 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
/* The only simplification we do attempts to remove references to op0
or make it constant -- in both cases, op0's invalidity will not
make the result invalid. */
- propagate_rtx_1 (&op0, old, new, true);
- valid_ops &= propagate_rtx_1 (&op1, old, new, can_appear);
+ propagate_rtx_1 (&op0, old, new, flags | PR_CAN_APPEAR);
+ valid_ops &= propagate_rtx_1 (&op1, old, new, flags);
if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
return true;
@@ -387,6 +417,18 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
return valid_ops || can_appear || CONSTANT_P (tem);
}
+
+/* for_each_rtx traversal function that returns 1 if BODY points to
+ a non-constant mem. */
+
+static int
+varying_mem_p (rtx *body, void *data ATTRIBUTE_UNUSED)
+{
+ rtx x = *body;
+ return MEM_P (x) && !MEM_READONLY_P (x);
+}
+
+
/* Replace all occurrences of OLD in X with NEW and try to simplify the
resulting expression (in mode MODE). Return a new expression if it is
a constant, otherwise X.
@@ -400,14 +442,19 @@ propagate_rtx (rtx x, enum machine_mode mode, rtx old, rtx new)
{
rtx tem;
bool collapsed;
+ int flags;
if (REG_P (new) && REGNO (new) < FIRST_PSEUDO_REGISTER)
return NULL_RTX;
- new = copy_rtx (new);
+ flags = 0;
+ if (REG_P (new) || CONSTANT_P (new))
+ flags |= PR_CAN_APPEAR;
+ if (!for_each_rtx (&new, varying_mem_p, NULL))
+ flags |= PR_HANDLE_MEM;
tem = x;
- collapsed = propagate_rtx_1 (&tem, old, new, REG_P (new) || CONSTANT_P (new));
+ collapsed = propagate_rtx_1 (&tem, old, copy_rtx (new), flags);
if (tem == x || !collapsed)
return NULL_RTX;
@@ -521,16 +568,6 @@ use_killed_between (struct df_ref *use, rtx def_insn, rtx target_insn)
}
-/* for_each_rtx traversal function that returns 1 if BODY points to
- a non-constant mem. */
-
-static int
-varying_mem_p (rtx *body, void *data ATTRIBUTE_UNUSED)
-{
- rtx x = *body;
- return MEM_P (x) && !MEM_READONLY_P (x);
-}
-
/* Check if all uses in DEF_INSN can be used in TARGET_INSN. This
would require full computation of available expressions;
we check only restricted conditions, see use_killed_between. */
@@ -582,9 +619,7 @@ all_uses_available_at (rtx def_insn, rtx target_insn)
}
}
- /* We don't do any analysis of memories or aliasing. Reject any
- instruction that involves references to non-constant memory. */
- return !for_each_rtx (&SET_SRC (def_set), varying_mem_p, NULL);
+ return true;
}
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 0480e1222c2..3af5017d327 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -3757,6 +3757,7 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
bsi = bsi_last (load_bb);
gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD);
call = build_call_expr (decl, 2, addr, fold_convert (itype, rhs));
+ call = fold_convert (void_type_node, call);
force_gimple_operand_bsi (&bsi, call, true, NULL_TREE, true, BSI_SAME_STMT);
bsi_remove (&bsi, true);
diff --git a/gcc/reload.c b/gcc/reload.c
index 830a8f383fd..8940fb58251 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -6090,7 +6090,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
doesn't find any, then we may have just converted a
valid address into an invalid one. Check for that
here. */
- if (reloaded != 1
+ if (reloaded == 0
&& !strict_memory_address_p (GET_MODE (tem),
XEXP (tem, 0)))
push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 70e654bd2e6..1f09b724e0d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -11,6 +11,26 @@
* gcc.dg/vmx/1b-06-ansi.c: New test for the pre-define method.
* gcc.dg/vmx/1b-07-ansi.c: Likewise.
+2008-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/36877
+ * gcc.dg/gomp/atomic-11.c: New test.
+
+2008-07-19 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/36366
+ * gfortran.dg/used_types_20.f90: New test.
+
+2008-07-18 Dodji Seketeli <dseketel@redhat.com>
+
+ PR c++/36407
+ * g++.dg/conversion/op5.C: New testcase.
+
+2008-07-18 Paolo Bonzini <bonzini@gnu.org>
+
+ PR rtl-optimization/35281
+ * gcc.target/i386/pr35281.c: New.
+
2008-07-17 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Backport from mainline:
diff --git a/gcc/testsuite/g++.dg/conversion/op5.C b/gcc/testsuite/g++.dg/conversion/op5.C
new file mode 100644
index 00000000000..69ef996d5c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/op5.C
@@ -0,0 +1,20 @@
+// Contributed by Dodji Seketeli <dseketel@redhat.com>
+// Origin: PR c++/36407
+// { dg-do compile }
+
+struct A
+{
+ A (const A&);
+};
+
+struct B
+{
+ operator A&();
+};
+
+void
+foo (const B& b)
+{
+ const A a = b; // { dg-error "conversion from 'const B' to non-scalar type 'const A' requested" }
+}
+
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-11.c b/gcc/testsuite/gcc.dg/gomp/atomic-11.c
new file mode 100644
index 00000000000..397972b3cf2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/atomic-11.c
@@ -0,0 +1,17 @@
+/* PR middle-end/36877 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+/* { dg-options "-fopenmp -march=i386" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+
+int i;
+float f;
+
+void foo (void)
+{
+#pragma omp atomic
+ i++;
+#pragma omp atomic
+ f += 1.0;
+}
+
+/* { dg-final { scan-assembler-not "__sync_(fetch|add|bool|val)" { target i?86-*-* x86_64-*-* powerpc*-*-* ia64-*-* s390*-*-* sparc*-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr35281.c b/gcc/testsuite/gcc.target/i386/pr35281.c
new file mode 100644
index 00000000000..70e93cbeac0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr35281.c
@@ -0,0 +1,19 @@
+/* { dg-options "-O2" } */
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+
+unsigned long long a;
+unsigned int b;
+unsigned short c;
+
+unsigned long long mul32()
+{
+ return a * b;
+}
+
+unsigned long long mul16()
+{
+ return a * c;
+}
+
+/* { dg-final { scan-assembler-not "xor" } } */
diff --git a/gcc/testsuite/gfortran.dg/used_types_20.f90 b/gcc/testsuite/gfortran.dg/used_types_20.f90
new file mode 100644
index 00000000000..c08235c67f2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/used_types_20.f90
@@ -0,0 +1,49 @@
+! { dg-do compile }
+! Tests the fix for PR36366 a regression in which the order of USE statements
+! in 'test2' would cause the result of 'test1' not to have a reference to
+! the derived type 'inner'.
+!
+! Contributed by Jakub Jelinek <jakub@gcc.gnu.org>
+!
+MODULE types
+ IMPLICIT NONE
+ TYPE :: inner
+ INTEGER, POINTER :: i(:)
+ END TYPE inner
+
+ TYPE :: outer
+ TYPE(inner), POINTER :: inr(:)
+ END TYPE outer
+END MODULE types
+
+MODULE mymod
+ IMPLICIT NONE
+CONTAINS
+ FUNCTION test1()
+ USE types
+ IMPLICIT NONE
+ TYPE(outer), POINTER :: test1
+ NULLIFY(test1)
+ END FUNCTION test1
+END MODULE mymod
+
+MODULE test
+ IMPLICIT NONE
+CONTAINS
+
+ SUBROUTINE test2(a)
+ USE mymod
+ USE types
+ IMPLICIT NONE
+ TYPE(outer), INTENT(INOUT) :: a
+ INTEGER :: i
+ i = a%inr(1)%i(1)
+ END SUBROUTINE test2
+
+ SUBROUTINE test3(a)
+ USE types
+ IMPLICIT NONE
+ TYPE(outer), INTENT(IN) :: a
+ END SUBROUTINE test3
+END MODULE test
+! { dg-final { cleanup-modules "types mymod test" } }