4.4.0-3
This commit is contained in:
parent
614bd41946
commit
b03a15ac61
|
@ -1,2 +1,2 @@
|
|||
fastjar-0.97.tar.gz
|
||||
gcc-4.4.0-20090424.tar.bz2
|
||||
gcc-4.4.0-20090427.tar.bz2
|
||||
|
|
44
gcc.spec
44
gcc.spec
|
@ -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
|
||||
|
|
|
@ -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" } } */
|
|
@ -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;
|
File diff suppressed because it is too large
Load Diff
|
@ -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]));
|
||||
+}
|
|
@ -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;
|
||||
+}
|
|
@ -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
|
|
@ -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;
|
||||
+}
|
|
@ -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;
|
||||
+}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
Loading…
Reference in New Issue