This commit is contained in:
Jakub Jelinek 2009-04-27 12:43:32 +00:00
parent 614bd41946
commit b03a15ac61
14 changed files with 3999 additions and 1705 deletions

View File

@ -1,2 +1,2 @@
fastjar-0.97.tar.gz
gcc-4.4.0-20090424.tar.bz2
gcc-4.4.0-20090427.tar.bz2

View File

@ -1,9 +1,9 @@
%define DATE 20090424
%define SVNREV 146674
%define DATE 20090427
%define SVNREV 146836
%define gcc_version 4.4.0
# Note, gcc_release must be integer, if you want to add suffixes to
# %{release}, append them after %{gcc_release} on Release: line.
%define gcc_release 2
%define gcc_release 3
%define _unpackaged_files_terminate_build 0
%define multilib_64_archs sparc64 ppc64 s390x x86_64
%define include_gappletviewer 1
@ -147,15 +147,12 @@ Patch20: gcc44-libtool-no-rpath.patch
Patch21: gcc44-cloog-dl.patch
Patch22: gcc44-raw-string.patch
Patch24: gcc44-atom.patch
Patch26: gcc44-power7.patch
Patch25: gcc44-power7.patch
Patch26: gcc44-power7-2.patch
Patch27: gcc44-power7-3.patch
Patch28: gcc44-pr38757.patch
Patch30: gcc44-pr39543.patch
Patch31: gcc44-pr39794.patch
Patch32: gcc44-rh459374-1.patch
Patch33: gcc44-rh459374-2.patch
Patch34: gcc44-rh459374-3.patch
Patch35: gcc44-cswtch.patch
Patch36: gcc44-pr39867.patch
Patch29: gcc44-pr39856.patch
Patch30: gcc44-pr39903.patch
Patch1000: fastjar-0.97-segfault.patch
@ -441,15 +438,12 @@ which are required to compile with the GNAT.
%endif
%patch22 -p0 -b .raw-string~
%patch24 -p0 -b .atom~
%patch26 -p0 -b .power7~
%patch25 -p0 -b .power7~
%patch26 -p0 -b .power7-2~
%patch27 -p0 -b .power7-3~
%patch28 -p0 -b .pr38757~
%patch30 -p0 -b .pr39543~
%patch31 -p0 -b .pr39794~
%patch32 -p0 -b .rh459374-1~
%patch33 -p0 -b .rh459374-2~
%patch34 -p0 -b .rh459374-3~
%patch35 -p0 -b .cswtch~
%patch36 -p0 -b .pr39867~
%patch29 -p0 -b .pr39856~
%patch30 -p0 -b .pr39903~
# This testcase doesn't compile.
rm libjava/testsuite/libjava.lang/PR35020*
@ -1760,6 +1754,16 @@ fi
%doc rpm.doc/changelogs/libmudflap/ChangeLog*
%changelog
* Mon Apr 27 2009 Jakub Jelinek <jakub@redhat.com> 4.4.0-3
- update from gcc-4_4-branch
- PR bootstrap/39739
- fix -Wunused-value (#497545, PR c/39889)
- backport further power7-meissner branch changes (#497816)
- fix reg-stack ICE on SPEC2k6 453.povray with -m32 -O3 -msse3
(PR target/39856)
- fix x86_64 ICE on passing structure with flexible array member
(PR target/39903)
* Fri Apr 24 2009 Jakub Jelinek <jakub@redhat.com> 4.4.0-2
- update from gcc-4_4-branch
- PR c++/38228
@ -1818,7 +1822,7 @@ fi
tree-optimization/39557
- emit debuginfo for block local externs in C (PR debug/39563)
- fix -maltivec conditional vector macro (PR target/39558)
- teach fwprop to handle asm (PR rtl-optimization/39543)
- teach fwprop to handle asm (PR inline-asm/39543)
* Tue Mar 24 2009 Jakub Jelinek <jakub@redhat.com> 4.4.0-0.29
- update from trunk

View File

@ -1,129 +0,0 @@
2009-04-21 Martin Jambor <mjambor@suse.cz>
* tree-switch-conversion.c (constructor_contains_same_values_p):
New function.
(build_one_array): Create assigns of constants if possible.
* gcc.dg/tree-ssa/cswtch-2.c: New test.
--- gcc/tree-switch-conversion.c.jj 2009-03-28 18:11:43.000000000 +0100
+++ gcc/tree-switch-conversion.c 2009-04-22 20:09:45.000000000 +0200
@@ -459,6 +459,28 @@ build_constructors (gimple swtch)
}
}
+/* If all values in the constructor vector are the same, return the value.
+ Otherwise return NULL_TREE. Not supposed to be called for empty
+ vectors. */
+
+static tree
+constructor_contains_same_values_p (VEC (constructor_elt, gc) *vec)
+{
+ int i, len = VEC_length (constructor_elt, vec);
+ tree prev = NULL_TREE;
+
+ for (i = 0; i < len; i++)
+ {
+ constructor_elt *elt = VEC_index (constructor_elt, vec, i);
+
+ if (!prev)
+ prev = elt->value;
+ else if (!operand_equal_p (elt->value, prev, OEP_ONLY_CONST))
+ return NULL_TREE;
+ }
+ return prev;
+}
+
/* Create an appropriate array type and declaration and assemble a static array
variable. Also create a load statement that initializes the variable in
question with a value from the static array. SWTCH is the switch statement
@@ -472,35 +494,44 @@ static void
build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi,
tree tidx)
{
- tree array_type, ctor, decl, value_type, name, fetch;
+ tree name, cst;
gimple load;
gimple_stmt_iterator gsi;
gcc_assert (info.default_values[num]);
- value_type = TREE_TYPE (info.default_values[num]);
- array_type = build_array_type (value_type, arr_index_type);
-
- ctor = build_constructor (array_type, info.constructors[num]);
- TREE_CONSTANT (ctor) = true;
-
- decl = build_decl (VAR_DECL, NULL_TREE, array_type);
- TREE_STATIC (decl) = 1;
- DECL_INITIAL (decl) = ctor;
-
- DECL_NAME (decl) = create_tmp_var_name ("CSWTCH");
- DECL_ARTIFICIAL (decl) = 1;
- TREE_CONSTANT (decl) = 1;
- add_referenced_var (decl);
- varpool_mark_needed_node (varpool_node (decl));
- varpool_finalize_decl (decl);
- mark_sym_for_renaming (decl);
name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL);
info.target_inbound_names[num] = name;
- fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE,
- NULL_TREE);
- load = gimple_build_assign (name, fetch);
+ cst = constructor_contains_same_values_p (info.constructors[num]);
+ if (cst)
+ load = gimple_build_assign (name, cst);
+ else
+ {
+ tree array_type, ctor, decl, value_type, fetch;
+
+ value_type = TREE_TYPE (info.default_values[num]);
+ array_type = build_array_type (value_type, arr_index_type);
+
+ ctor = build_constructor (array_type, info.constructors[num]);
+ TREE_CONSTANT (ctor) = true;
+
+ decl = build_decl (VAR_DECL, NULL_TREE, array_type);
+ TREE_STATIC (decl) = 1;
+ DECL_INITIAL (decl) = ctor;
+
+ DECL_NAME (decl) = create_tmp_var_name ("CSWTCH");
+ DECL_ARTIFICIAL (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
+ add_referenced_var (decl);
+ varpool_mark_needed_node (varpool_node (decl));
+ varpool_finalize_decl (decl);
+ mark_sym_for_renaming (decl);
+
+ fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE,
+ NULL_TREE);
+ load = gimple_build_assign (name, fetch);
+ }
SSA_NAME_DEF_STMT (name) = load;
gsi = gsi_for_stmt (swtch);
--- gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c.jj 2009-04-22 20:01:40.000000000 +0200
+++ gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c 2009-04-22 20:01:40.000000000 +0200
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-switchconv" } */
+
+typedef enum { a = 5, b = 6, c = 7, d = 8, e = 9 } X;
+
+int h1 (X x)
+{
+ switch (x) {
+ case a:
+ case b:
+ case c:
+ case d:
+ case e:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "CSWTCH" 0 "switchconv" } } */
+/* { dg-final { cleanup-tree-dump "switchconv" } } */

328
gcc44-power7-2.patch Normal file
View File

@ -0,0 +1,328 @@
2009-04-14 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (rs6000_secondary_reload_inner): Handle
more possible combinations of addresses.
* config/rs6000/vector.md (vec_reload_and_plus_<mptrsize>): Allow
register+small constant in addition to register+register, and
restrict the insn to only match during reload and afterwards.
(vec_reload_and_reg_<mptrsize>): Allow for and of register
indirect to not generate insn not found message.
PR testsuite/39769
* gcc.dg/vmx/3a-04.c (test): Don't rely on floating point equality
for testing the results of estimate instructions.
* gcc.dg/vmx/3a-04m.c (test): Ditto.
* gcc.dg/vmx/3a-05.c (test): Ditto.
--- gcc/testsuite/gcc.dg/vmx/3a-05.c (revision 146069)
+++ gcc/testsuite/gcc.dg/vmx/3a-05.c (revision 146118)
@@ -14,9 +14,13 @@ f(vector float a, vector float b, vector
static void test()
{
- check(vec_all_eq(f(((vector float){2,3,5,7}),
+ check(vec_all_gt(f(((vector float){2,3,5,7}),
((vector float){11,13,17,19}),
((vector float){23,29,31,37})),
- ((vector float){16.9092026, 18.7693329, -2.8233242, -92.9472198})),
- "f");
+ ((vector float){16.90, 18.76, -2.83, -92.95}))
+ && vec_all_lt(f(((vector float){2,3,5,7}),
+ ((vector float){11,13,17,19}),
+ ((vector float){23,29,31,37})),
+ ((vector float){16.91, 18.77, -2.82, -92.94})),
+ "f");
}
--- gcc/testsuite/gcc.dg/vmx/3a-04m.c (revision 146069)
+++ gcc/testsuite/gcc.dg/vmx/3a-04m.c (revision 146118)
@@ -10,9 +10,13 @@ f(vector float a, vector float b, vector
static void test()
{
- check(vec_all_eq(f(((vector float){2,3,5,7}),
+ check(vec_all_gt(f(((vector float){2,3,5,7}),
((vector float){11,13,17,19}),
((vector float){23,29,31,37})),
- ((vector float){23.1818085, 29.2307587, 32.2940826, 128.368393})),
+ ((vector float){23.18, 29.23, 32.29, 128.36}))
+ && vec_all_lt(f(((vector float){2,3,5,7}),
+ ((vector float){11,13,17,19}),
+ ((vector float){23,29,31,37})),
+ ((vector float){23.19, 29.24, 32.30, 128.37})),
"f");
}
--- gcc/testsuite/gcc.dg/vmx/3a-04.c (revision 146069)
+++ gcc/testsuite/gcc.dg/vmx/3a-04.c (revision 146118)
@@ -10,9 +10,13 @@ f(vector float a, vector float b, vector
static void test()
{
- check(vec_all_eq(f(((vector float){2,3,5,7}),
+ check(vec_all_gt(f(((vector float){2,3,5,7}),
((vector float){11,13,17,19}),
((vector float){23,29,31,37})),
- ((vector float){23.1818085, 29.2307587, 32.2940826, 128.368393})),
+ ((vector float){23.18, 29.23, 32.29, 128.36}))
+ && vec_all_lt(f(((vector float){2,3,5,7}),
+ ((vector float){11,13,17,19}),
+ ((vector float){23,29,31,37})),
+ ((vector float){23.19, 29.24, 32.30, 128.37})),
"f");
}
--- gcc/config/rs6000/vector.md (revision 146069)
+++ gcc/config/rs6000/vector.md (revision 146118)
@@ -129,14 +129,15 @@ (define_expand "reload_<VEC_R:mode>_<P:m
})
;; Reload sometimes tries to move the address to a GPR, and can generate
-;; invalid RTL for addresses involving AND -16.
+;; invalid RTL for addresses involving AND -16. Allow addresses involving
+;; reg+reg, reg+small constant, or just reg, all wrapped in an AND -16.
(define_insn_and_split "*vec_reload_and_plus_<mptrsize>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
- (match_operand:P 2 "gpc_reg_operand" "r"))
+ (match_operand:P 2 "reg_or_cint_operand" "rI"))
(const_int -16)))]
- "TARGET_ALTIVEC || TARGET_VSX"
+ "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
"#"
"&& reload_completed"
[(set (match_dup 0)
@@ -146,6 +147,21 @@ (define_insn_and_split "*vec_reload_and_
(and:P (match_dup 0)
(const_int -16)))
(clobber:CC (scratch:CC))])])
+
+;; The normal ANDSI3/ANDDI3 won't match if reload decides to move an AND -16
+;; address to a register because there is no clobber of a (scratch), so we add
+;; it here.
+(define_insn_and_split "*vec_reload_and_reg_<mptrsize>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+ (and:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (const_int -16)))]
+ "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 0)
+ (and:P (match_dup 1)
+ (const_int -16)))
+ (clobber:CC (scratch:CC))])])
;; Generic floating point vector arithmetic support
(define_expand "add<mode>3"
--- gcc/config/rs6000/rs6000.c (revision 146069)
+++ gcc/config/rs6000/rs6000.c (revision 146118)
@@ -12574,6 +12574,11 @@ rs6000_secondary_reload_inner (rtx reg,
enum reg_class rclass;
rtx addr;
rtx and_op2 = NULL_RTX;
+ rtx addr_op1;
+ rtx addr_op2;
+ rtx scratch_or_premodify = scratch;
+ rtx and_rtx;
+ rtx cc_clobber;
if (TARGET_DEBUG_ADDR)
{
@@ -12595,7 +12600,8 @@ rs6000_secondary_reload_inner (rtx reg,
switch (rclass)
{
- /* Move reg+reg addresses into a scratch register for GPRs. */
+ /* GPRs can handle reg + small constant, all other addresses need to use
+ the scratch register. */
case GENERAL_REGS:
case BASE_REGS:
if (GET_CODE (addr) == AND)
@@ -12603,70 +12609,152 @@ rs6000_secondary_reload_inner (rtx reg,
and_op2 = XEXP (addr, 1);
addr = XEXP (addr, 0);
}
+
+ if (GET_CODE (addr) == PRE_MODIFY)
+ {
+ scratch_or_premodify = XEXP (addr, 0);
+ gcc_assert (REG_P (scratch_or_premodify));
+ gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
+ addr = XEXP (addr, 1);
+ }
+
if (GET_CODE (addr) == PLUS
&& (!rs6000_legitimate_offset_address_p (TImode, addr, true)
|| and_op2 != NULL_RTX))
{
- if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
- || GET_CODE (addr) == CONST_INT)
- rs6000_emit_move (scratch, addr, GET_MODE (addr));
- else
- emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
- addr = scratch;
+ addr_op1 = XEXP (addr, 0);
+ addr_op2 = XEXP (addr, 1);
+ gcc_assert (legitimate_indirect_address_p (addr_op1, true));
+
+ if (!REG_P (addr_op2)
+ && (GET_CODE (addr_op2) != CONST_INT
+ || !satisfies_constraint_I (addr_op2)))
+ {
+ rs6000_emit_move (scratch, addr_op2, Pmode);
+ addr_op2 = scratch;
+ }
+
+ emit_insn (gen_rtx_SET (VOIDmode,
+ scratch_or_premodify,
+ gen_rtx_PLUS (Pmode,
+ addr_op1,
+ addr_op2)));
+
+ addr = scratch_or_premodify;
+ scratch_or_premodify = scratch;
}
- else if (GET_CODE (addr) == PRE_MODIFY
- && REG_P (XEXP (addr, 0))
- && GET_CODE (XEXP (addr, 1)) == PLUS)
+ else if (!legitimate_indirect_address_p (addr, true)
+ && !rs6000_legitimate_offset_address_p (TImode, addr, true))
{
- emit_insn (gen_rtx_SET (VOIDmode, XEXP (addr, 0), XEXP (addr, 1)));
- addr = XEXP (addr, 0);
+ rs6000_emit_move (scratch_or_premodify, addr, Pmode);
+ addr = scratch_or_premodify;
+ scratch_or_premodify = scratch;
}
break;
+ /* Float/Altivec registers can only handle reg+reg addressing. Move
+ other addresses into a scratch register. */
+ case FLOAT_REGS:
+ case VSX_REGS:
+ case ALTIVEC_REGS:
+
/* With float regs, we need to handle the AND ourselves, since we can't
use the Altivec instruction with an implicit AND -16. Allow scalar
loads to float registers to use reg+offset even if VSX. */
- case FLOAT_REGS:
- case VSX_REGS:
- if (GET_CODE (addr) == AND)
+ if (GET_CODE (addr) == AND
+ && (rclass != ALTIVEC_REGS || GET_MODE_SIZE (mode) != 16))
{
and_op2 = XEXP (addr, 1);
addr = XEXP (addr, 0);
}
- /* fall through */
- /* Move reg+offset addresses into a scratch register. */
- case ALTIVEC_REGS:
- if (!legitimate_indirect_address_p (addr, true)
- && !legitimate_indexed_address_p (addr, true)
- && (GET_CODE (addr) != PRE_MODIFY
- || !legitimate_indexed_address_p (XEXP (addr, 1), true))
- && (rclass != FLOAT_REGS
- || GET_MODE_SIZE (mode) != 8
+ /* If we aren't using a VSX load, save the PRE_MODIFY register and use it
+ as the address later. */
+ if (GET_CODE (addr) == PRE_MODIFY
+ && (!VECTOR_MEM_VSX_P (mode)
|| and_op2 != NULL_RTX
- || !rs6000_legitimate_offset_address_p (mode, addr, true)))
+ || !legitimate_indexed_address_p (XEXP (addr, 1), true)))
{
- if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
- || GET_CODE (addr) == CONST_INT)
- rs6000_emit_move (scratch, addr, GET_MODE (addr));
- else
- emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
- addr = scratch;
+ scratch_or_premodify = XEXP (addr, 0);
+ gcc_assert (legitimate_indirect_address_p (scratch_or_premodify,
+ true));
+ gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
+ addr = XEXP (addr, 1);
+ }
+
+ if (legitimate_indirect_address_p (addr, true) /* reg */
+ || legitimate_indexed_address_p (addr, true) /* reg+reg */
+ || GET_CODE (addr) == PRE_MODIFY /* VSX pre-modify */
+ || GET_CODE (addr) == AND /* Altivec memory */
+ || (rclass == FLOAT_REGS /* legacy float mem */
+ && GET_MODE_SIZE (mode) == 8
+ && and_op2 == NULL_RTX
+ && scratch_or_premodify == scratch
+ && rs6000_legitimate_offset_address_p (mode, addr, true)))
+ ;
+
+ else if (GET_CODE (addr) == PLUS)
+ {
+ addr_op1 = XEXP (addr, 0);
+ addr_op2 = XEXP (addr, 1);
+ gcc_assert (REG_P (addr_op1));
+
+ rs6000_emit_move (scratch, addr_op2, Pmode);
+ emit_insn (gen_rtx_SET (VOIDmode,
+ scratch_or_premodify,
+ gen_rtx_PLUS (Pmode,
+ addr_op1,
+ scratch)));
+ addr = scratch_or_premodify;
+ scratch_or_premodify = scratch;
}
+
+ else if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
+ || GET_CODE (addr) == CONST_INT)
+ {
+ rs6000_emit_move (scratch_or_premodify, addr, Pmode);
+ addr = scratch_or_premodify;
+ scratch_or_premodify = scratch;
+ }
+
+ else
+ gcc_unreachable ();
+
break;
default:
gcc_unreachable ();
}
- /* If the original address involved an AND -16 that is part of the Altivec
- addresses, recreate the and now. */
+ /* If the original address involved a pre-modify that we couldn't use the VSX
+ memory instruction with update, and we haven't taken care of already,
+ store the address in the pre-modify register and use that as the
+ address. */
+ if (scratch_or_premodify != scratch && scratch_or_premodify != addr)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, scratch_or_premodify, addr));
+ addr = scratch_or_premodify;
+ }
+
+ /* If the original address involved an AND -16 and we couldn't use an ALTIVEC
+ memory instruction, recreate the AND now, including the clobber which is
+ generated by the general ANDSI3/ANDDI3 patterns for the
+ andi. instruction. */
if (and_op2 != NULL_RTX)
{
- rtx and_rtx = gen_rtx_SET (VOIDmode,
- scratch,
- gen_rtx_AND (Pmode, addr, and_op2));
- rtx cc_clobber = gen_rtx_CLOBBER (CCmode, gen_rtx_SCRATCH (CCmode));
+ if (! legitimate_indirect_address_p (addr, true))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
+ addr = scratch;
+ }
+
+ and_rtx = gen_rtx_SET (VOIDmode,
+ scratch,
+ gen_rtx_AND (Pmode,
+ addr,
+ and_op2));
+
+ cc_clobber = gen_rtx_CLOBBER (CCmode, gen_rtx_SCRATCH (CCmode));
emit_insn (gen_rtx_PARALLEL (VOIDmode,
gen_rtvec (2, and_rtx, cc_clobber)));
addr = scratch;

3523
gcc44-power7-3.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,293 +0,0 @@
2009-04-22 Jakub Jelinek <jakub@redhat.com>
PR inline-asm/39543
* fwprop.c (forward_propagate_asm): New function.
(forward_propagate_and_simplify): Propagate also into __asm, if it
doesn't increase the number of referenced registers.
* gcc.target/i386/pr39543-1.c: New test.
* gcc.target/i386/pr39543-2.c: New test.
* gcc.target/i386/pr39543-3.c: New test.
--- gcc/fwprop.c.jj 2009-03-30 12:45:45.000000000 +0200
+++ gcc/fwprop.c 2009-04-10 16:19:36.000000000 +0200
@@ -1,5 +1,5 @@
/* RTL-based forward propagation pass for GNU compiler.
- Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Paolo Bonzini and Steven Bosscher.
This file is part of GCC.
@@ -852,6 +852,80 @@ forward_propagate_subreg (df_ref use, rt
return false;
}
+/* Try to replace USE with SRC (defined in DEF_INSN) in __asm. */
+
+static bool
+forward_propagate_asm (df_ref use, rtx def_insn, rtx def_set, rtx reg)
+{
+ rtx use_insn = DF_REF_INSN (use), src, use_pat, asm_operands, new_rtx, *loc;
+ int speed_p, i;
+ df_ref *use_vec;
+
+ gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0);
+
+ src = SET_SRC (def_set);
+ use_pat = PATTERN (use_insn);
+
+ /* In __asm don't replace if src might need more registers than
+ reg, as that could increase register pressure on the __asm. */
+ use_vec = DF_INSN_USES (def_insn);
+ if (use_vec[0] && use_vec[1])
+ return false;
+
+ speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
+ asm_operands = NULL_RTX;
+ switch (GET_CODE (use_pat))
+ {
+ case ASM_OPERANDS:
+ asm_operands = use_pat;
+ break;
+ case SET:
+ if (MEM_P (SET_DEST (use_pat)))
+ {
+ loc = &SET_DEST (use_pat);
+ new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p);
+ if (new_rtx)
+ validate_unshare_change (use_insn, loc, new_rtx, true);
+ }
+ asm_operands = SET_SRC (use_pat);
+ break;
+ case PARALLEL:
+ for (i = 0; i < XVECLEN (use_pat, 0); i++)
+ if (GET_CODE (XVECEXP (use_pat, 0, i)) == SET)
+ {
+ if (MEM_P (SET_DEST (XVECEXP (use_pat, 0, i))))
+ {
+ loc = &SET_DEST (XVECEXP (use_pat, 0, i));
+ new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg,
+ src, speed_p);
+ if (new_rtx)
+ validate_unshare_change (use_insn, loc, new_rtx, true);
+ }
+ asm_operands = SET_SRC (XVECEXP (use_pat, 0, i));
+ }
+ else if (GET_CODE (XVECEXP (use_pat, 0, i)) == ASM_OPERANDS)
+ asm_operands = XVECEXP (use_pat, 0, i);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ gcc_assert (asm_operands && GET_CODE (asm_operands) == ASM_OPERANDS);
+ for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (asm_operands); i++)
+ {
+ loc = &ASM_OPERANDS_INPUT (asm_operands, i);
+ new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p);
+ if (new_rtx)
+ validate_unshare_change (use_insn, loc, new_rtx, true);
+ }
+
+ if (num_changes_pending () == 0 || !apply_change_group ())
+ return false;
+
+ num_changes++;
+ return true;
+}
+
/* Try to replace USE with SRC (defined in DEF_INSN) and simplify the
result. */
@@ -863,12 +937,16 @@ forward_propagate_and_simplify (df_ref u
rtx src, reg, new_rtx, *loc;
bool set_reg_equal;
enum machine_mode mode;
+ int asm_use = -1;
+
+ if (INSN_CODE (use_insn) < 0)
+ asm_use = asm_noperands (PATTERN (use_insn));
- if (!use_set)
+ if (!use_set && asm_use < 0)
return false;
/* Do not propagate into PC, CC0, etc. */
- if (GET_MODE (SET_DEST (use_set)) == VOIDmode)
+ if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode)
return false;
/* If def and use are subreg, check if they match. */
@@ -900,7 +978,7 @@ forward_propagate_and_simplify (df_ref u
if (MEM_P (src) && MEM_READONLY_P (src))
{
rtx x = avoid_constant_pool_reference (src);
- if (x != src)
+ if (x != src && use_set)
{
rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (use_set);
@@ -911,6 +989,9 @@ forward_propagate_and_simplify (df_ref u
return false;
}
+ if (asm_use >= 0)
+ return forward_propagate_asm (use, def_insn, def_set, reg);
+
/* Else try simplifying. */
if (DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE)
--- gcc/testsuite/gcc.target/i386/pr39543-1.c.jj 2009-04-09 09:47:16.000000000 +0200
+++ gcc/testsuite/gcc.target/i386/pr39543-1.c 2009-04-09 09:47:16.000000000 +0200
@@ -0,0 +1,52 @@
+/* PR inline-asm/39543 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -fomit-frame-pointer" } */
+
+float __attribute__ ((aligned (16))) s0[128];
+const float s1 = 0.707;
+float s2[8] __attribute__ ((aligned (16)));
+float s3[8] __attribute__ ((aligned (16)));
+float s4[16] __attribute__ ((aligned (16)));
+float s5[16] __attribute__ ((aligned (16)));
+
+void
+foo (int k, float *x, float *y, const float *d, const float *z)
+{
+ float *a, *b, *c, *e;
+
+ a = x + 2 * k;
+ b = a + 2 * k;
+ c = b + 2 * k;
+ e = y + 2 * k;
+ __asm__ volatile (""
+ : "=m" (x[0]), "=m" (b[0]), "=m" (a[0]), "=m" (c[0])
+ : "m" (y[0]), "m" (y[k * 2]), "m" (x[0]), "m" (a[0])
+ : "memory");
+ for (;;)
+ {
+ __asm__ volatile (""
+ :
+ : "m" (y[2]), "m" (d[2]), "m" (e[2]), "m" (z[2])
+ : "memory");
+ if (!--k)
+ break;
+ }
+ __asm__ volatile (""
+ : "=m" (x[2]), "=m" (x[10]), "=m" (x[6]), "=m" (x[14])
+ : "m" (y[2]), "m" (y[6]), "m" (x[2]), "m" (x[6]),
+ "m" (y[18]), "m" (s1)
+ : "memory");
+}
+
+void
+bar (float *a)
+{
+ foo (4, a, a + 16, s2, s3);
+ foo (8, a, a + 32, s4, s5);
+}
+
+void
+baz (void)
+{
+ bar (s0);
+}
--- gcc/testsuite/gcc.target/i386/pr39543-2.c.jj 2009-04-09 09:47:16.000000000 +0200
+++ gcc/testsuite/gcc.target/i386/pr39543-2.c 2009-04-09 09:47:16.000000000 +0200
@@ -0,0 +1,51 @@
+/* PR inline-asm/39543 */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+float __attribute__ ((aligned (16))) s0[128];
+const float s1 = 0.707;
+float s2[8] __attribute__ ((aligned (16)));
+float s3[8] __attribute__ ((aligned (16)));
+float s4[16] __attribute__ ((aligned (16)));
+float s5[16] __attribute__ ((aligned (16)));
+
+void
+foo (int k, float *x, float *y, const float *d, const float *z)
+{
+ float *a, *b, *c, *e;
+
+ a = x + 2 * k;
+ b = a + 2 * k;
+ c = b + 2 * k;
+ e = y + 2 * k;
+ __asm__ volatile (""
+ : "=m" (x[0]), "=m" (b[0]), "=m" (a[0]), "=m" (c[0])
+ : "m" (y[0]), "m" (y[k * 2]), "m" (x[0]), "m" (a[0])
+ : "memory");
+ for (;;)
+ {
+ __asm__ volatile (""
+ :
+ : "m" (y[2]), "m" (d[2]), "m" (e[2]), "m" (z[2])
+ : "memory");
+ if (!--k)
+ break;
+ }
+ __asm__ volatile (""
+ : "=m" (x[2]), "=m" (x[10]), "=m" (x[6]), "=m" (x[14])
+ : "m" (y[2]), "m" (y[6]), "m" (x[2]), "m" (x[6]), "m" (s1)
+ : "memory");
+}
+
+void
+bar (float *a)
+{
+ foo (4, a, a + 16, s2, s3);
+ foo (8, a, a + 32, s4, s5);
+}
+
+void
+baz (void)
+{
+ bar (s0);
+}
--- gcc/testsuite/gcc.target/i386/pr39543-3.c.jj 2009-04-09 09:47:16.000000000 +0200
+++ gcc/testsuite/gcc.target/i386/pr39543-3.c 2009-04-09 09:47:16.000000000 +0200
@@ -0,0 +1,42 @@
+/* PR inline-asm/39543 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int s[128];
+
+void
+f1 (void)
+{
+ int i;
+ asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17"
+ : "=r" (i)
+ : "m" (s[0]), "m" (s[2]), "m" (s[4]), "m" (s[6]), "m" (s[8]),
+ "m" (s[10]), "m" (s[12]), "m" (s[14]), "m" (s[16]), "m" (s[18]),
+ "m" (s[20]), "m" (s[22]), "m" (s[24]), "m" (s[26]), "m" (s[28]),
+ "m" (s[30]), "m" (s[32]));
+ asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17"
+ : "=r" (i)
+ : "m" (s[0]), "m" (s[2]), "m" (s[4]), "m" (s[6]), "m" (s[8]),
+ "m" (s[10]), "m" (s[12]), "m" (s[14]), "m" (s[16]), "m" (s[18]),
+ "m" (s[20]), "m" (s[22]), "m" (s[24]), "m" (s[26]), "m" (s[28]),
+ "m" (s[30]), "m" (s[32]));
+}
+
+void
+f2 (int *q)
+{
+ int i;
+ int *p = q + 32;
+ asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17"
+ : "=r" (i)
+ : "m" (p[0]), "m" (p[2]), "m" (p[4]), "m" (p[6]), "m" (p[8]),
+ "m" (p[10]), "m" (p[12]), "m" (p[14]), "m" (p[16]), "m" (p[18]),
+ "m" (p[20]), "m" (p[22]), "m" (p[24]), "m" (p[26]), "m" (p[28]),
+ "m" (p[30]), "m" (p[32]));
+ asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17"
+ : "=r" (i)
+ : "m" (p[0]), "m" (p[2]), "m" (p[4]), "m" (p[6]), "m" (p[8]),
+ "m" (p[10]), "m" (p[12]), "m" (p[14]), "m" (p[16]), "m" (p[18]),
+ "m" (p[20]), "m" (p[22]), "m" (p[24]), "m" (p[26]), "m" (p[28]),
+ "m" (p[30]), "m" (p[32]));
+}

View File

@ -1,309 +0,0 @@
2009-04-24 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/39794
* alias.c (canon_true_dependence): Add x_addr argument.
* rtl.h (canon_true_dependence): Adjust prototype.
* cse.c (check_dependence): Adjust canon_true_dependence callers.
* cselib.c (cselib_invalidate_mem): Likewise.
* gcse.c (compute_transp): Likewise.
* dse.c (scan_reads_nospill): Likewise.
(record_store, check_mem_read_rtx): Likewise. For non-const-or-frame
addresses pass base->val_rtx as mem_addr, for const-or-frame addresses
canon_base_addr of the group, plus optional offset.
(struct group_info): Rename canon_base_mem to
canon_base_addr.
(get_group_info): Set canon_base_addr to canon_rtx of base, not
canon_rtx of base_mem.
* gcc.dg/pr39794.c: New test.
--- gcc/alias.c.jj 2009-04-22 23:54:25.000000000 +0200
+++ gcc/alias.c 2009-04-23 18:09:28.000000000 +0200
@@ -2287,14 +2287,13 @@ true_dependence (const_rtx mem, enum mac
Variant of true_dependence which assumes MEM has already been
canonicalized (hence we no longer do that here).
The mem_addr argument has been added, since true_dependence computed
- this value prior to canonicalizing. */
+ this value prior to canonicalizing.
+ If x_addr is non-NULL, it is used in preference of XEXP (x, 0). */
int
canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
- const_rtx x, bool (*varies) (const_rtx, bool))
+ const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool))
{
- rtx x_addr;
-
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
return 1;
@@ -2320,7 +2319,8 @@ canon_true_dependence (const_rtx mem, en
if (nonoverlapping_memrefs_p (x, mem))
return 0;
- x_addr = get_addr (XEXP (x, 0));
+ if (! x_addr)
+ x_addr = get_addr (XEXP (x, 0));
if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
return 0;
--- gcc/dse.c.jj 2009-04-22 22:20:23.000000000 +0200
+++ gcc/dse.c 2009-04-23 18:20:44.000000000 +0200
@@ -223,7 +223,7 @@ struct store_info
/* This canonized mem. */
rtx mem;
- /* The result of get_addr on mem. */
+ /* Canonized MEM address for use by canon_true_dependence. */
rtx mem_addr;
/* If this is non-zero, it is the alias set of a spill location. */
@@ -476,8 +476,8 @@ struct group_info
do read dependency. */
rtx base_mem;
- /* Canonized version of base_mem, most likely the same thing. */
- rtx canon_base_mem;
+ /* Canonized version of base_mem's address. */
+ rtx canon_base_addr;
/* These two sets of two bitmaps are used to keep track of how many
stores are actually referencing that position from this base. We
@@ -705,7 +705,7 @@ get_group_info (rtx base)
gi->rtx_base = base;
gi->id = rtx_group_next_id++;
gi->base_mem = gen_rtx_MEM (QImode, base);
- gi->canon_base_mem = canon_rtx (gi->base_mem);
+ gi->canon_base_addr = canon_rtx (base);
gi->store1_n = BITMAP_ALLOC (NULL);
gi->store1_p = BITMAP_ALLOC (NULL);
gi->store2_n = BITMAP_ALLOC (NULL);
@@ -1286,7 +1286,7 @@ static rtx get_stored_val (store_info_t,
static int
record_store (rtx body, bb_info_t bb_info)
{
- rtx mem, rhs, const_rhs;
+ rtx mem, rhs, const_rhs, mem_addr;
HOST_WIDE_INT offset = 0;
HOST_WIDE_INT width = 0;
alias_set_type spill_alias_set;
@@ -1456,6 +1456,23 @@ record_store (rtx body, bb_info_t bb_inf
ptr = active_local_stores;
last = NULL;
redundant_reason = NULL;
+ mem = canon_rtx (mem);
+ /* For alias_set != 0 canon_true_dependence should be never called. */
+ if (spill_alias_set)
+ mem_addr = NULL_RTX;
+ else
+ {
+ if (group_id < 0)
+ mem_addr = base->val_rtx;
+ else
+ {
+ group_info_t group
+ = VEC_index (group_info_t, rtx_group_vec, group_id);
+ mem_addr = group->canon_base_addr;
+ }
+ if (offset)
+ mem_addr = plus_constant (mem_addr, offset);
+ }
while (ptr)
{
@@ -1547,13 +1564,13 @@ record_store (rtx body, bb_info_t bb_inf
if (canon_true_dependence (s_info->mem,
GET_MODE (s_info->mem),
s_info->mem_addr,
- mem, rtx_varies_p))
+ mem, mem_addr, rtx_varies_p))
{
s_info->rhs = NULL;
s_info->const_rhs = NULL;
}
}
-
+
/* An insn can be deleted if every position of every one of
its s_infos is zero. */
if (any_positions_needed_p (s_info)
@@ -1580,9 +1597,9 @@ record_store (rtx body, bb_info_t bb_inf
/* Finish filling in the store_info. */
store_info->next = insn_info->store_rec;
insn_info->store_rec = store_info;
- store_info->mem = canon_rtx (mem);
+ store_info->mem = mem;
store_info->alias_set = spill_alias_set;
- store_info->mem_addr = get_addr (XEXP (mem, 0));
+ store_info->mem_addr = mem_addr;
store_info->cse_base = base;
if (width > HOST_BITS_PER_WIDE_INT)
{
@@ -2006,7 +2023,7 @@ replace_read (store_info_t store_info, i
static int
check_mem_read_rtx (rtx *loc, void *data)
{
- rtx mem = *loc;
+ rtx mem = *loc, mem_addr;
bb_info_t bb_info;
insn_info_t insn_info;
HOST_WIDE_INT offset = 0;
@@ -2058,6 +2075,22 @@ check_mem_read_rtx (rtx *loc, void *data
read_info->end = offset + width;
read_info->next = insn_info->read_rec;
insn_info->read_rec = read_info;
+ /* For alias_set != 0 canon_true_dependence should be never called. */
+ if (spill_alias_set)
+ mem_addr = NULL_RTX;
+ else
+ {
+ if (group_id < 0)
+ mem_addr = base->val_rtx;
+ else
+ {
+ group_info_t group
+ = VEC_index (group_info_t, rtx_group_vec, group_id);
+ mem_addr = group->canon_base_addr;
+ }
+ if (offset)
+ mem_addr = plus_constant (mem_addr, offset);
+ }
/* We ignore the clobbers in store_info. The is mildly aggressive,
but there really should not be a clobber followed by a read. */
@@ -2128,7 +2161,7 @@ check_mem_read_rtx (rtx *loc, void *data
= canon_true_dependence (store_info->mem,
GET_MODE (store_info->mem),
store_info->mem_addr,
- mem, rtx_varies_p);
+ mem, mem_addr, rtx_varies_p);
else if (group_id == store_info->group_id)
{
@@ -2139,7 +2172,7 @@ check_mem_read_rtx (rtx *loc, void *data
= canon_true_dependence (store_info->mem,
GET_MODE (store_info->mem),
store_info->mem_addr,
- mem, rtx_varies_p);
+ mem, mem_addr, rtx_varies_p);
/* If this read is just reading back something that we just
stored, rewrite the read. */
@@ -2224,7 +2257,7 @@ check_mem_read_rtx (rtx *loc, void *data
remove = canon_true_dependence (store_info->mem,
GET_MODE (store_info->mem),
store_info->mem_addr,
- mem, rtx_varies_p);
+ mem, mem_addr, rtx_varies_p);
if (remove)
{
@@ -3066,8 +3099,9 @@ scan_reads_nospill (insn_info_t insn_inf
if ((read_info->group_id < 0)
&& canon_true_dependence (group->base_mem,
QImode,
- group->canon_base_mem,
- read_info->mem, rtx_varies_p))
+ group->canon_base_addr,
+ read_info->mem, NULL_RTX,
+ rtx_varies_p))
{
if (kill)
bitmap_ior_into (kill, group->group_kill);
--- gcc/cse.c.jj 2009-04-22 22:20:23.000000000 +0200
+++ gcc/cse.c 2009-04-23 18:09:35.000000000 +0200
@@ -1658,7 +1658,7 @@ check_dependence (rtx *x, void *data)
{
struct check_dependence_data *d = (struct check_dependence_data *) data;
if (*x && MEM_P (*x))
- return canon_true_dependence (d->exp, d->mode, d->addr, *x,
+ return canon_true_dependence (d->exp, d->mode, d->addr, *x, NULL_RTX,
cse_rtx_varies_p);
else
return 0;
--- gcc/rtl.h.jj 2009-04-22 22:20:37.000000000 +0200
+++ gcc/rtl.h 2009-04-23 18:09:35.000000000 +0200
@@ -2290,7 +2290,7 @@ extern rtx canon_rtx (rtx);
extern int true_dependence (const_rtx, enum machine_mode, const_rtx, bool (*)(const_rtx, bool));
extern rtx get_addr (rtx);
extern int canon_true_dependence (const_rtx, enum machine_mode, rtx, const_rtx,
- bool (*)(const_rtx, bool));
+ rtx, bool (*)(const_rtx, bool));
extern int read_dependence (const_rtx, const_rtx);
extern int anti_dependence (const_rtx, const_rtx);
extern int output_dependence (const_rtx, const_rtx);
--- gcc/cselib.c.jj 2009-04-22 22:20:23.000000000 +0200
+++ gcc/cselib.c 2009-04-23 18:09:35.000000000 +0200
@@ -1,6 +1,6 @@
/* Common subexpression elimination library for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
+ 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
@@ -1483,7 +1483,7 @@ cselib_invalidate_mem (rtx mem_rtx)
}
if (num_mems < PARAM_VALUE (PARAM_MAX_CSELIB_MEMORY_LOCATIONS)
&& ! canon_true_dependence (mem_rtx, GET_MODE (mem_rtx), mem_addr,
- x, cselib_rtx_varies_p))
+ x, NULL_RTX, cselib_rtx_varies_p))
{
has_mem = true;
num_mems++;
--- gcc/gcse.c.jj 2009-04-22 22:20:23.000000000 +0200
+++ gcc/gcse.c 2009-04-23 18:09:35.000000000 +0200
@@ -1,7 +1,7 @@
/* Global common subexpression elimination/Partial redundancy elimination
and global constant/copy propagation for GNU compiler.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GCC.
@@ -2512,7 +2512,7 @@ compute_transp (const_rtx x, int indx, s
dest_addr = XEXP (list_entry, 0);
if (canon_true_dependence (dest, GET_MODE (dest), dest_addr,
- x, rtx_addr_varies_p))
+ x, NULL_RTX, rtx_addr_varies_p))
{
if (set_p)
SET_BIT (bmap[bb_index], indx);
--- gcc/testsuite/gcc.dg/pr39794.c.jj 2009-04-23 18:09:35.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr39794.c 2009-04-23 18:21:13.000000000 +0200
@@ -0,0 +1,33 @@
+/* PR rtl-optimization/39794 */
+/* { dg-do run } */
+/* { dg-options "-O2 -funroll-loops" } */
+
+extern void abort ();
+
+void
+foo (int *a, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ a[i] *= 2;
+ a[i + 1] = a[i - 1] + a[i - 2];
+ }
+}
+
+int a[16];
+int ref[16] = { 0, 1, 4, 2, 10, 12, 24, 44,
+ 72, 136, 232, 416, 736, 1296, 2304, 2032 };
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ a[i] = i;
+ foo (a + 2, 16 - 3);
+ for (i = 0; i < 16; i++)
+ if (ref[i] != a[i])
+ abort ();
+ return 0;
+}

43
gcc44-pr39856.patch Normal file
View File

@ -0,0 +1,43 @@
2009-04-24 Vladimir Makarov <vmakarov@redhat.com>
PR target/39856
* reg-stack.c (subst_stack_regs_pat): Remove gcc_assert for note
for clobber.
--- gcc/reg-stack.c (revision 146648)
+++ gcc/reg-stack.c (working copy)
@@ -1371,21 +1371,23 @@ subst_stack_regs_pat (rtx insn, stack re
if (pat != PATTERN (insn))
{
- /* The fix_truncdi_1 pattern wants to be able to allocate
- its own scratch register. It does this by clobbering
- an fp reg so that it is assured of an empty reg-stack
- register. If the register is live, kill it now.
- Remove the DEAD/UNUSED note so we don't try to kill it
- later too. */
+ /* The fix_truncdi_1 pattern wants to be able to
+ allocate its own scratch register. It does this by
+ clobbering an fp reg so that it is assured of an
+ empty reg-stack register. If the register is live,
+ kill it now. Remove the DEAD/UNUSED note so we
+ don't try to kill it later too.
+
+ In reality the UNUSED note can be absent in some
+ complicated cases when the register is reused for
+ partially set variable. */
if (note)
emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE);
else
- {
- note = find_reg_note (insn, REG_UNUSED, *dest);
- gcc_assert (note);
- }
- remove_note (insn, note);
+ note = find_reg_note (insn, REG_UNUSED, *dest);
+ if (note)
+ remove_note (insn, note);
replace_reg (dest, FIRST_STACK_REG + 1);
}
else

View File

@ -1,70 +0,0 @@
2009-04-24 Paolo Bonzini <bonzini@gnu.org>
PR middle-end/39867
* fold-const.c (fold_cond_expr_with_comparison): When folding
> and >= to MAX, make sure the MAX uses the same type as the
comparison's operands.
* gcc.dg/pr39867.c: New.
--- gcc/fold-const.c (revision 146581)
+++ gcc/fold-const.c (working copy)
@@ -5337,31 +5337,34 @@ fold_cond_expr_with_comparison (tree typ
break;
case GT_EXPR:
- /* If C1 is C2 - 1, this is max(A, C2). */
+ /* If C1 is C2 - 1, this is max(A, C2), but use ARG00's type for
+ MAX_EXPR, to preserve the signedness of the comparison. */
if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (MINUS_EXPR, arg2,
build_int_cst (type, 1), 0),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
- type,
- fold_convert (type, arg1),
- arg2));
+ return pedantic_non_lvalue (fold_convert (type,
+ fold_build2 (MAX_EXPR, TREE_TYPE (arg00),
+ arg00,
+ fold_convert (TREE_TYPE (arg00),
+ arg2))));
break;
case GE_EXPR:
- /* If C1 is C2 + 1, this is max(A, C2). */
+ /* If C1 is C2 + 1, this is max(A, C2), with the same care as above. */
if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (PLUS_EXPR, arg2,
build_int_cst (type, 1), 0),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
- type,
- fold_convert (type, arg1),
- arg2));
+ return pedantic_non_lvalue (fold_convert (type,
+ fold_build2 (MAX_EXPR, TREE_TYPE (arg00),
+ arg00,
+ fold_convert (TREE_TYPE (arg00),
+ arg2))));
break;
case NE_EXPR:
break;
--- gcc/testsuite/gcc.dg/pr39867.c 2009-04-21 23:33:56.143009234 +0200
+++ gcc/testsuite/gcc.dg/pr39867.c 2009-04-24 09:20:07.000000000 +0200
@@ -0,0 +1,11 @@
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+int main (void)
+{
+ int exp = -1;
+ /* Wrong folding of the LHS to an unsigned MAX leads to 4294967295 > 2. */
+ if ((exp < 2 ? 2U : (unsigned int) exp) != 2)
+ link_error ();
+ return 0;
+}

79
gcc44-pr39903.patch Normal file
View File

@ -0,0 +1,79 @@
2009-04-26 H.J. Lu <hongjiu.lu@intel.com>
PR target/39903
* config/i386/i386.c (construct_container): Don't call
gen_reg_or_parallel with BLKmode for X86_64_SSE_CLASS,
X86_64_SSESF_CLASS and X86_64_SSEDF_CLASS.
PR target/39903
* gcc.dg/torture/pr39903-1.c: New.
* gcc.dg/torture/pr39903-2.c: Likewise.
--- gcc/config/i386/i386.c (revision 146817)
+++ gcc/config/i386/i386.c (working copy)
@@ -5466,7 +5466,10 @@ construct_container (enum machine_mode m
case X86_64_SSE_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSEDF_CLASS:
- return gen_reg_or_parallel (mode, orig_mode, SSE_REGNO (sse_regno));
+ if (mode != BLKmode)
+ return gen_reg_or_parallel (mode, orig_mode,
+ SSE_REGNO (sse_regno));
+ break;
case X86_64_X87_CLASS:
case X86_64_COMPLEX_X87_CLASS:
return gen_rtx_REG (mode, FIRST_STACK_REG);
--- gcc/testsuite/gcc.dg/torture/pr39903-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr39903-1.c (revision 0)
@@ -0,0 +1,24 @@
+/* PR target/39903 */
+/* { dg-do run } */
+/* { dg-options "-Wno-psabi" } */
+
+struct X {
+ double d;
+ double b[];
+};
+
+struct X __attribute__((noinline))
+foo (double d)
+{
+ struct X x;
+ x.d = d;
+ return x;
+}
+extern void abort (void);
+int main()
+{
+ struct X x = foo(3.0);
+ if (x.d != 3.0)
+ abort ();
+ return 0;
+}
--- gcc/testsuite/gcc.dg/torture/pr39903-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr39903-2.c (revision 0)
@@ -0,0 +1,24 @@
+/* PR target/39903 */
+/* { dg-do run } */
+/* { dg-options "-Wno-psabi" } */
+
+struct X {
+ float d;
+ float b[];
+};
+
+struct X __attribute__((noinline))
+foo (float d)
+{
+ struct X x;
+ x.d = d;
+ return x;
+}
+extern void abort (void);
+int main()
+{
+ struct X x = foo(3.0);
+ if (x.d != 3.0)
+ abort ();
+ return 0;
+}

View File

@ -1,239 +0,0 @@
2009-04-08 Jakub Jelinek <jakub@redhat.com>
* tree.h (DECL_BY_REFERENCE): Note that it is also valid for
!TREE_STATIC VAR_DECLs.
* dwarf2out.c (loc_by_reference, gen_decl_die): Handle
DECL_BY_REFERENCE on !TREE_STATIC VAR_DECLs.
(gen_variable_die): Likewise. Don't look at TREE_PRIVATE if
DECL_BY_REFERENCE is valid.
* dbxout.c (DECL_ACCESSIBILITY_CHAR): Don't look at TREE_PRIVATE
for PARM_DECLs, RESULT_DECLs or !TREE_STATIC VAR_DECLs.
* tree-nested.c (get_nonlocal_debug_decl, get_local_debug_decl):
Copy DECL_BY_REFERENCE.
(struct nesting_copy_body_data): New type.
(nesting_copy_decl): New function.
(finalize_nesting_tree_1): Remap types of debug_var_chain variables,
if they have variable length.
--- gcc/dwarf2out.c.jj 2009-04-07 08:32:56.000000000 +0200
+++ gcc/dwarf2out.c 2009-04-08 11:10:16.000000000 +0200
@@ -11709,7 +11709,9 @@ loc_by_reference (dw_loc_descr_ref loc,
if (loc == NULL)
return NULL;
- if ((TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != RESULT_DECL)
+ if ((TREE_CODE (decl) != PARM_DECL
+ && TREE_CODE (decl) != RESULT_DECL
+ && (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)))
|| !DECL_BY_REFERENCE (decl))
return loc;
@@ -14047,12 +14049,19 @@ gen_variable_die (tree decl, tree origin
else
{
tree type = TREE_TYPE (decl);
+ bool private_flag_valid = true;
add_name_and_src_coords_attributes (var_die, decl);
if ((TREE_CODE (decl) == PARM_DECL
- || TREE_CODE (decl) == RESULT_DECL)
+ || TREE_CODE (decl) == RESULT_DECL
+ || (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl)))
&& DECL_BY_REFERENCE (decl))
- add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
+ {
+ add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
+ /* DECL_BY_REFERENCE uses the same bit as TREE_PRIVATE,
+ for PARM_DECL, RESULT_DECL or non-static VAR_DECL. */
+ private_flag_valid = false;
+ }
else
add_type_attribute (var_die, type, TREE_READONLY (decl),
TREE_THIS_VOLATILE (decl), context_die);
@@ -14065,7 +14074,7 @@ gen_variable_die (tree decl, tree origin
if (TREE_PROTECTED (decl))
add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected);
- else if (TREE_PRIVATE (decl))
+ else if (private_flag_valid && TREE_PRIVATE (decl))
add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private);
}
@@ -15298,7 +15307,9 @@ gen_decl_die (tree decl, tree origin, dw
/* Output any DIEs that are needed to specify the type of this data
object. */
- if (TREE_CODE (decl_or_origin) == RESULT_DECL
+ if ((TREE_CODE (decl_or_origin) == RESULT_DECL
+ || (TREE_CODE (decl_or_origin) == VAR_DECL
+ && !TREE_STATIC (decl_or_origin)))
&& DECL_BY_REFERENCE (decl_or_origin))
gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
else
--- gcc/tree.h.jj 2009-04-06 11:48:32.000000000 +0200
+++ gcc/tree.h 2009-04-07 17:16:28.000000000 +0200
@@ -478,7 +478,7 @@ struct tree_common GTY(())
CALL_EXPR
DECL_BY_REFERENCE in
- PARM_DECL, RESULT_DECL
+ PARM_DECL, RESULT_DECL, VAR_DECL (only !TREE_STATIC)
OMP_SECTION_LAST in
OMP_SECTION
@@ -1291,8 +1291,9 @@ extern void omp_clause_range_check_faile
#define CALL_EXPR_RETURN_SLOT_OPT(NODE) \
(CALL_EXPR_CHECK (NODE)->base.private_flag)
-/* In a RESULT_DECL or PARM_DECL, means that it is passed by invisible
- reference (and the TREE_TYPE is a pointer to the true type). */
+/* In a RESULT_DECL, PARM_DECL or VAR_DECL without TREE_STATIC, means that it is
+ passed by invisible reference (and the TREE_TYPE is a pointer to the true
+ type). */
#define DECL_BY_REFERENCE(NODE) (DECL_COMMON_CHECK (NODE)->base.private_flag)
/* In a CALL_EXPR, means that the call is the jump from a thunk to the
--- gcc/tree-nested.c.jj 2009-04-06 11:47:30.000000000 +0200
+++ gcc/tree-nested.c 2009-04-08 09:50:55.000000000 +0200
@@ -827,6 +827,11 @@ get_nonlocal_debug_decl (struct nesting_
TREE_READONLY (new_decl) = TREE_READONLY (decl);
TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl);
DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
+ if ((TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == RESULT_DECL
+ || TREE_CODE (decl) == VAR_DECL)
+ && DECL_BY_REFERENCE (decl))
+ DECL_BY_REFERENCE (new_decl) = 1;
SET_DECL_VALUE_EXPR (new_decl, x);
DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
@@ -1240,6 +1245,11 @@ get_local_debug_decl (struct nesting_inf
TREE_READONLY (new_decl) = TREE_READONLY (decl);
TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl);
DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
+ if ((TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == RESULT_DECL
+ || TREE_CODE (decl) == VAR_DECL)
+ && DECL_BY_REFERENCE (decl))
+ DECL_BY_REFERENCE (new_decl) = 1;
SET_DECL_VALUE_EXPR (new_decl, x);
DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
@@ -1944,6 +1954,34 @@ convert_all_function_calls (struct nesti
while (root);
}
+struct nesting_copy_body_data
+{
+ copy_body_data cb;
+ struct nesting_info *root;
+};
+
+/* A helper subroutine for debug_var_chain type remapping. */
+
+static tree
+nesting_copy_decl (tree decl, copy_body_data *id)
+{
+ struct nesting_copy_body_data *nid = (struct nesting_copy_body_data *) id;
+ void **slot = pointer_map_contains (nid->root->var_map, decl);
+
+ if (slot)
+ return (tree) *slot;
+
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ORIGINAL_TYPE (decl))
+ {
+ tree new_decl = copy_decl_no_change (decl, id);
+ DECL_ORIGINAL_TYPE (new_decl)
+ = remap_type (DECL_ORIGINAL_TYPE (decl), id);
+ return new_decl;
+ }
+
+ return copy_decl_no_change (decl, id);
+}
+
/* Do "everything else" to clean up or complete state collected by the
various walking passes -- lay out the types and decls, generate code
to initialize the frame decl, store critical expressions in the
@@ -2076,10 +2114,66 @@ finalize_nesting_tree_1 (struct nesting_
declare_vars (root->new_local_var_chain,
gimple_seq_first_stmt (gimple_body (root->context)),
false);
+
if (root->debug_var_chain)
- declare_vars (root->debug_var_chain,
- gimple_seq_first_stmt (gimple_body (root->context)),
- true);
+ {
+ tree debug_var;
+
+ for (debug_var = root->debug_var_chain; debug_var;
+ debug_var = TREE_CHAIN (debug_var))
+ if (variably_modified_type_p (TREE_TYPE (debug_var), NULL))
+ break;
+
+ /* If there are any debug decls with variable length types,
+ remap those types using other debug_var_chain variables. */
+ if (debug_var)
+ {
+ struct nesting_copy_body_data id;
+
+ memset (&id, 0, sizeof (id));
+ id.cb.copy_decl = nesting_copy_decl;
+ id.cb.decl_map = pointer_map_create ();
+ id.root = root;
+
+ for (; debug_var; debug_var = TREE_CHAIN (debug_var))
+ if (variably_modified_type_p (TREE_TYPE (debug_var), NULL))
+ {
+ tree type = TREE_TYPE (debug_var);
+ tree newt, t = type;
+ struct nesting_info *i;
+
+ for (i = root; i; i = i->outer)
+ if (variably_modified_type_p (type, i->context))
+ break;
+
+ if (i == NULL)
+ continue;
+
+ id.cb.src_fn = i->context;
+ id.cb.dst_fn = i->context;
+ id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context);
+
+ TREE_TYPE (debug_var) = newt = remap_type (type, &id.cb);
+ while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt))
+ {
+ newt = TREE_TYPE (newt);
+ t = TREE_TYPE (t);
+ }
+ if (TYPE_NAME (newt)
+ && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (newt))
+ && newt != t
+ && TYPE_NAME (newt) == TYPE_NAME (t))
+ TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
+ }
+
+ pointer_map_destroy (id.cb.decl_map);
+ }
+
+ declare_vars (root->debug_var_chain,
+ gimple_seq_first_stmt (gimple_body (root->context)),
+ true);
+ }
/* Dump the translated tree function. */
dump_function (TDI_nested, root->context);
--- gcc/dbxout.c.jj 2009-04-06 11:47:29.000000000 +0200
+++ gcc/dbxout.c 2009-04-07 17:16:27.000000000 +0200
@@ -1397,7 +1397,9 @@ dbxout_type_index (tree type)
/* Used in several places: evaluates to '0' for a private decl,
'1' for a protected decl, '2' for a public decl. */
#define DECL_ACCESSIBILITY_CHAR(DECL) \
-(TREE_PRIVATE (DECL) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2')
+((TREE_CODE (DECL) != PARM_DECL && TREE_CODE (DECL) != RESULT_DECL \
+ && (TREE_CODE (DECL) != VAR_DECL || TREE_STATIC (DECL)) \
+ && TREE_PRIVATE (DECL)) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2')
/* Subroutine of `dbxout_type'. Output the type fields of TYPE.
This must be a separate function because anonymous unions require

View File

@ -1,175 +0,0 @@
2009-04-08 Jakub Jelinek <jakub@redhat.com>
* dwarf2out.c (loc_descr_plus_const): New function.
(build_cfa_aligned_loc, tls_mem_loc_descriptor,
mem_loc_descriptor, loc_descriptor_from_tree_1,
descr_info_loc, gen_variable_die): Use it.
--- gcc/dwarf2out.c.jj 2009-04-08 11:10:16.000000000 +0200
+++ gcc/dwarf2out.c 2009-04-08 12:52:16.000000000 +0200
@@ -3890,6 +3890,47 @@ add_loc_descr (dw_loc_descr_ref *list_he
*d = descr;
}
+/* Add a constant OFFSET to a location expression. */
+
+static void
+loc_descr_plus_const (dw_loc_descr_ref *list_head, HOST_WIDE_INT offset)
+{
+ dw_loc_descr_ref loc;
+ HOST_WIDE_INT *p;
+
+ gcc_assert (*list_head != NULL);
+
+ if (!offset)
+ return;
+
+ /* Find the end of the chain. */
+ for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next)
+ ;
+
+ p = NULL;
+ if (loc->dw_loc_opc == DW_OP_fbreg
+ || (loc->dw_loc_opc >= DW_OP_breg0 && loc->dw_loc_opc <= DW_OP_breg31))
+ p = &loc->dw_loc_oprnd1.v.val_int;
+ else if (loc->dw_loc_opc == DW_OP_bregx)
+ p = &loc->dw_loc_oprnd2.v.val_int;
+
+ /* If the last operation is fbreg, breg{0..31,x}, optimize by adjusting its
+ offset. Don't optimize if an signed integer overflow would happen. */
+ if (p != NULL
+ && ((offset > 0 && *p <= INTTYPE_MAXIMUM (HOST_WIDE_INT) - offset)
+ || (offset < 0 && *p >= INTTYPE_MINIMUM (HOST_WIDE_INT) - offset)))
+ *p += offset;
+
+ else if (offset > 0)
+ loc->dw_loc_next = new_loc_descr (DW_OP_plus_uconst, offset, 0);
+
+ else
+ {
+ loc->dw_loc_next = int_loc_descriptor (offset);
+ add_loc_descr (&loc->dw_loc_next, new_loc_descr (DW_OP_plus, 0, 0));
+ }
+}
+
/* Return the size of a location descriptor. */
static unsigned long
@@ -4409,9 +4450,7 @@ build_cfa_aligned_loc (HOST_WIDE_INT off
head = new_reg_loc_descr (dwarf_fp, 0);
add_loc_descr (&head, int_loc_descriptor (alignment));
add_loc_descr (&head, new_loc_descr (DW_OP_and, 0, 0));
-
- add_loc_descr (&head, int_loc_descriptor (offset));
- add_loc_descr (&head, new_loc_descr (DW_OP_plus, 0, 0));
+ loc_descr_plus_const (&head, offset);
}
else
head = new_reg_loc_descr (dwarf_fp, offset);
@@ -9913,7 +9952,7 @@ static dw_loc_descr_ref
tls_mem_loc_descriptor (rtx mem)
{
tree base;
- dw_loc_descr_ref loc_result, loc_result2;
+ dw_loc_descr_ref loc_result;
if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
return NULL;
@@ -9929,21 +9968,7 @@ tls_mem_loc_descriptor (rtx mem)
return NULL;
if (INTVAL (MEM_OFFSET (mem)))
- {
- if (INTVAL (MEM_OFFSET (mem)) >= 0)
- add_loc_descr (&loc_result,
- new_loc_descr (DW_OP_plus_uconst,
- INTVAL (MEM_OFFSET (mem)), 0));
- else
- {
- loc_result2 = mem_loc_descriptor (MEM_OFFSET (mem), GET_MODE (mem),
- VAR_INIT_STATUS_INITIALIZED);
- if (loc_result2 == 0)
- return NULL;
- add_loc_descr (&loc_result, loc_result2);
- add_loc_descr (&loc_result, new_loc_descr (DW_OP_plus, 0, 0));
- }
- }
+ loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem)));
return loc_result;
}
@@ -10108,11 +10133,8 @@ mem_loc_descriptor (rtx rtl, enum machin
if (mem_loc_result == 0)
break;
- if (GET_CODE (XEXP (rtl, 1)) == CONST_INT
- && INTVAL (XEXP (rtl, 1)) >= 0)
- add_loc_descr (&mem_loc_result,
- new_loc_descr (DW_OP_plus_uconst,
- INTVAL (XEXP (rtl, 1)), 0));
+ if (GET_CODE (XEXP (rtl, 1)) == CONST_INT)
+ loc_descr_plus_const (&mem_loc_result, INTVAL (XEXP (rtl, 1)));
else
{
dw_loc_descr_ref mem_loc_result2
@@ -10526,13 +10548,7 @@ loc_descriptor_from_tree_1 (tree loc, in
}
bytepos = bitpos / BITS_PER_UNIT;
- if (bytepos > 0)
- add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
- else if (bytepos < 0)
- {
- add_loc_descr (&ret, int_loc_descriptor (bytepos));
- add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
- }
+ loc_descr_plus_const (&ret, bytepos);
have_address = 1;
break;
@@ -10616,11 +10632,7 @@ loc_descriptor_from_tree_1 (tree loc, in
if (ret == 0)
return 0;
- add_loc_descr (&ret,
- new_loc_descr (DW_OP_plus_uconst,
- tree_low_cst (TREE_OPERAND (loc, 1),
- 0),
- 0));
+ loc_descr_plus_const (&ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
break;
}
@@ -13001,10 +13013,7 @@ descr_info_loc (tree val, tree base_decl
loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
if (!loc)
break;
- add_loc_descr (&loc,
- new_loc_descr (DW_OP_plus_uconst,
- tree_low_cst (TREE_OPERAND (val, 1),
- 1), 0));
+ loc_descr_plus_const (&loc, tree_low_cst (TREE_OPERAND (val, 1), 0));
}
else
{
@@ -13920,9 +13929,7 @@ gen_variable_die (tree decl, tree origin
loc->dw_loc_oprnd1.v.val_addr
= plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
else
- add_loc_descr (&loc,
- new_loc_descr (DW_OP_plus_uconst,
- off, 0));
+ loc_descr_plus_const (&loc, off);
}
add_AT_loc (var_die, DW_AT_location, loc);
remove_AT (var_die, DW_AT_declaration);
@@ -13985,8 +13992,7 @@ gen_variable_die (tree decl, tree origin
loc->dw_loc_oprnd1.v.val_addr
= plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
else
- add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst,
- off, 0));
+ loc_descr_plus_const (&loc, off);
}
add_AT_loc (var_die, DW_AT_location, loc);
}

View File

@ -1,468 +0,0 @@
2009-04-22 Jakub Jelinek <jakub@redhat.com>
* tree-nested.c (get_nonlocal_vla_type): If not optimizing, call
note_nonlocal_vla_type for nonlocal VLAs.
(note_nonlocal_vla_type, note_nonlocal_block_vlas,
contains_remapped_vars, remap_vla_decls): New functions.
(convert_nonlocal_reference_stmt): If not optimizing, call
note_nonlocal_block_vlas on GIMPLE_BIND block vars.
(nesting_copy_decl): Return {VAR,PARM,RESULT}_DECL unmodified
if it wasn't found in var_map.
(finalize_nesting_tree_1): Call remap_vla_decls. If outermost
GIMPLE_BIND doesn't have gimple_bind_block, chain debug_var_chain
to BLOCK_VARS (DECL_INITIAL (root->context)) instead of calling
declare_vars.
* gimplify.c (nonlocal_vlas): New variable.
(gimplify_var_or_parm_decl): Add debug VAR_DECLs for non-local
referenced VLAs.
(gimplify_body): Create and destroy nonlocal_vlas.
* trans-decl.c: Include pointer-set.h.
(nonlocal_dummy_decl_pset, tree nonlocal_dummy_decls): New variables.
(gfc_nonlocal_dummy_array_decl): New function.
(gfc_get_symbol_decl): Call it for non-local dummy args with saved
descriptor.
(gfc_get_symbol_decl): Set DECL_BY_REFERENCE when needed.
(gfc_generate_function_code): Initialize nonlocal_dummy_decl{s,_pset},
chain it to outermost block's vars, destroy it afterwards.
* Make-lang.in (trans-decl.o): Depend on pointer-set.h.
--- gcc/tree-nested.c.jj 2009-04-21 19:24:25.000000000 +0200
+++ gcc/tree-nested.c 2009-04-22 10:18:38.000000000 +0200
@@ -770,6 +770,7 @@ get_frame_field (struct nesting_info *in
return x;
}
+static void note_nonlocal_vla_type (struct nesting_info *info, tree type);
/* A subroutine of convert_nonlocal_reference_op. Create a local variable
in the nested function with DECL_VALUE_EXPR set to reference the true
@@ -840,6 +841,11 @@ get_nonlocal_debug_decl (struct nesting_
TREE_CHAIN (new_decl) = info->debug_var_chain;
info->debug_var_chain = new_decl;
+ if (!optimize
+ && info->context != target_context
+ && variably_modified_type_p (TREE_TYPE (decl), NULL))
+ note_nonlocal_vla_type (info, TREE_TYPE (decl));
+
return new_decl;
}
@@ -1111,6 +1117,60 @@ convert_nonlocal_omp_clauses (tree *pcla
return need_chain;
}
+/* Create nonlocal debug decls for nonlocal VLA array bounds. */
+
+static void
+note_nonlocal_vla_type (struct nesting_info *info, tree type)
+{
+ while (POINTER_TYPE_P (type) && !TYPE_NAME (type))
+ type = TREE_TYPE (type);
+
+ if (TYPE_NAME (type)
+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+ type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+
+ while (POINTER_TYPE_P (type)
+ || TREE_CODE (type) == VECTOR_TYPE
+ || TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ type = TREE_TYPE (type);
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree domain, t;
+
+ note_nonlocal_vla_type (info, TREE_TYPE (type));
+ domain = TYPE_DOMAIN (type);
+ if (domain)
+ {
+ t = TYPE_MIN_VALUE (domain);
+ if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+ && decl_function_context (t) != info->context)
+ get_nonlocal_debug_decl (info, t);
+ t = TYPE_MAX_VALUE (domain);
+ if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+ && decl_function_context (t) != info->context)
+ get_nonlocal_debug_decl (info, t);
+ }
+ }
+}
+
+/* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs
+ in BLOCK. */
+
+static void
+note_nonlocal_block_vlas (struct nesting_info *info, tree block)
+{
+ tree var;
+
+ for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
+ if (TREE_CODE (var) == VAR_DECL
+ && variably_modified_type_p (TREE_TYPE (var), NULL)
+ && DECL_HAS_VALUE_EXPR_P (var)
+ && decl_function_context (var) != info->context)
+ note_nonlocal_vla_type (info, TREE_TYPE (var));
+}
/* Callback for walk_gimple_stmt. Rewrite all references to VAR and
PARM_DECLs that belong to outer functions. This handles statements
@@ -1202,6 +1262,13 @@ convert_nonlocal_reference_stmt (gimple_
info, gimple_omp_body (stmt));
break;
+ case GIMPLE_BIND:
+ if (!optimize && gimple_bind_block (stmt))
+ note_nonlocal_block_vlas (info, gimple_bind_block (stmt));
+
+ *handled_ops_p = false;
+ return NULL_TREE;
+
default:
/* For every other statement that we are not interested in
handling here, let the walker traverse the operands. */
@@ -1979,9 +2046,117 @@ nesting_copy_decl (tree decl, copy_body_
return new_decl;
}
+ if (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == RESULT_DECL)
+ return decl;
+
return copy_decl_no_change (decl, id);
}
+/* A helper function for remap_vla_decls. See if *TP contains
+ some remapped variables. */
+
+static tree
+contains_remapped_vars (tree *tp, int *walk_subtrees, void *data)
+{
+ struct nesting_info *root = (struct nesting_info *) data;
+ tree t = *tp;
+ void **slot;
+
+ if (DECL_P (t))
+ {
+ *walk_subtrees = 0;
+ slot = pointer_map_contains (root->var_map, t);
+
+ if (slot)
+ return (tree) *slot;
+ }
+ return NULL;
+}
+
+/* Remap VLA decls in BLOCK and subblocks if remapped variables are
+ involved. */
+
+static void
+remap_vla_decls (tree block, struct nesting_info *root)
+{
+ tree var, subblock, val, type;
+ struct nesting_copy_body_data id;
+
+ for (subblock = BLOCK_SUBBLOCKS (block);
+ subblock;
+ subblock = BLOCK_CHAIN (subblock))
+ remap_vla_decls (subblock, root);
+
+ for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var))
+ {
+ if (TREE_CODE (var) == VAR_DECL
+ && variably_modified_type_p (TREE_TYPE (var), NULL)
+ && DECL_HAS_VALUE_EXPR_P (var))
+ {
+ type = TREE_TYPE (var);
+ val = DECL_VALUE_EXPR (var);
+ if (walk_tree (&type, contains_remapped_vars, root, NULL) != NULL
+ || walk_tree (&val, contains_remapped_vars, root, NULL) != NULL)
+ break;
+ }
+ }
+ if (var == NULL_TREE)
+ return;
+
+ memset (&id, 0, sizeof (id));
+ id.cb.copy_decl = nesting_copy_decl;
+ id.cb.decl_map = pointer_map_create ();
+ id.root = root;
+
+ for (; var; var = TREE_CHAIN (var))
+ if (TREE_CODE (var) == VAR_DECL
+ && variably_modified_type_p (TREE_TYPE (var), NULL)
+ && DECL_HAS_VALUE_EXPR_P (var))
+ {
+ struct nesting_info *i;
+ tree newt, t, context;
+
+ t = type = TREE_TYPE (var);
+ val = DECL_VALUE_EXPR (var);
+ if (walk_tree (&type, contains_remapped_vars, root, NULL) == NULL
+ && walk_tree (&val, contains_remapped_vars, root, NULL) == NULL)
+ continue;
+
+ context = decl_function_context (var);
+ for (i = root; i; i = i->outer)
+ if (i->context == context)
+ break;
+
+ if (i == NULL)
+ continue;
+
+ id.cb.src_fn = i->context;
+ id.cb.dst_fn = i->context;
+ id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context);
+
+ TREE_TYPE (var) = newt = remap_type (type, &id.cb);
+ while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt))
+ {
+ newt = TREE_TYPE (newt);
+ t = TREE_TYPE (t);
+ }
+ if (TYPE_NAME (newt)
+ && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (newt))
+ && newt != t
+ && TYPE_NAME (newt) == TYPE_NAME (t))
+ TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb);
+
+ walk_tree (&val, copy_tree_body_r, &id.cb, NULL);
+ if (val != DECL_VALUE_EXPR (var))
+ SET_DECL_VALUE_EXPR (var, val);
+ }
+
+ pointer_map_destroy (id.cb.decl_map);
+}
+
/* Do "everything else" to clean up or complete state collected by the
various walking passes -- lay out the types and decls, generate code
to initialize the frame decl, store critical expressions in the
@@ -2118,6 +2293,9 @@ finalize_nesting_tree_1 (struct nesting_
if (root->debug_var_chain)
{
tree debug_var;
+ gimple scope;
+
+ remap_vla_decls (DECL_INITIAL (root->context), root);
for (debug_var = root->debug_var_chain; debug_var;
debug_var = TREE_CHAIN (debug_var))
@@ -2170,9 +2348,13 @@ finalize_nesting_tree_1 (struct nesting_
pointer_map_destroy (id.cb.decl_map);
}
- declare_vars (root->debug_var_chain,
- gimple_seq_first_stmt (gimple_body (root->context)),
- true);
+ scope = gimple_seq_first_stmt (gimple_body (root->context));
+ if (gimple_bind_block (scope))
+ declare_vars (root->debug_var_chain, scope, true);
+ else
+ BLOCK_VARS (DECL_INITIAL (root->context))
+ = chainon (BLOCK_VARS (DECL_INITIAL (root->context)),
+ root->debug_var_chain);
}
/* Dump the translated tree function. */
--- gcc/gimplify.c.jj 2009-04-21 19:23:29.000000000 +0200
+++ gcc/gimplify.c 2009-04-22 00:20:41.000000000 +0200
@@ -1851,6 +1851,9 @@ gimplify_conversion (tree *expr_p)
return GS_OK;
}
+/* Nonlocal VLAs seen in the current function. */
+static struct pointer_set_t *nonlocal_vlas;
+
/* Gimplify a VAR_DECL or PARM_DECL. Returns GS_OK if we expanded a
DECL_VALUE_EXPR, and it's worth re-examining things. */
@@ -1881,7 +1884,36 @@ gimplify_var_or_parm_decl (tree *expr_p)
/* If the decl is an alias for another expression, substitute it now. */
if (DECL_HAS_VALUE_EXPR_P (decl))
{
- *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
+ tree value_expr = DECL_VALUE_EXPR (decl);
+
+ /* For referenced nonlocal VLAs add a decl for debugging purposes
+ to the current function. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
+ && nonlocal_vlas != NULL
+ && TREE_CODE (value_expr) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (value_expr, 0)) == VAR_DECL
+ && decl_function_context (decl) != current_function_decl)
+ {
+ struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+ while (ctx && ctx->region_type == ORT_WORKSHARE)
+ ctx = ctx->outer_context;
+ if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
+ {
+ tree copy = copy_node (decl), block;
+
+ lang_hooks.dup_lang_specific_decl (copy);
+ SET_DECL_RTL (copy, NULL_RTX);
+ TREE_USED (copy) = 1;
+ block = DECL_INITIAL (current_function_decl);
+ TREE_CHAIN (copy) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = copy;
+ SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr));
+ DECL_HAS_VALUE_EXPR_P (copy) = 1;
+ }
+ }
+
+ *expr_p = unshare_expr (value_expr);
return GS_OK;
}
@@ -7359,6 +7391,9 @@ gimplify_body (tree *body_p, tree fndecl
unshare_body (body_p, fndecl);
unvisit_body (body_p, fndecl);
+ if (cgraph_node (fndecl)->origin)
+ nonlocal_vlas = pointer_set_create ();
+
/* Make sure input_location isn't set to something weird. */
input_location = DECL_SOURCE_LOCATION (fndecl);
@@ -7394,6 +7429,12 @@ gimplify_body (tree *body_p, tree fndecl
gimple_bind_set_body (outer_bind, parm_stmts);
}
+ if (nonlocal_vlas)
+ {
+ pointer_set_destroy (nonlocal_vlas);
+ nonlocal_vlas = NULL;
+ }
+
pop_gimplify_context (outer_bind);
gcc_assert (gimplify_ctxp == NULL);
--- gcc/fortran/Make-lang.in.jj 2008-12-11 13:30:28.000000000 +0100
+++ gcc/fortran/Make-lang.in 2009-04-21 19:26:35.000000000 +0200
@@ -319,7 +319,7 @@ fortran/convert.o: $(GFORTRAN_TRANS_DEPS
fortran/trans.o: $(GFORTRAN_TRANS_DEPS) tree-iterator.h
fortran/trans-decl.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-decl.h \
$(CGRAPH_H) $(TARGET_H) $(FUNCTION_H) $(FLAGS_H) $(RTL_H) $(GIMPLE_H) \
- $(TREE_DUMP_H) debug.h
+ $(TREE_DUMP_H) debug.h pointer-set.h
fortran/trans-types.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-types.h \
$(REAL_H) toplev.h $(TARGET_H) $(FLAGS_H) dwarf2out.h
fortran/trans-const.o: $(GFORTRAN_TRANS_DEPS)
--- gcc/fortran/trans-decl.c.jj 2009-04-14 10:18:29.000000000 +0200
+++ gcc/fortran/trans-decl.c 2009-04-21 19:26:35.000000000 +0200
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.
#include "cgraph.h"
#include "debug.h"
#include "gfortran.h"
+#include "pointer-set.h"
#include "trans.h"
#include "trans-types.h"
#include "trans-array.h"
@@ -60,6 +61,8 @@ static GTY(()) tree current_function_ret
static GTY(()) tree saved_function_decls;
static GTY(()) tree saved_parent_function_decls;
+static struct pointer_set_t *nonlocal_dummy_decl_pset;
+static GTY(()) tree nonlocal_dummy_decls;
/* The namespace of the module we're currently generating. Only used while
outputting decls for module variables. Do not rely on this being set. */
@@ -870,6 +873,38 @@ gfc_build_dummy_array_decl (gfc_symbol *
return decl;
}
+/* For symbol SYM with GFC_DECL_SAVED_DESCRIPTOR used in contained
+ function add a VAR_DECL to the current function with DECL_VALUE_EXPR
+ pointing to the artificial variable for debug info purposes. */
+
+static void
+gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
+{
+ tree decl, dummy;
+
+ if (! nonlocal_dummy_decl_pset)
+ nonlocal_dummy_decl_pset = pointer_set_create ();
+
+ if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl))
+ return;
+
+ dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
+ decl = build_decl (VAR_DECL, DECL_NAME (dummy),
+ TREE_TYPE (sym->backend_decl));
+ DECL_ARTIFICIAL (decl) = 0;
+ TREE_USED (decl) = 1;
+ TREE_PUBLIC (decl) = 0;
+ TREE_STATIC (decl) = 0;
+ DECL_EXTERNAL (decl) = 0;
+ if (DECL_BY_REFERENCE (dummy))
+ DECL_BY_REFERENCE (decl) = 1;
+ DECL_LANG_SPECIFIC (decl) = DECL_LANG_SPECIFIC (sym->backend_decl);
+ SET_DECL_VALUE_EXPR (decl, sym->backend_decl);
+ DECL_HAS_VALUE_EXPR_P (decl) = 1;
+ DECL_CONTEXT (decl) = DECL_CONTEXT (sym->backend_decl);
+ TREE_CHAIN (decl) = nonlocal_dummy_decls;
+ nonlocal_dummy_decls = decl;
+}
/* Return a constant or a variable to use as a string length. Does not
add the decl to the current scope. */
@@ -1010,6 +1045,13 @@ gfc_get_symbol_decl (gfc_symbol * sym)
{
gfc_add_assign_aux_vars (sym);
}
+
+ if (sym->attr.dimension
+ && DECL_LANG_SPECIFIC (sym->backend_decl)
+ && GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl)
+ && DECL_CONTEXT (sym->backend_decl) != current_function_decl)
+ gfc_nonlocal_dummy_array_decl (sym);
+
return sym->backend_decl;
}
@@ -1129,6 +1171,13 @@ gfc_get_symbol_decl (gfc_symbol * sym)
sym->attr.pointer || sym->attr.allocatable);
}
+ if (!TREE_STATIC (decl)
+ && POINTER_TYPE_P (TREE_TYPE (decl))
+ && !sym->attr.pointer
+ && !sym->attr.allocatable
+ && !sym->attr.proc_pointer)
+ DECL_BY_REFERENCE (decl) = 1;
+
return decl;
}
@@ -3852,6 +3901,9 @@ gfc_generate_function_code (gfc_namespac
gfc_generate_contained_functions (ns);
+ nonlocal_dummy_decls = NULL;
+ nonlocal_dummy_decl_pset = NULL;
+
generate_local_vars (ns);
/* Keep the parent fake result declaration in module functions
@@ -4111,6 +4163,15 @@ gfc_generate_function_code (gfc_namespac
= build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (fndecl),
DECL_INITIAL (fndecl));
+ if (nonlocal_dummy_decls)
+ {
+ BLOCK_VARS (DECL_INITIAL (fndecl))
+ = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
+ pointer_set_destroy (nonlocal_dummy_decl_pset);
+ nonlocal_dummy_decls = NULL;
+ nonlocal_dummy_decl_pset = NULL;
+ }
+
/* Output the GENERIC tree. */
dump_function (TDI_original, fndecl);

View File

@ -1,2 +1,2 @@
2659f09c2e43ef8b7d4406321753f1b2 fastjar-0.97.tar.gz
441af0d1283e61c52f241a06710f56a3 gcc-4.4.0-20090424.tar.bz2
373986714230ac85e2d6d6e4abb107e0 gcc-4.4.0-20090427.tar.bz2