Index: configure =================================================================== --- configure (.../tags/gcc_4_2_0_release) (revision 125292) +++ configure (.../branches/gcc-4_2-branch) (revision 125292) @@ -7337,6 +7337,12 @@ #line 7338 "configure" #include "confdefs.h" +#if (__GNUC__ < 3) \ + || (__GNUC__ == 3 && (__GNUC_MINOR__ < 3 \ + || (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ < 1))) +#error http://gcc.gnu.org/PR29382 +#endif + int main() { ; return 0; } Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/tree-vrp.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -195,7 +195,28 @@ || operand_equal_p (val, TYPE_MIN_VALUE (TREE_TYPE (val)), 0))); } +/* If VAL is now an overflow infinity, return VAL. Otherwise, return + the same value with TREE_OVERFLOW clear. This can be used to avoid + confusing a regular value with an overflow value. */ +static inline tree +avoid_overflow_infinity (tree val) +{ + if (!is_overflow_infinity (val)) + return val; + + if (operand_equal_p (val, TYPE_MAX_VALUE (TREE_TYPE (val)), 0)) + return TYPE_MAX_VALUE (TREE_TYPE (val)); + else + { +#ifdef ENABLE_CHECKING + gcc_assert (operand_equal_p (val, TYPE_MIN_VALUE (TREE_TYPE (val)), 0)); +#endif + return TYPE_MIN_VALUE (TREE_TYPE (val)); + } +} + + /* Return whether VAL is equal to the maximum value of its type. This will be true for a positive overflow infinity. We can't do a simple equality comparison with TYPE_MAX_VALUE because C typedefs @@ -351,23 +372,11 @@ infinity when we shouldn't. */ static inline void -set_value_range_to_value (value_range_t *vr, tree val) +set_value_range_to_value (value_range_t *vr, tree val, bitmap equiv) { gcc_assert (is_gimple_min_invariant (val)); - if (is_overflow_infinity (val)) - { - if (operand_equal_p (val, TYPE_MAX_VALUE (TREE_TYPE (val)), 0)) - val = TYPE_MAX_VALUE (TREE_TYPE (val)); - else - { -#ifdef ENABLE_CHECKING - gcc_assert (operand_equal_p (val, - TYPE_MIN_VALUE (TREE_TYPE (val)), 0)); -#endif - val = TYPE_MIN_VALUE (TREE_TYPE (val)); - } - } - set_value_range (vr, VR_RANGE, val, val, NULL); + val = avoid_overflow_infinity (val); + set_value_range (vr, VR_RANGE, val, val, equiv); } /* Set value range VR to a non-negative range of type TYPE. @@ -411,8 +420,7 @@ static inline void set_value_range_to_null (value_range_t *vr, tree type) { - tree zero = build_int_cst (type, 0); - set_value_range (vr, VR_RANGE, zero, zero, vr->equiv); + set_value_range_to_value (vr, build_int_cst (type, 0), vr->equiv); } @@ -1028,6 +1036,8 @@ cond_code = swap_tree_comparison (TREE_CODE (cond)); } + limit = avoid_overflow_infinity (limit); + type = TREE_TYPE (limit); gcc_assert (limit != var); @@ -1619,7 +1629,7 @@ if (TREE_CODE (op0) == SSA_NAME) vr0 = *(get_value_range (op0)); else if (is_gimple_min_invariant (op0)) - set_value_range_to_value (&vr0, op0); + set_value_range_to_value (&vr0, op0, NULL); else set_value_range_to_varying (&vr0); @@ -1627,7 +1637,7 @@ if (TREE_CODE (op1) == SSA_NAME) vr1 = *(get_value_range (op1)); else if (is_gimple_min_invariant (op1)) - set_value_range_to_value (&vr1, op1); + set_value_range_to_value (&vr1, op1, NULL); else set_value_range_to_varying (&vr1); @@ -2006,7 +2016,7 @@ if (TREE_CODE (op0) == SSA_NAME) vr0 = *(get_value_range (op0)); else if (is_gimple_min_invariant (op0)) - set_value_range_to_value (&vr0, op0); + set_value_range_to_value (&vr0, op0, NULL); else set_value_range_to_varying (&vr0); @@ -2393,7 +2403,10 @@ its type may be different from _Bool. Convert VAL to EXPR's type. */ val = fold_convert (TREE_TYPE (expr), val); - set_value_range (vr, VR_RANGE, val, val, vr->equiv); + if (is_gimple_min_invariant (val)) + set_value_range_to_value (vr, val, vr->equiv); + else + set_value_range (vr, VR_RANGE, val, val, vr->equiv); } else set_value_range_to_varying (vr); @@ -2424,7 +2437,7 @@ else if (TREE_CODE_CLASS (code) == tcc_comparison) extract_range_from_comparison (vr, expr); else if (is_gimple_min_invariant (expr)) - set_value_range_to_value (vr, expr); + set_value_range_to_value (vr, expr, NULL); else set_value_range_to_varying (vr); @@ -4156,7 +4169,7 @@ t = retval = NULL_TREE; EXECUTE_IF_SET_IN_BITMAP (e2, 0, i2, bi2) { - bool sop; + bool sop = false; value_range_t vr2 = *(vr_value[i2]); Index: gcc/DATESTAMP =================================================================== --- gcc/DATESTAMP (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/DATESTAMP (.../branches/gcc-4_2-branch) (revision 125292) @@ -1 +1 @@ -20070514 +20070603 Index: gcc/pointer-set.c =================================================================== --- gcc/pointer-set.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/pointer-set.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -22,13 +22,12 @@ #include "system.h" #include "pointer-set.h" -/* A pointer sets is represented as a simple open-addressing hash +/* A pointer set is represented as a simple open-addressing hash table. Simplifications: The hash code is based on the value of the pointer, not what it points to. The number of buckets is always a power of 2. Null pointers are a reserved value. Deletion is not - supported. There is no mechanism for user control of hash - function, equality comparison, initial size, or resizing policy. -*/ + supported (yet). There is no mechanism for user control of hash + function, equality comparison, initial size, or resizing policy. */ struct pointer_set_t { @@ -114,22 +113,16 @@ } } -/* Subroutine of pointer_set_insert. Inserts P into an empty - element of SLOTS, an array of length N_SLOTS. Returns nonzero - if P was already present in N_SLOTS. */ -static int +/* Subroutine of pointer_set_insert. Return the insertion slot for P into + an empty element of SLOTS, an array of length N_SLOTS. */ +static inline size_t insert_aux (void *p, void **slots, size_t n_slots, size_t log_slots) { size_t n = hash1 (p, n_slots, log_slots); while (true) { - if (slots[n] == p) - return 1; - else if (slots[n] == 0) - { - slots[n] = p; - return 0; - } + if (slots[n] == p || slots[n] == 0) + return n; else { ++n; @@ -144,12 +137,10 @@ int pointer_set_insert (struct pointer_set_t *pset, void *p) { - if (insert_aux (p, pset->slots, pset->n_slots, pset->log_slots)) - return 1; - - /* We've inserted a new element. Expand the table if necessary to keep - the load factor small. */ - ++pset->n_elements; + size_t n; + + /* For simplicity, expand the set even if P is already there. This can be + superfluous but can happen at most once. */ if (pset->n_elements > pset->n_slots / 4) { size_t new_log_slots = pset->log_slots + 1; @@ -158,9 +149,10 @@ size_t i; for (i = 0; i < pset->n_slots; ++i) - { - if (pset->slots[i]) - insert_aux (pset->slots[i], new_slots, new_n_slots, new_log_slots); + { + void *value = pset->slots[i]; + n = insert_aux (value, new_slots, new_n_slots, new_log_slots); + new_slots[n] = value; } XDELETEVEC (pset->slots); @@ -169,5 +161,144 @@ pset->slots = new_slots; } + n = insert_aux (p, pset->slots, pset->n_slots, pset->log_slots); + if (pset->slots[n]) + return 1; + + pset->slots[n] = p; + ++pset->n_elements; return 0; } + +/* Pass each pointer in PSET to the function in FN, together with the fixed + parameter DATA. If FN returns false, the iteration stops. */ + +void pointer_set_traverse (struct pointer_set_t *pset, + bool (*fn) (void *, void *), void *data) +{ + size_t i; + for (i = 0; i < pset->n_slots; ++i) + if (pset->slots[i] && !fn (pset->slots[i], data)) + break; +} + + +/* A pointer map is represented the same way as a pointer_set, so + the hash code is based on the address of the key, rather than + its contents. Null keys are a reserved value. Deletion is not + supported (yet). There is no mechanism for user control of hash + function, equality comparison, initial size, or resizing policy. */ + +struct pointer_map_t +{ + size_t log_slots; + size_t n_slots; /* n_slots = 2^log_slots */ + size_t n_elements; + + void **keys; + void **values; +}; + +/* Allocate an empty pointer map. */ +struct pointer_map_t * +pointer_map_create (void) +{ + struct pointer_map_t *result = XNEW (struct pointer_map_t); + + result->n_elements = 0; + result->log_slots = 8; + result->n_slots = (size_t) 1 << result->log_slots; + + result->keys = XCNEWVEC (void *, result->n_slots); + result->values = XCNEWVEC (void *, result->n_slots); + return result; +} + +/* Reclaims all memory associated with PMAP. */ +void pointer_map_destroy (struct pointer_map_t *pmap) +{ + XDELETEVEC (pmap->keys); + XDELETEVEC (pmap->values); + XDELETE (pmap); +} + +/* Returns a pointer to the value to which P maps, if PMAP contains P. P + must be nonnull. Return NULL if PMAP does not contain P. + + Collisions are resolved by linear probing. */ +void ** +pointer_map_contains (struct pointer_map_t *pmap, void *p) +{ + size_t n = hash1 (p, pmap->n_slots, pmap->log_slots); + + while (true) + { + if (pmap->keys[n] == p) + return &pmap->values[n]; + else if (pmap->keys[n] == 0) + return NULL; + else + { + ++n; + if (n == pmap->n_slots) + n = 0; + } + } +} + +/* Inserts P into PMAP if it wasn't already there. Returns a pointer + to the value. P must be nonnull. */ +void ** +pointer_map_insert (struct pointer_map_t *pmap, void *p) +{ + size_t n; + + /* For simplicity, expand the map even if P is already there. This can be + superfluous but can happen at most once. */ + if (pmap->n_elements > pmap->n_slots / 4) + { + size_t new_log_slots = pmap->log_slots + 1; + size_t new_n_slots = pmap->n_slots * 2; + void **new_keys = XCNEWVEC (void *, new_n_slots); + void **new_values = XCNEWVEC (void *, new_n_slots); + size_t i; + + for (i = 0; i < pmap->n_slots; ++i) + if (pmap->keys[i]) + { + void *key = pmap->keys[i]; + n = insert_aux (key, new_keys, new_n_slots, new_log_slots); + new_keys[n] = key; + new_values[n] = pmap->values[i]; + } + + XDELETEVEC (pmap->keys); + XDELETEVEC (pmap->values); + pmap->n_slots = new_n_slots; + pmap->log_slots = new_log_slots; + pmap->keys = new_keys; + pmap->values = new_values; + } + + n = insert_aux (p, pmap->keys, pmap->n_slots, pmap->log_slots); + if (!pmap->keys[n]) + { + ++pmap->n_elements; + pmap->keys[n] = p; + } + + return &pmap->values[n]; +} + +/* Pass each pointer in PMAP to the function in FN, together with the pointer + to the value and the fixed parameter DATA. If FN returns false, the + iteration stops. */ + +void pointer_map_traverse (struct pointer_map_t *pmap, + bool (*fn) (void *, void **, void *), void *data) +{ + size_t i; + for (i = 0; i < pmap->n_slots; ++i) + if (pmap->keys[i] && !fn (pmap->keys[i], &pmap->values[i], data)) + break; +} Index: gcc/pointer-set.h =================================================================== --- gcc/pointer-set.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/pointer-set.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -22,11 +22,21 @@ #define POINTER_SET_H struct pointer_set_t; - struct pointer_set_t *pointer_set_create (void); void pointer_set_destroy (struct pointer_set_t *pset); int pointer_set_contains (struct pointer_set_t *pset, void *p); int pointer_set_insert (struct pointer_set_t *pset, void *p); +void pointer_set_traverse (struct pointer_set_t *, bool (*) (void *, void *), + void *); +struct pointer_map_t; +struct pointer_map_t *pointer_map_create (void); +void pointer_map_destroy (struct pointer_map_t *pmap); + +void **pointer_map_contains (struct pointer_map_t *pmap, void *p); +void **pointer_map_insert (struct pointer_map_t *pmap, void *p); +void pointer_map_traverse (struct pointer_map_t *, + bool (*) (void *, void **, void *), void *); + #endif /* POINTER_SET_H */ Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/fold-const.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -12634,9 +12634,14 @@ /* ... fall through ... */ default: - if (truth_value_p (TREE_CODE (t))) - /* Truth values evaluate to 0 or 1, which is nonnegative. */ - return 1; + { + tree type = TREE_TYPE (t); + if ((TYPE_PRECISION (type) != 1 || TYPE_UNSIGNED (type)) + && truth_value_p (TREE_CODE (t))) + /* Truth values evaluate to 0 or 1, which is nonnegative unless we + have a signed:1 type (where the value is -1 and 0). */ + return true; + } } /* We don't know sign of `t', so be conservative and return false. */ Index: gcc/DEV-PHASE =================================================================== --- gcc/DEV-PHASE (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/DEV-PHASE (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1 @@ +prerelease Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,174 @@ +2007-05-31 H.J. Lu + + Backport from mainline: + 2007-05-25 H.J. Lu + + * config/i386/i386.c (__builtin_ia32_vec_ext_v2df): Mark it + with MASK_SSE2. + (__builtin_ia32_vec_ext_v2di): Likewise. + (__builtin_ia32_vec_ext_v4si): Likewise. + (__builtin_ia32_vec_ext_v8hi): Likewise. + (__builtin_ia32_vec_set_v8hi): Likewise. + +2007-05-31 John David Anglin + + Backport from mainline: + 2007-05-05 Aurelien Jarno + + * config/pa/pa.md: Split tgd_load, tld_load and tie_load + into pic and non-pic versions. Mark r19 as used for + tgd_load_pic, tld_load_pic and tie_load_pic. Mark r27 as used + for tgd_load, tld_load and tie_load . + * config/pa/pa.c (legitimize_tls_address): Emit pic or non-pic + version of tgd_load, tld_load and tie_load depending on the + value of flag_pic. + +2007-05-27 Daniel Berlin + + Fix PR/30052 + Backport PTA solver from mainline + + * pointer-set.c: Copy from mainline + * pointer-set.h: Ditto. + * tree-ssa-structalias.c: Copy solver portions from mainline. + * Makefile.in (tree-ssa-structalias.o): Update dependencies + +2007-05-30 Ralf Wildenhues + + * tree-vrp.c (compare_names): Initialize sop. + +2007-05-30 Jakub Jelinek + + PR tree-optimization/31769 + * except.c (duplicate_eh_regions): Clear prev_try if + ERT_MUST_NOT_THROW region is inside of ERT_TRY region. + +2007-05-28 Andrew Pinski + + PR tree-opt/32100 + * fold-const.c (tree_expr_nonnegative_warnv_p): Don't + return true when truth_value_p is true and the type + is of signed:1. + +2007-05-27 H.J. Lu + + Backport from mainline: + 2007-05-25 Uros Bizjak + + * config/i386/sse.md (*vec_extractv2di_1_sse2): Do not calculate + "memory" attribute for "sseishft" type insn without operands[2]. + + 2007-05-25 H.J. Lu + + * config/i386/sse.md (*vec_extractv2di_1_sse2): Correct shift. + +2007-05-22 Ian Lance Taylor + + * tree-vrp.c (avoid_overflow_infinity): New static function, + broken out of set_value_range_to_value. + (set_value_range_to_value): Call avoid_overflow_infinity. + (extract_range_from_assert): Likewise. + +2007-05-23 Chen Liqin + + PR target/30987 + * config/score/misc.md (bitclr_c, bitset_c, bittgl_c): remove. + * config/score/predicate.md (const_pow2, const_npow2): remove. + * config/score/score.h (ASM_OUTPUT_EXTERNAL): add ASM_OUTPUT_EXTERNAL undef. + PR target/30474 + * config/score/score.c (score_print_operand): makes sure that only lower + bits are used. + +2007-05-21 Uros Bizjak + + PR target/31167 + Backport from mainline. + * config/i386/i386.md (*addti3_1, *addti3_1 splitter): Use + x86_64_general_operand as operand[2] predicate. Remove "iF" + from operand constraints and use "e" constraint instead. + (*subti3_1, *subti3_1 splitter): Ditto. + (*negti2_1, *negti2_1 splitter): Use nonimmediate_operand as + operand[1] predicate. + +2007-05-21 Uros Bizjak + + PR target/30041 + Backport from mainline. + * config/i386/sse.md ("*sse3_movddup"): Use operands[0] and + operands[1] in insn constraint. Correct type attribute to sselog1. + +2007-05-20 Kaz Kojima + + PR target/31701 + Backport from mainline. + * config/sh/sh.c (output_stack_adjust): Avoid using the frame + register itself to hold the offset constant. Tell flow the use + of r4 and r5 when they are used. + +2007-05-20 Kaz Kojima + + PR target/31480 + Backport from mainline. + * config/sh/sh.md (length): Check if prev_nonnote_insn (insn) + is null. + +2007-05-20 Kaz Kojima + + PR target/31022 + Backport from mainline. + * config/sh/sh.c (sh_adjust_cost): Use the result of single_set + instead of PATTERN. + +2007-05-20 Kaz Kojima + + PR target/27405 + Backport from mainline. + * config/sh/sh.md (cmp{eq,gt,gtu}{si,di}_media): Remove. + (cmpsi{eq,gt,gtu}{si,di}_media): Rename to + cmp{eq,gt,gtu}{si,di}_media. + (*cmpne0si_media): Remove. + (*movsicc_umin): Adjust gen_cmp*_media call. + (unordered): Change the mode of unordered and operands[1] to + SImode. + (seq): Adjust gen_cmp*_media calls. Make the mode of + a temporary result of compare SImode if needed. If the mode + of operands[0] is DImode, extend the temporary result to DImode. + (slt, sle, sgt, sge, sgtu, sltu, sleu, sgue, sne): Likewise. + (sunorderd): Change the mode of match_operand and unorderd to + SImode. + (cmpeq{sf,df}_media): Remove. + (cmpsieq{sf,df}_media): Rename to cmpeq{sf,df}_media. + (cmp{gt,ge,un}{sf,df}_media): Change the mode of match_operand + and compare operation to SImode. + +2007-05-18 Joseph Myers + + * config/soft-fp/double.h, config/soft-fp/extended.h, + config/soft-fp/floatundidf.c, config/soft-fp/floatundisf.c, + config/soft-fp/floatunsidf.c, config/soft-fp/floatunsisf.c, + config/soft-fp/op-2.h, config/soft-fp/op-4.h, + config/soft-fp/op-common.h, config/soft-fp/quad.h: Update from + glibc CVS. + +2007-05-17 Ian Lance Taylor + + PR tree-optimization/31953 + * tree-vrp.c (set_value_range_to_value): Add equiv parameter. + Change all callers. + (set_value_range_to_null): Call set_value_range_to_value. + (extract_range_from_comparison): Likewise. + +2007-05-17 Eric Botcazou + + PR rtl-optimization/31691 + * combine.c (simplify_set): Build a new src pattern instead of + substituting its operands in the COMPARE case. + +2007-05-14 Mark Mitchell + + * BASE-VER: Set to 4.2.1. + * DEV-PHASE: Set to prerelease. + 2007-05-13 Release Manager * GCC 4.2.0 released. @@ -307,7 +478,8 @@ 2007-04-03 Stuart Hastings PR 31281 - * objc/objc-act.c (next_sjlj_build_catch_list): Delete volatile from rethrow decl. + * objc/objc-act.c (next_sjlj_build_catch_list): Delete volatile + from rethrow decl. * cse.c (record_jump_equiv): Bail out on CCmode comparisons. 2007-04-03 Jakub Jelinek Index: gcc/testsuite/gcc.c-torture/execute/vrp-7.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/vrp-7.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/vrp-7.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,20 @@ + +void abort (void); + +struct T +{ + int b : 1; +} t; + +void __attribute__((noinline)) foo (int f) +{ + t.b = (f & 0x10) ? 1 : 0; +} + +int main (void) +{ + foo (0x10); + if (!t.b) + abort (); + return 0; +} Index: gcc/testsuite/gcc.c-torture/execute/20070517-1.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/20070517-1.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/20070517-1.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,41 @@ +/* PR rtl-optimization/31691 */ +/* Origin: Chi-Hua Chen */ + +extern void abort (void); + +static int get_kind(int) __attribute__ ((noinline)); + +static int get_kind(int v) +{ + volatile int k = v; + return k; +} + +static int some_call(void) __attribute__ ((noinline)); + +static int some_call(void) +{ + return 0; +} + +static void example (int arg) +{ + int tmp, kind = get_kind (arg); + + if (kind == 9 || kind == 10 || kind == 5) + { + if (some_call() == 0) + { + if (kind == 9 || kind == 10) + tmp = arg; + else + abort(); + } + } +} + +int main(void) +{ + example(10); + return 0; +} Index: gcc/testsuite/gcc.c-torture/compile/pr31953.c =================================================================== --- gcc/testsuite/gcc.c-torture/compile/pr31953.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.c-torture/compile/pr31953.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,14 @@ +struct WView +{ + int hexedit_mode:1; +}; +toggle_hexedit_mode (struct WView *view) +{ + if (view->hexedit_mode) + { + } + else + { + view->hexedit_mode = !view->hexedit_mode; + } +} Index: gcc/testsuite/gcc.target/i386/sse2-vec-3.c =================================================================== --- gcc/testsuite/gcc.target/i386/sse2-vec-3.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.target/i386/sse2-vec-3.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,37 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -msse2" } */ + +#include "sse2-check.h" + +#include + +static void +sse2_test (void) +{ + union + { + __m128i x; + char c[16]; + short s[8]; + int i[4]; + long long ll[2]; + } val1; + int res[4]; + int masks[4]; + int i; + + for (i = 0; i < 16; i++) + val1.c[i] = i; + + res[0] = __builtin_ia32_vec_ext_v4si ((__v4si)val1.x, 0); + res[1] = __builtin_ia32_vec_ext_v4si ((__v4si)val1.x, 1); + res[2] = __builtin_ia32_vec_ext_v4si ((__v4si)val1.x, 2); + res[3] = __builtin_ia32_vec_ext_v4si ((__v4si)val1.x, 3); + + for (i = 0; i < 4; i++) + masks[i] = i; + + for (i = 0; i < 4; i++) + if (res[i] != val1.i [masks[i]]) + abort (); +} Index: gcc/testsuite/gcc.target/i386/pr31167.c =================================================================== --- gcc/testsuite/gcc.target/i386/pr31167.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.target/i386/pr31167.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,20 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-O" } */ + +typedef int int32_t; + +int32_t round32hi (const __int128_t arg) +{ + const int SHIFT = 96; + const int mshift = 96; + const __int128_t M = (~(__int128_t) 0) << mshift; + const __int128_t L = (~M) + 1; + const __int128_t L1 = ((__int128_t) L) >> 1; + const __int128_t Mlo = ((__int128_t) (~M)) >> 1; + __int128_t vv = arg & M; + + if ((arg & (L1)) && ((arg & Mlo) || (arg & L))) + vv += L; + + return (int32_t) (vv >> SHIFT); +} Index: gcc/testsuite/gcc.target/i386/sse2-vec-4.c =================================================================== --- gcc/testsuite/gcc.target/i386/sse2-vec-4.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.target/i386/sse2-vec-4.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,41 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -msse2" } */ + +#include "sse2-check.h" + +#include + +static void +sse2_test (void) +{ + union + { + __m128i x; + char c[16]; + short s[8]; + int i[4]; + long long ll[2]; + } val1; + short res[8]; + int masks[8]; + int i; + + for (i = 0; i < 16; i++) + val1.c[i] = i; + + res[0] = __builtin_ia32_vec_ext_v8hi ((__v8hi)val1.x, 0); + res[1] = __builtin_ia32_vec_ext_v8hi ((__v8hi)val1.x, 1); + res[2] = __builtin_ia32_vec_ext_v8hi ((__v8hi)val1.x, 2); + res[3] = __builtin_ia32_vec_ext_v8hi ((__v8hi)val1.x, 3); + res[4] = __builtin_ia32_vec_ext_v8hi ((__v8hi)val1.x, 4); + res[5] = __builtin_ia32_vec_ext_v8hi ((__v8hi)val1.x, 5); + res[6] = __builtin_ia32_vec_ext_v8hi ((__v8hi)val1.x, 6); + res[7] = __builtin_ia32_vec_ext_v8hi ((__v8hi)val1.x, 7); + + for (i = 0; i < 8; i++) + masks[i] = i; + + for (i = 0; i < 8; i++) + if (res[i] != val1.s [masks[i]]) + abort (); +} Index: gcc/testsuite/gcc.target/i386/sse2-check.h =================================================================== --- gcc/testsuite/gcc.target/i386/sse2-check.h (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.target/i386/sse2-check.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,20 @@ +#include +#include + +#include "../../gcc.dg/i386-cpuid.h" + +static void sse2_test (void); + +int +main () +{ + unsigned long cpu_facilities; + + cpu_facilities = i386_cpuid_edx (); + + /* Run SSE2 test only if host has SSE2 support. */ + if ((cpu_facilities & bit_SSE2)) + sse2_test (); + + exit (0); +} Index: gcc/testsuite/gcc.target/i386/sse2-vec-1.c =================================================================== --- gcc/testsuite/gcc.target/i386/sse2-vec-1.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.target/i386/sse2-vec-1.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,35 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -msse2" } */ + +#include "sse2-check.h" + +#include + +#define msk0 0 +#define msk1 1 + +static void +sse2_test (void) +{ + union + { + __m128d x; + double d[2]; + } val1; + double res[2]; + int masks[2]; + int i; + + val1.d[0] = 23.; + val1.d[1] = 45; + + res[0] = __builtin_ia32_vec_ext_v2df ((__v2df)val1.x, msk0); + res[1] = __builtin_ia32_vec_ext_v2df ((__v2df)val1.x, msk1); + + masks[0] = msk0; + masks[1] = msk1; + + for (i = 0; i < 2; i++) + if (res[i] != val1.d [masks[i]]) + abort (); +} Index: gcc/testsuite/gcc.target/i386/sse2-vec-5.c =================================================================== --- gcc/testsuite/gcc.target/i386/sse2-vec-5.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.target/i386/sse2-vec-5.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,49 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -msse2" } */ + +#include "sse2-check.h" + +#include + +static void +sse2_test (void) +{ + union + { + __m128i x; + char c[16]; + short s[8]; + int i[4]; + long long ll[2]; + } val1; + char res[16]; + int masks[16]; + int i; + + for (i = 0; i < 16; i++) + val1.c[i] = i; + + res[0] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 0); + res[1] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 1); + res[2] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 2); + res[3] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 3); + res[4] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 4); + res[5] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 5); + res[6] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 6); + res[7] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 7); + res[8] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 8); + res[9] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 9); + res[10] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 10); + res[11] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 11); + res[12] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 12); + res[13] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 13); + res[14] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 14); + res[15] = __builtin_ia32_vec_ext_v16qi ((__v16qi)val1.x, 15); + + for (i = 0; i < 16; i++) + masks[i] = i; + + for (i = 0; i < 16; i++) + if (res[i] != val1.c [masks[i]]) + abort (); +} Index: gcc/testsuite/gcc.target/i386/sse2-vec-2.c =================================================================== --- gcc/testsuite/gcc.target/i386/sse2-vec-2.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.target/i386/sse2-vec-2.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,35 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -msse2" } */ + +#include "sse2-check.h" + +#include + +static void +sse2_test (void) +{ + union + { + __m128i x; + char c[16]; + short s[8]; + int i[4]; + long long ll[2]; + } val1; + long long res[2]; + int masks[2]; + int i; + + for (i = 0; i < 16; i++) + val1.c[i] = i; + + res[0] = __builtin_ia32_vec_ext_v2di ((__v2di)val1.x, 0); + res[1] = __builtin_ia32_vec_ext_v2di ((__v2di)val1.x, 1); + + for (i = 0; i < 2; i++) + masks[i] = i; + + for (i = 0; i < 2; i++) + if (res[i] != val1.ll [masks[i]]) + abort (); +} Index: gcc/testsuite/gcc.target/i386/sse2-vec-6.c =================================================================== --- gcc/testsuite/gcc.target/i386/sse2-vec-6.c (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gcc.target/i386/sse2-vec-6.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,69 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -msse2" } */ + +#include "sse2-check.h" + +#include +#include + +static void +sse2_test (void) +{ + union + { + __m128i x; + char c[16]; + short s[8]; + int i[4]; + long long ll[2]; + } val1, res[16], tmp; + short ins[8] = { 8, 5, 9, 4, 2, 6, 1, 20 }; + int masks[8]; + int i; + + for (i = 0; i < 16; i++) + val1.c[i] = i; + + res[0].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[0], 0); + res[1].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[0], 1); + res[2].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[0], 2); + res[3].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[0], 3); + res[4].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[0], 4); + res[5].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[0], 5); + res[6].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[0], 6); + res[7].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[0], 7); + + for (i = 0; i < 8; i++) + masks[i] = i; + + for (i = 0; i < 8; i++) + { + tmp.x = val1.x; + tmp.s[masks[i]] = ins[0]; + if (memcmp (&tmp, &res[i], sizeof (tmp))) + abort (); + } + + for (i = 0; i < 8; i++) + { + res[i].x = (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)val1.x, + ins[i], 0); + masks[i] = 0; + } + + for (i = 0; i < 8; i++) + { + tmp.x = val1.x; + tmp.s[masks[i]] = ins[i]; + if (memcmp (&tmp, &res[i], sizeof (tmp))) + abort (); + } +} Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/testsuite/ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,104 @@ +2007-05-31 H.J. Lu + + Backport from mainline: + 2007-05-25 H.J. Lu + + * gcc.target/i386/sse2-check.h: New. + * gcc.target/i386/sse2-vec-1.c: Likewise. + * gcc.target/i386/sse2-vec-2.c: Likewise. + * gcc.target/i386/sse2-vec-3.c: Likewise. + * gcc.target/i386/sse2-vec-4.c: Likewise. + * gcc.target/i386/sse2-vec-5.c: Likewise. + * gcc.target/i386/sse2-vec-6.c: Likewise. + +2007-05-31 Paul Thomas + + PR fortran/31483 + * gfortran.dg/altreturn_5.f90: New test. + + PR fortran/31540 + * gfortran.dg/char_result_5.f90: New test. + + PR fortran/31867 + * gfortran.dg/char_length_5.f90: New test. + + PR fortran/31994 + * gfortran.dg/array_reference_1.f90: New test. + +2007-05-22 Tobias Burnus + + PR fortran/31559 + Backport from mainline. + * primary.c (match_variable): External functions + are no variables. + +2007-05-30 Jakub Jelinek + + PR tree-optimization/31769 + * g++.dg/gomp/pr31769.C: New test. + +2007-05-28 Andrew Pinski + + PR tree-opt/32100 + * gcc.c-torture/execute/vrp-7.c: New test. + +2007-05-23 Jerry DeLisle + + PR libfortran/31964 + * gfortran.fortran-torture/execute/intrinsic_bitops.f90: Update. + +2007-05-22 Jerry DeLisle + + PR libgfortran/31051 + * gfortran.dg/fmt_t_3.f90: New. + +2007-05-22 Dominique d'Humieres + + * gfortran.dg/unf_io_convert_3.f90: Fix dg directive. + +2007-05-22 Tobias Burnus + + PR fortran/31559 + Backport from mainline. + * func_assign.f90: New test. + +2007-05-21 Uros Bizjak + + PR target/31167 + Backport from mainline. + * gcc.target/i386/pr31167.c: New test. + +2007-05-20 Jerry DeLisle + + PR libgfortran/31395 + * gfortran.dg/fmt_colon.f90: New test. + +2007-05-20 Thomas Koenig + + PR fortran/31618 + Backport from trunk. + * gfortran.dg/backspace_8.f: New test case. + +2007-05-20 Thomas Koenig + + PR libfortran/31196 + Backport from trunk. + * gfortran.dg/reshape_transpose_1.f90: New test. + +2007-05-17 Ian Lance Taylor + + PR tree-optimization/31953 + * gcc.c-torture/compile/pr31953.c: New test. + +2007-05-17 Eric Botcazou + + * gcc.c-torture/execute/20070517-1.c: New test. + +2007-05-16 Francois-Xavier Coudert + + PR fortran/31725 + * gfortran.dg/substr_4.f: New test. + 2007-05-13 Release Manager * GCC 4.2.0 released. Index: gcc/testsuite/gfortran.fortran-torture/execute/intrinsic_bitops.f90 =================================================================== --- gcc/testsuite/gfortran.fortran-torture/execute/intrinsic_bitops.f90 (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/testsuite/gfortran.fortran-torture/execute/intrinsic_bitops.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -8,7 +8,8 @@ i = 2 j = 3 k = 12 - + a = 5 + if (.not. btest (i, o+1)) call abort if (btest (i, o+2)) call abort if (iand (i, j) .ne. 2) call abort @@ -26,4 +27,6 @@ if (ishftc (k, o-30) .ne. 48) call abort if (ishftc (k, o+1, o+3) .ne. 9) call abort if (not (i) .ne. -3) call abort + if (ishftc (a, 1, bit_size(a)) .ne. 10) call abort + if (ishftc (1, 1, 32) .ne. 2) call abort end program Index: gcc/testsuite/g++.dg/gomp/pr31769.C =================================================================== --- gcc/testsuite/g++.dg/gomp/pr31769.C (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/g++.dg/gomp/pr31769.C (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,61 @@ +// PR tree-optimization/31769 +// { dg-options "-O2 -fopenmp" } +// { dg-do compile } + +struct B +{ + B () {} + virtual ~B () {} +}; +struct C +{ + C (int x, int y) {} +}; +template +struct D +{ + D () {} + ~D () {} +}; +struct E +{ + E () {} + ~E () {} + D e; +}; +struct A +{ + B *b; + A () { b = __null; } + ~A () { if (b != __null) delete b; } +}; +struct F : public A +{ + explicit F (int x) { foo (0); } + F (const F &x) {} + F (F &x, C y) {} + F operator () (C x) const + { + return F (const_cast(*this), x); + } + template F & operator+= (const U &); + void foo (int); + E f; +}; + +int +main () +{ + try + { + F f (10); + F g (10); + C h (0, 9); +#pragma omp parallel for + for (int i = 0; i < 2; ++i) + g += f (h); + } + catch (int &e) + { + } +} Index: gcc/testsuite/gfortran.dg/char_length_5.f90 =================================================================== --- gcc/testsuite/gfortran.dg/char_length_5.f90 (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/char_length_5.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,61 @@ +! { dg-do run } +! Tests the fix for PR31867, in which the interface evaluation +! of the character length of 'join' (ie. the length available in +! the caller) was wrong. +! +! Contributed by +! +module util_mod + implicit none +contains + function join (words, sep) result(str) + character (len=*), intent(in) :: words(:),sep + character (len = (size (words) - 1) * len_trim (sep) + & + sum (len_trim (words))) :: str + integer :: i,nw + nw = size (words) + str = "" + if (nw < 1) then + return + else + str = words(1) + end if + do i=2,nw + str = trim (str) // trim (sep) // words(i) + end do + end function join +end module util_mod +! +program xjoin + use util_mod, only: join + implicit none + integer yy + character (len=5) :: words(5:8) = (/"two ","three","four ","five "/), sep = "^#^" + character (len=5) :: words2(4) = (/"bat ","ball ","goal ","stump"/), sep2 = "&" + + if (join (words, sep) .ne. "two^#^three^#^four^#^five") call abort () + if (len (join (words, sep)) .ne. 25) call abort () + + if (join (words(5:6), sep) .ne. "two^#^three") call abort () + if (len (join (words(5:6), sep)) .ne. 11) call abort () + + if (join (words(7:8), sep) .ne. "four^#^five") call abort () + if (len (join (words(7:8), sep)) .ne. 11) call abort () + + if (join (words(5:7:2), sep) .ne. "two^#^four") call abort () + if (len (join (words(5:7:2), sep)) .ne. 10) call abort () + + if (join (words(6:8:2), sep) .ne. "three^#^five") call abort () + if (len (join (words(6:8:2), sep)) .ne. 12) call abort () + + if (join (words2, sep2) .ne. "bat&ball&goal&stump") call abort () + if (len (join (words2, sep2)) .ne. 19) call abort () + + if (join (words2(1:2), sep2) .ne. "bat&ball") call abort () + if (len (join (words2(1:2), sep2)) .ne. 8) call abort () + + if (join (words2(2:4:2), sep2) .ne. "ball&stump") call abort () + if (len (join (words2(2:4:2), sep2)) .ne. 10) call abort () + +end program xjoin +! { dg-final { cleanup-modules "util_mod" } } Index: gcc/testsuite/gfortran.dg/array_reference_1.f90 =================================================================== --- gcc/testsuite/gfortran.dg/array_reference_1.f90 (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/array_reference_1.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,35 @@ +! { dg-do run } +! Tests the fix for PR31994, aka 31867, in which the offset +! of 'a' in both subroutines was being evaluated incorrectly. +! The testcase for PR31867 is char_length_5.f90 +! +! Contributed by Elizabeth Yip +! and Francois-Xavier Coudert +! +program main + call PR31994 + call PR31994_comment6 +contains + subroutine PR31994 + implicit none + complex (kind=4), dimension(2,2) :: a, b, c + a(1,1) = (1.,1.) + a(2,1) = (2.,2.) + a(1,2) = (3.,3.) + a(2,2) = (4.,4.) + b=conjg (transpose (a)) + c=transpose (a) + c=conjg (c) + if (any (b .ne. c)) call abort () + end subroutine PR31994 + subroutine PR31994_comment6 + implicit none + real ,dimension(2,2)::a + integer ,dimension(2,2) :: b, c + a = reshape ((/1.,2.,3.,4./), (/2,2/)) + b=int (transpose(a)) + c = int (a) + c = transpose (c) + if (any (b .ne. c)) call abort () + end subroutine PR31994_comment6 +END program main Index: gcc/testsuite/gfortran.dg/reshape_transpose_1.f90 =================================================================== --- gcc/testsuite/gfortran.dg/reshape_transpose_1.f90 (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/reshape_transpose_1.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,18 @@ +! { dg-do run } +! PR 31196 - reshape of transposed derived types generated +! wront results. +program main + implicit none + TYPE datatype + INTEGER :: I + END TYPE datatype + character (len=20) line1, line2 + TYPE(datatype), dimension(2,2) :: data, result + data(1,1)%i = 1 + data(2,1)%i = 2 + data(1,2)%i = 3 + data(2,2)%i = 4 + write (unit=line1, fmt="(4I4)") reshape(transpose(data),shape(data)) + write (unit=line2, fmt="(4I4)") (/ 1, 3, 2, 4 /) + if (line1 /= line2) call abort +END program main Index: gcc/testsuite/gfortran.dg/fmt_colon.f90 =================================================================== --- gcc/testsuite/gfortran.dg/fmt_colon.f90 (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/fmt_colon.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,14 @@ +! { dg-do run } +! PR31395 Colon edit descriptor is ignored. +! Test case derived from PR. Prepared by Jerry DeLisle +! +PROGRAM test + INTEGER :: i = 1 + character(30) :: astring + WRITE(astring, 10) i + 10 FORMAT('i =',I2:' this should not print') + if (astring.ne."i = 1") call abort + write(astring, 20) i, i + 20 format('i =',I2:' this should print',I2) + if (astring.ne."i = 1 this should print 1") call abort +END PROGRAM test \ No newline at end of file Index: gcc/testsuite/gfortran.dg/char_result_13.f90 =================================================================== --- gcc/testsuite/gfortran.dg/char_result_13.f90 (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/char_result_13.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,13 @@ +! { dg-do compile } +! tests the fix for PR31540, in which the character lengths in +! parentheses were not resolved. +! +! Contributed by Tobias Burnus +! + subroutine pfb() + implicit none + external pfname1, pfname2 + character ((136)) pfname1 + character ((129+7)) pfname2 + return + end Index: gcc/testsuite/gfortran.dg/altreturn_5.f90 =================================================================== --- gcc/testsuite/gfortran.dg/altreturn_5.f90 (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/altreturn_5.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,30 @@ +! { dg-do run } +! Tests the fix for PR31483, in which dummy argument procedures +! produced an ICE if they had an alternate return. +! +! Contributed by Mathias Fröhlich + + SUBROUTINE R (i, *, *) + INTEGER i + RETURN i + END + + SUBROUTINE PHLOAD (READER, i, res) + IMPLICIT NONE + EXTERNAL READER + integer i + character(3) res + CALL READER (i, *1, *2) + 1 res = "one" + return + 2 res = "two" + return + END + + EXTERNAL R + character(3) res + call PHLOAD (R, 1, res) + if (res .ne. "one") call abort () + CALL PHLOAD (R, 2, res) + if (res .ne. "two") call abort () + END \ No newline at end of file Index: gcc/testsuite/gfortran.dg/substr_4.f =================================================================== --- gcc/testsuite/gfortran.dg/substr_4.f (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/substr_4.f (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,69 @@ +! { dg-do run } + subroutine test_lower + implicit none + character(3), dimension(3) :: zsymel,zsymelr + common /xx/ zsymel, zsymelr + integer :: znsymelr + zsymel = (/ 'X', 'Y', ' ' /) + zsymelr= (/ 'X', 'Y', ' ' /) + znsymelr=2 + call check_zsymel(zsymel,zsymelr,znsymelr) + + contains + + subroutine check_zsymel(zsymel,zsymelr,znsymelr) + implicit none + integer znsymelr, isym + character(*) zsymel(*),zsymelr(*) + character(len=80) buf + zsymel(3)(lenstr(zsymel(3))+1:)='X' + write (buf,10) (trim(zsymelr(isym)),isym=1,znsymelr) +10 format(3(a,:,',')) + if (trim(buf) /= 'X,Y') call abort + end subroutine check_zsymel + + function lenstr(s) + character(len=*),intent(in) :: s + integer :: lenstr + if (len_trim(s) /= 0) call abort + lenstr = len_trim(s) + end function lenstr + + end subroutine test_lower + + subroutine test_upper + implicit none + character(3), dimension(3) :: zsymel,zsymelr + common /xx/ zsymel, zsymelr + integer :: znsymelr + zsymel = (/ 'X', 'Y', ' ' /) + zsymelr= (/ 'X', 'Y', ' ' /) + znsymelr=2 + call check_zsymel(zsymel,zsymelr,znsymelr) + + contains + + subroutine check_zsymel(zsymel,zsymelr,znsymelr) + implicit none + integer znsymelr, isym + character(*) zsymel(*),zsymelr(*) + character(len=80) buf + zsymel(3)(:lenstr(zsymel(3))+1)='X' + write (buf,20) (trim(zsymelr(isym)),isym=1,znsymelr) +20 format(3(a,:,',')) + if (trim(buf) /= 'X,Y') call abort + end subroutine check_zsymel + + function lenstr(s) + character(len=*),intent(in) :: s + integer :: lenstr + if (len_trim(s) /= 0) call abort + lenstr = len_trim(s) + end function lenstr + + end subroutine test_upper + + program test + call test_lower + call test_upper + end program test Index: gcc/testsuite/gfortran.dg/fmt_t_3.f90 =================================================================== --- gcc/testsuite/gfortran.dg/fmt_t_3.f90 (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/fmt_t_3.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,15 @@ +! { dg-do run } +! PR31051 bug with x and t format descriptors. +! Test case prepared by Jerry DeLisle from PR. +program t + integer, parameter :: n = 9 + character(len=40) :: fmt + character(len=2), dimension(n) :: y + open(unit=10, status="scratch") + y = 'a ' + fmt = '(a,1x,(t7, 3a))' + write(10, fmt) 'xxxx', (y(i), i = 1,n) + rewind(10) + read(10, '(a)') fmt + if (fmt.ne."xxxx a a a") call abort() +end program t Index: gcc/testsuite/gfortran.dg/backspace_8.f =================================================================== --- gcc/testsuite/gfortran.dg/backspace_8.f (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/backspace_8.f (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,18 @@ +C { dg-do run } +C PR libfortran/31618 - backspace after an error didn't work. + program main + character*78 msg + open (21, file="backspace_7.dat", form="unformatted") + write (21) 42, 43 + write (21) 4711, 4712 + write (21) -1, -4 + rewind (21) + read (21) i,j + read (21,err=100,end=100) i,j,k + call abort + 100 continue + backspace 21 + read (21) i,j + if (i .ne. 4711 .or. j .ne. 4712) call abort + close (21,status="delete") + end Index: gcc/testsuite/gfortran.dg/func_assign.f90 =================================================================== --- gcc/testsuite/gfortran.dg/func_assign.f90 (.../tags/gcc_4_2_0_release) (revision 0) +++ gcc/testsuite/gfortran.dg/func_assign.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -0,0 +1,33 @@ +! { dg-do compile } +! +! PR fortran/31559 +! Do not allow assigning to external functions +! +! Contributed by Steve Kargl +! +module mod + implicit none +contains + integer function bar() + bar = 4 + end function bar + + subroutine a() + implicit none + real :: fun + external fun + interface + function funget(a) + integer :: a + end function + subroutine sub() + end subroutine sub + end interface + sub = 'a' ! { dg-error "Expected VARIABLE" } + fun = 4.4 ! { dg-error "Expected VARIABLE" } + funget = 4 ! { dg-error "is not a VALUE" } + bar = 5 ! { dg-error "is not a VALUE" } + end subroutine a +end module mod + +end Index: gcc/testsuite/gfortran.dg/unf_io_convert_3.f90 =================================================================== --- gcc/testsuite/gfortran.dg/unf_io_convert_3.f90 (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/testsuite/gfortran.dg/unf_io_convert_3.f90 (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,4 +1,4 @@ -! { dg-do run} +! { dg-do run } ! { dg-require-effective-target fortran_large_real } program main integer,parameter :: k = selected_real_kind (precision (0.0_8) + 1) Index: gcc/fortran/trans-expr.c =================================================================== --- gcc/fortran/trans-expr.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/fortran/trans-expr.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -255,6 +255,10 @@ gfc_conv_string_parameter (se); else { + /* Avoid multiple evaluation of substring start. */ + if (!CONSTANT_CLASS_P (start.expr) && !DECL_P (start.expr)) + start.expr = gfc_evaluate_now (start.expr, &se->pre); + /* Change the start of the string. */ if (TYPE_STRING_FLAG (TREE_TYPE (se->expr))) tmp = se->expr; @@ -273,6 +277,10 @@ gfc_conv_expr_type (&end, ref->u.ss.end, gfc_charlen_type_node); gfc_add_block_to_block (&se->pre, &end.pre); } + + if (!CONSTANT_CLASS_P (end.expr) && !DECL_P (end.expr)) + end.expr = gfc_evaluate_now (end.expr, &se->pre); + tmp = fold_build2 (MINUS_EXPR, gfc_charlen_type_node, build_int_cst (gfc_charlen_type_node, 1), start.expr); @@ -2340,17 +2348,23 @@ /* Generate the actual call. */ gfc_conv_function_val (se, sym); + /* If there are alternate return labels, function type should be integer. Can't modify the type in place though, since it can be shared - with other functions. */ + with other functions. For dummy arguments, the typing is done to + to this result, even if it has to be repeated for each call. */ if (has_alternate_specifier && TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr))) != integer_type_node) { - gcc_assert (! sym->attr.dummy); - TREE_TYPE (sym->backend_decl) - = build_function_type (integer_type_node, - TYPE_ARG_TYPES (TREE_TYPE (sym->backend_decl))); - se->expr = build_fold_addr_expr (sym->backend_decl); + if (!sym->attr.dummy) + { + TREE_TYPE (sym->backend_decl) + = build_function_type (integer_type_node, + TYPE_ARG_TYPES (TREE_TYPE (sym->backend_decl))); + se->expr = build_fold_addr_expr (sym->backend_decl); + } + else + TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr))) = integer_type_node; } fntype = TREE_TYPE (TREE_TYPE (se->expr)); Index: gcc/fortran/trans-array.c =================================================================== --- gcc/fortran/trans-array.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/fortran/trans-array.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -4422,6 +4422,8 @@ if (se->direct_byref) base = gfc_index_zero_node; + else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc))) + base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre); else base = NULL_TREE; @@ -4489,8 +4491,20 @@ stride, info->stride[dim]); if (se->direct_byref) - base = fold_build2 (MINUS_EXPR, TREE_TYPE (base), - base, stride); + { + base = fold_build2 (MINUS_EXPR, TREE_TYPE (base), + base, stride); + } + else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc))) + { + tmp = gfc_conv_array_lbound (desc, n); + tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (base), + tmp, loop.from[dim]); + tmp = fold_build2 (MULT_EXPR, TREE_TYPE (base), + tmp, gfc_conv_array_stride (desc, n)); + base = fold_build2 (PLUS_EXPR, TREE_TYPE (base), + tmp, base); + } /* Store the new stride. */ tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]); @@ -4511,7 +4525,8 @@ gfc_conv_descriptor_data_set (&loop.pre, parm, offset); } - if (se->direct_byref && !se->data_not_needed) + if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc))) + && !se->data_not_needed) { /* Set the offset. */ tmp = gfc_conv_descriptor_offset (parm); Index: gcc/fortran/gfortran.texi =================================================================== --- gcc/fortran/gfortran.texi (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/fortran/gfortran.texi (.../branches/gcc-4_2-branch) (revision 125292) @@ -611,7 +611,7 @@ to change the representation of data for unformatted files. The syntax for the @env{GFORTRAN_CONVERT_UNIT} variable is: @smallexample -GFORTRAN_CONVERT_UNIT: mode | mode ';' exception ; +GFORTRAN_CONVERT_UNIT: mode | mode ';' exception | exception ; mode: 'native' | 'swap' | 'big_endian' | 'little_endian' ; exception: mode ':' unit_list | unit_list ; unit_list: unit_spec | unit_list unit_spec ; @@ -668,7 +668,12 @@ setting a default data representation for the whole program. The @code{CONVERT} specifier overrides the @option{-fconvert} compile options. +@emph{Note that the values specified via the GFORTRAN_CONVERT_UNIT +environment variable will override the CONVERT specifier in the +open statement}. This is to give control over data formats to +users who do not have the source code of their program available. + @c ===================================================================== @c PART II: LANGUAGE REFERENCE @c ===================================================================== Index: gcc/fortran/ChangeLog =================================================================== --- gcc/fortran/ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/fortran/ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,30 @@ +2007-05-31 Paul Thomas + + PR fortran/31483 + * trans-expr.c (gfc_conv_function_call): Give a dummy + procedure the correct type if it has alternate returns. + + + PR fortran/31540 + * resolve.c (resolve_fl_procedure): Resolve constant character + lengths. + + PR fortran/31867 + PR fortran/31994 + * trans-array.c (gfc_conv_expr_descriptor): Obtain the stored + offset for non-descriptor, source arrays and correct for stride + not equal to one before writing to field of output descriptor. + +2007-05-17 Tobias Burnus + + * gfortran.texi (GFORTRAN_CONVERT_UNIT): Improve documentation. + +2007-05-16 Francois-Xavier Coudert + + PR fortran/31725 + * trans-expr.c (gfc_conv_substring): Evaluate substring bounds + only once. + 2007-05-13 Release Manager * GCC 4.2.0 released. Index: gcc/fortran/resolve.c =================================================================== --- gcc/fortran/resolve.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/fortran/resolve.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -5742,6 +5742,11 @@ if (sym->ts.type == BT_CHARACTER) { gfc_charlen *cl = sym->ts.cl; + + if (cl && cl->length && gfc_is_constant_expr (cl->length) + && resolve_charlen (cl) == FAILURE) + return FAILURE; + if (!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT) { if (sym->attr.proc == PROC_ST_FUNCTION) Index: gcc/fortran/primary.c =================================================================== --- gcc/fortran/primary.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/fortran/primary.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -2415,7 +2415,8 @@ case FL_PROCEDURE: /* Check for a nonrecursive function result */ - if (sym->attr.function && (sym->result == sym || sym->attr.entry)) + if (sym->attr.function && (sym->result == sym || sym->attr.entry) + && !sym->attr.external) { /* If a function result is a derived type, then the derived type may still have to be resolved. */ Index: gcc/BASE-VER =================================================================== --- gcc/BASE-VER (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/BASE-VER (.../branches/gcc-4_2-branch) (revision 125292) @@ -1 +1 @@ -4.2.0 +4.2.1 Index: gcc/except.c =================================================================== --- gcc/except.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/except.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -1005,7 +1005,11 @@ for (prev_try = VEC_index (eh_region, cfun->eh->region_array, outer_region); prev_try && prev_try->type != ERT_TRY; prev_try = prev_try->outer) - ; + if (prev_try->type == ERT_MUST_NOT_THROW) + { + prev_try = NULL; + break; + } /* Remap all of the internal catch and cleanup linkages. Since we duplicate entire subtrees, all of the referenced regions will have Index: gcc/combine.c =================================================================== --- gcc/combine.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/combine.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -5341,14 +5341,14 @@ } else if (GET_MODE (op0) == compare_mode && op1 == const0_rtx) { - SUBST(SET_SRC (x), op0); + SUBST (SET_SRC (x), op0); src = SET_SRC (x); } - else + /* Otherwise, update the COMPARE if needed. */ + else if (XEXP (src, 0) != op0 || XEXP (src, 1) != op1) { - /* Otherwise, update the COMPARE if needed. */ - SUBST (XEXP (src, 0), op0); - SUBST (XEXP (src, 1), op1); + SUBST (SET_SRC (x), gen_rtx_COMPARE (compare_mode, op0, op1)); + src = SET_SRC (x); } } else Index: gcc/Makefile.in =================================================================== --- gcc/Makefile.in (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/Makefile.in (.../branches/gcc-4_2-branch) (revision 125292) @@ -1839,7 +1839,7 @@ tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \ $(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \ $(TM_H) coretypes.h $(CGRAPH_H) tree-pass.h $(TIMEVAR_H) \ - gt-tree-ssa-structalias.h $(PARAMS_H) + gt-tree-ssa-structalias.h $(PARAMS_H) pointer-set.h tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \ toplev.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \ Index: gcc/tree-ssa-structalias.c =================================================================== --- gcc/tree-ssa-structalias.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/tree-ssa-structalias.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -51,10 +51,11 @@ #include "params.h" #include "tree-ssa-structalias.h" #include "cgraph.h" +#include "pointer-set.h" /* The idea behind this analyzer is to generate set constraints from the program, then solve the resulting constraints in order to generate the - points-to sets. + points-to sets. Set constraints are a way of modeling program analysis problems that involve sets. They consist of an inclusion constraint language, @@ -70,33 +71,33 @@ Also see "Ultra-fast Aliasing Analysis using CLA: A Million Lines of C Code in a Second" by ""Nevin Heintze and Olivier Tardieu" at - http://citeseer.ist.psu.edu/heintze01ultrafast.html + http://citeseer.ist.psu.edu/heintze01ultrafast.html - There are three types of constraint expressions, DEREF, ADDRESSOF, and - SCALAR. Each constraint expression consists of a constraint type, - a variable, and an offset. - + There are three types of real constraint expressions, DEREF, + ADDRESSOF, and SCALAR. Each constraint expression consists + of a constraint type, a variable, and an offset. + SCALAR is a constraint expression type used to represent x, whether it appears on the LHS or the RHS of a statement. DEREF is a constraint expression type used to represent *x, whether - it appears on the LHS or the RHS of a statement. + it appears on the LHS or the RHS of a statement. ADDRESSOF is a constraint expression used to represent &x, whether it appears on the LHS or the RHS of a statement. - + Each pointer variable in the program is assigned an integer id, and each field of a structure variable is assigned an integer id as well. - + Structure variables are linked to their list of fields through a "next field" in each variable that points to the next field in offset - order. - Each variable for a structure field has + order. + Each variable for a structure field has 1. "size", that tells the size in bits of that field. 2. "fullsize, that tells the size in bits of the entire structure. 3. "offset", that tells the offset in bits from the beginning of the structure to this field. - Thus, + Thus, struct f { int a; @@ -110,50 +111,51 @@ foo.b -> id 2, size 32, offset 32, fullsize 64, next NULL bar -> id 3, size 32, offset 0, fullsize 32, next NULL - + In order to solve the system of set constraints, the following is done: 1. Each constraint variable x has a solution set associated with it, Sol(x). - + 2. Constraints are separated into direct, copy, and complex. Direct constraints are ADDRESSOF constraints that require no extra processing, such as P = &Q Copy constraints are those of the form P = Q. - Complex constraints are all the constraints involving dereferences. - + Complex constraints are all the constraints involving dereferences + and offsets (including offsetted copies). + 3. All direct constraints of the form P = &Q are processed, such - that Q is added to Sol(P) + that Q is added to Sol(P) 4. All complex constraints for a given constraint variable are stored in a - linked list attached to that variable's node. + linked list attached to that variable's node. 5. A directed graph is built out of the copy constraints. Each - constraint variable is a node in the graph, and an edge from + constraint variable is a node in the graph, and an edge from Q to P is added for each copy constraint of the form P = Q - + 6. The graph is then walked, and solution sets are propagated along the copy edges, such that an edge from Q to P causes Sol(P) <- Sol(P) union Sol(Q). - + 7. As we visit each node, all complex constraints associated with that node are processed by adding appropriate copy edges to the graph, or the - appropriate variables to the solution set. + appropriate variables to the solution set. 8. The process of walking the graph is iterated until no solution sets change. Prior to walking the graph in steps 6 and 7, We perform static - cycle elimination on the constraint graph, as well + cycle elimination on the constraint graph, as well as off-line variable substitution. - + TODO: Adding offsets to pointer-to-structures can be handled (IE not punted on and turned into anything), but isn't. You can just see what offset inside the pointed-to struct it's going to access. - + TODO: Constant bounded arrays can be handled as if they were structs of the - same number of elements. + same number of elements. TODO: Modeling heap and incoming pointers becomes much better if we add fields to them as we discover them, which we could do. @@ -161,20 +163,29 @@ TODO: We could handle unions, but to be honest, it's probably not worth the pain or slowdown. */ -static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) -htab_t heapvar_for_stmt; +static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t heapvar_for_stmt; /* One variable to represent all non-local accesses. */ tree nonlocal_all; static bool use_field_sensitive = true; static int in_ipa_mode = 0; + +/* Used for predecessor bitmaps. */ static bitmap_obstack predbitmap_obstack; -static bitmap_obstack ptabitmap_obstack; + +/* Used for points-to sets. */ +static bitmap_obstack pta_obstack; + +/* Used for oldsolution members of variables. */ +static bitmap_obstack oldpta_obstack; + +/* Used for per-solver-iteration bitmaps. */ static bitmap_obstack iteration_obstack; static unsigned int create_variable_info_for (tree, const char *); -static void build_constraint_graph (void); +typedef struct constraint_graph *constraint_graph_t; +static void unify_nodes (constraint_graph_t, unsigned int, unsigned int, bool); DEF_VEC_P(constraint_t); DEF_VEC_ALLOC_P(constraint_t,heap); @@ -186,11 +197,13 @@ static struct constraint_stats { unsigned int total_vars; - unsigned int collapsed_vars; + unsigned int nonpointer_vars; unsigned int unified_vars_static; unsigned int unified_vars_dynamic; unsigned int iterations; unsigned int num_edges; + unsigned int num_implicit_edges; + unsigned int points_to_sets_created; } stats; struct variable_info @@ -205,7 +218,7 @@ tree decl; /* Offset of this variable, in bits, from the base variable */ - unsigned HOST_WIDE_INT offset; + unsigned HOST_WIDE_INT offset; /* Size of the variable, in bits. */ unsigned HOST_WIDE_INT size; @@ -216,34 +229,21 @@ /* A link to the variable for the next field in this structure. */ struct variable_info *next; - /* Node in the graph that represents the constraints and points-to - solution for the variable. */ - unsigned int node; - - /* True if the address of this variable is taken. Needed for - variable substitution. */ - unsigned int address_taken:1; - - /* True if this variable is the target of a dereference. Needed for - variable substitution. */ - unsigned int indirect_target:1; - /* True if the variable is directly the target of a dereference. This is used to track which variables are *actually* dereferenced - so we can prune their points to listed. This is equivalent to the - indirect_target flag when no merging of variables happens. */ + so we can prune their points to listed. */ unsigned int directly_dereferenced:1; /* True if this is a variable created by the constraint analysis, such as heap variables and constraints we had to break up. */ unsigned int is_artificial_var:1; - + /* True if this is a special variable whose solution set should not be changed. */ unsigned int is_special_var:1; /* True for variables whose size is not known or variable. */ - unsigned int is_unknown_size_var:1; + unsigned int is_unknown_size_var:1; /* True for variables that have unions somewhere in them. */ unsigned int has_union:1; @@ -254,16 +254,15 @@ /* Points-to set for this variable. */ bitmap solution; + /* Old points-to set for this variable. */ + bitmap oldsolution; + /* Variable ids represented by this node. */ bitmap variables; - /* Vector of complex constraints for this node. Complex - constraints are those involving dereferences. */ - VEC(constraint_t,heap) *complex; - - /* Variable id this was collapsed to due to type unsafety. - This should be unused completely after build_constraint_graph, or - something is broken. */ + /* Variable id this was collapsed to due to type unsafety. This + should be unused completely after build_succ_graph, or something + is broken. */ struct variable_info *collapsed_to; }; typedef struct variable_info *varinfo_t; @@ -277,8 +276,8 @@ DEF_VEC_ALLOC_P(varinfo_t, heap); -/* Table of variable info structures for constraint variables. Indexed directly - by variable info id. */ +/* Table of variable info structures for constraint variables. + Indexed directly by variable info id. */ static VEC(varinfo_t,heap) *varmap; /* Return the varmap element N */ @@ -286,7 +285,7 @@ static inline varinfo_t get_varinfo (unsigned int n) { - return VEC_index(varinfo_t, varmap, n); + return VEC_index (varinfo_t, varmap, n); } /* Return the varmap element N, following the collapsed_to link. */ @@ -294,7 +293,7 @@ static inline varinfo_t get_varinfo_fc (unsigned int n) { - varinfo_t v = VEC_index(varinfo_t, varmap, n); + varinfo_t v = VEC_index (varinfo_t, varmap, n); if (v->collapsed_to) return v->collapsed_to; @@ -331,10 +330,9 @@ /* Variable that represents non-local variables before we expand it to one for each type. */ static unsigned int nonlocal_vars_id; - /* Lookup a heap var for FROM, and return it if we find one. */ -static tree +static tree heapvar_lookup (tree from) { struct tree_map *h, in; @@ -367,25 +365,21 @@ named NAME, and using constraint graph node NODE. */ static varinfo_t -new_var_info (tree t, unsigned int id, const char *name, unsigned int node) +new_var_info (tree t, unsigned int id, const char *name) { varinfo_t ret = pool_alloc (variable_info_pool); ret->id = id; ret->name = name; ret->decl = t; - ret->node = node; - ret->address_taken = false; - ret->indirect_target = false; ret->directly_dereferenced = false; ret->is_artificial_var = false; ret->is_heap_var = false; ret->is_special_var = false; ret->is_unknown_size_var = false; ret->has_union = false; - ret->solution = BITMAP_ALLOC (&ptabitmap_obstack); - ret->variables = BITMAP_ALLOC (&ptabitmap_obstack); - ret->complex = NULL; + ret->solution = BITMAP_ALLOC (&pta_obstack); + ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack); ret->next = NULL; ret->collapsed_to = NULL; return ret; @@ -395,7 +389,7 @@ /* An expression that appears in a constraint. */ -struct constraint_expr +struct constraint_expr { /* Constraint type. */ constraint_expr_type type; @@ -418,7 +412,7 @@ static void do_deref (VEC (ce_s, heap) **); /* Our set constraints are made up of two constraint expressions, one - LHS, and one RHS. + LHS, and one RHS. As described in the introduction, our set constraints each represent an operation between set valued variables. @@ -434,63 +428,98 @@ static VEC(constraint_t,heap) *constraints; static alloc_pool constraint_pool; -/* An edge in the weighted constraint graph. The edges are weighted, - with a bit set in weights meaning their is an edge with that - weight. - We don't keep the src in the edge, because we always know what it - is. */ -struct constraint_edge +DEF_VEC_I(int); +DEF_VEC_ALLOC_I(int, heap); + +/* The constraint graph is represented as an array of bitmaps + containing successor nodes. */ + +struct constraint_graph { - unsigned int dest; - bitmap weights; -}; + /* Size of this graph, which may be different than the number of + nodes in the variable map. */ + unsigned int size; -typedef struct constraint_edge *constraint_edge_t; -static alloc_pool constraint_edge_pool; + /* Explicit successors of each node. */ + bitmap *succs; -/* Return a new constraint edge from SRC to DEST. */ + /* Implicit predecessors of each node (Used for variable + substitution). */ + bitmap *implicit_preds; -static constraint_edge_t -new_constraint_edge (unsigned int dest) -{ - constraint_edge_t ret = pool_alloc (constraint_edge_pool); - ret->dest = dest; - ret->weights = NULL; - return ret; -} + /* Explicit predecessors of each node (Used for variable substitution). */ + bitmap *preds; -DEF_VEC_P(constraint_edge_t); -DEF_VEC_ALLOC_P(constraint_edge_t,heap); + /* Indirect cycle representatives, or -1 if the node has no indirect + cycles. */ + int *indirect_cycles; + /* Representative node for a node. rep[a] == a unless the node has + been unified. */ + unsigned int *rep; -/* The constraint graph is represented internally in two different - ways. The overwhelming majority of edges in the constraint graph - are zero weigh edges, and thus, using a vector of contrainst_edge_t - is a waste of time and memory, since they have no weights. We - simply use a bitmap to store the preds and succs for each node. - The weighted edges are stored as a set of adjacency vectors, one - per variable. succs[x] is the vector of successors for variable x, - and preds[x] is the vector of predecessors for variable x. IOW, - all edges are "forward" edges, which is not like our CFG. So - remember that preds[x]->src == x, and succs[x]->src == x. */ + /* Equivalence class representative for a node. This is used for + variable substitution. */ + int *eq_rep; -struct constraint_graph -{ - bitmap *zero_weight_succs; - bitmap *zero_weight_preds; - VEC(constraint_edge_t,heap) **succs; - VEC(constraint_edge_t,heap) **preds; + /* Label for each node, used during variable substitution. */ + unsigned int *label; + + /* Bitmap of nodes where the bit is set if the node is a direct + node. Used for variable substitution. */ + sbitmap direct_nodes; + + /* Vector of complex constraints for each graph node. Complex + constraints are those involving dereferences or offsets that are + not 0. */ + VEC(constraint_t,heap) **complex; }; -typedef struct constraint_graph *constraint_graph_t; - static constraint_graph_t graph; -static int graph_size; +/* During variable substitution and the offline version of indirect + cycle finding, we create nodes to represent dereferences and + address taken constraints. These represent where these start and + end. */ +#define FIRST_REF_NODE (VEC_length (varinfo_t, varmap)) +#define LAST_REF_NODE (FIRST_REF_NODE + (FIRST_REF_NODE - 1)) +#define FIRST_ADDR_NODE (LAST_REF_NODE + 1) + +/* Return the representative node for NODE, if NODE has been unioned + with another NODE. + This function performs path compression along the way to finding + the representative. */ + +static unsigned int +find (unsigned int node) +{ + gcc_assert (node < graph->size); + if (graph->rep[node] != node) + return graph->rep[node] = find (graph->rep[node]); + return node; +} + +/* Union the TO and FROM nodes to the TO nodes. + Note that at some point in the future, we may want to do + union-by-rank, in which case we are going to have to return the + node we unified to. */ + +static bool +unite (unsigned int to, unsigned int from) +{ + gcc_assert (to < graph->size && from < graph->size); + if (to != from && graph->rep[from] != to) + { + graph->rep[from] = to; + return true; + } + return false; +} + /* Create a new constraint consisting of LHS and RHS expressions. */ -static constraint_t +static constraint_t new_constraint (const struct constraint_expr lhs, const struct constraint_expr rhs) { @@ -508,7 +537,7 @@ if (c->lhs.type == ADDRESSOF) fprintf (file, "&"); else if (c->lhs.type == DEREF) - fprintf (file, "*"); + fprintf (file, "*"); fprintf (file, "%s", get_varinfo_fc (c->lhs.var)->name); if (c->lhs.offset != 0) fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->lhs.offset); @@ -550,23 +579,24 @@ dump_constraints (stderr); } -/* SOLVER FUNCTIONS +/* SOLVER FUNCTIONS The solver is a simple worklist solver, that works on the following algorithm: - - sbitmap changed_nodes = all ones; - changed_count = number of nodes; - For each node that was already collapsed: - changed_count--; + sbitmap changed_nodes = all zeroes; + changed_count = 0; + For each node that is not already collapsed: + changed_count++; + set bit in changed nodes + while (changed_count > 0) { compute topological ordering for constraint graph - + find and collapse cycles in the constraint graph (updating changed if necessary) - + for each node (n) in the graph in topological order: changed_count--; @@ -619,11 +649,11 @@ } /* Return true if two constraints A and B are equal. */ - + static bool constraint_equal (struct constraint a, struct constraint b) { - return constraint_expr_equal (a.lhs, b.lhs) + return constraint_expr_equal (a.lhs, b.lhs) && constraint_expr_equal (a.rhs, b.rhs); } @@ -634,7 +664,7 @@ constraint_vec_find (VEC(constraint_t,heap) *vec, struct constraint lookfor) { - unsigned int place; + unsigned int place; constraint_t found; if (vec == NULL) @@ -684,7 +714,7 @@ /* If this is a properly sized variable, only add offset if it's less than end. Otherwise, it is globbed to a single variable. */ - + if ((get_varinfo (i)->offset + offset) < get_varinfo (i)->fullsize) { unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset + offset; @@ -693,15 +723,15 @@ continue; bitmap_set_bit (result, v->id); } - else if (get_varinfo (i)->is_artificial_var + else if (get_varinfo (i)->is_artificial_var || get_varinfo (i)->has_union || get_varinfo (i)->is_unknown_size_var) { bitmap_set_bit (result, i); } } - - bitmap_copy (set, result); + + bitmap_copy (set, result); BITMAP_FREE (result); } @@ -727,397 +757,149 @@ } } -/* Insert constraint C into the list of complex constraints for VAR. */ +/* Insert constraint C into the list of complex constraints for graph + node VAR. */ static void -insert_into_complex (unsigned int var, constraint_t c) +insert_into_complex (constraint_graph_t graph, + unsigned int var, constraint_t c) { - varinfo_t vi = get_varinfo (var); - unsigned int place = VEC_lower_bound (constraint_t, vi->complex, c, + VEC (constraint_t, heap) *complex = graph->complex[var]; + unsigned int place = VEC_lower_bound (constraint_t, complex, c, constraint_less); - VEC_safe_insert (constraint_t, heap, vi->complex, place, c); -} - -/* Compare two constraint edges A and B, return true if they are equal. */ - -static bool -constraint_edge_equal (struct constraint_edge a, struct constraint_edge b) -{ - return a.dest == b.dest; + /* Only insert constraints that do not already exist. */ + if (place >= VEC_length (constraint_t, complex) + || !constraint_equal (*c, *VEC_index (constraint_t, complex, place))) + VEC_safe_insert (constraint_t, heap, graph->complex[var], place, c); } -/* Compare two constraint edges, return true if A is less than B */ -static bool -constraint_edge_less (const constraint_edge_t a, const constraint_edge_t b) -{ - if (a->dest < b->dest) - return true; - return false; -} - -/* Find the constraint edge that matches LOOKFOR, in VEC. - Return the edge, if found, NULL otherwise. */ - -static constraint_edge_t -constraint_edge_vec_find (VEC(constraint_edge_t,heap) *vec, - struct constraint_edge lookfor) -{ - unsigned int place; - constraint_edge_t edge = NULL; - - place = VEC_lower_bound (constraint_edge_t, vec, &lookfor, - constraint_edge_less); - if (place >= VEC_length (constraint_edge_t, vec)) - return NULL; - edge = VEC_index (constraint_edge_t, vec, place); - if (!constraint_edge_equal (*edge, lookfor)) - return NULL; - return edge; -} - /* Condense two variable nodes into a single variable node, by moving all associated info from SRC to TO. */ -static void -condense_varmap_nodes (unsigned int to, unsigned int src) +static void +merge_node_constraints (constraint_graph_t graph, unsigned int to, + unsigned int from) { - varinfo_t tovi = get_varinfo (to); - varinfo_t srcvi = get_varinfo (src); unsigned int i; constraint_t c; - bitmap_iterator bi; - - /* the src node, and all its variables, are now the to node. */ - srcvi->node = to; - EXECUTE_IF_SET_IN_BITMAP (srcvi->variables, 0, i, bi) - get_varinfo (i)->node = to; - - /* Merge the src node variables and the to node variables. */ - bitmap_set_bit (tovi->variables, src); - bitmap_ior_into (tovi->variables, srcvi->variables); - bitmap_clear (srcvi->variables); - + + gcc_assert (find (from) == to); + /* Move all complex constraints from src node into to node */ - for (i = 0; VEC_iterate (constraint_t, srcvi->complex, i, c); i++) + for (i = 0; VEC_iterate (constraint_t, graph->complex[from], i, c); i++) { /* In complex constraints for node src, we may have either - a = *src, and *src = a. */ - + a = *src, and *src = a, or an offseted constraint which are + always added to the rhs node's constraints. */ + if (c->rhs.type == DEREF) c->rhs.var = to; + else if (c->lhs.type == DEREF) + c->lhs.var = to; else - c->lhs.var = to; + c->rhs.var = to; } - constraint_set_union (&tovi->complex, &srcvi->complex); - VEC_free (constraint_t, heap, srcvi->complex); - srcvi->complex = NULL; + constraint_set_union (&graph->complex[to], &graph->complex[from]); + VEC_free (constraint_t, heap, graph->complex[from]); + graph->complex[from] = NULL; } -/* Erase an edge from SRC to SRC from GRAPH. This routine only - handles self-edges (e.g. an edge from a to a). */ -static void -erase_graph_self_edge (constraint_graph_t graph, unsigned int src) -{ - VEC(constraint_edge_t,heap) *predvec = graph->preds[src]; - VEC(constraint_edge_t,heap) *succvec = graph->succs[src]; - struct constraint_edge edge; - unsigned int place; - - edge.dest = src; - - /* Remove from the successors. */ - place = VEC_lower_bound (constraint_edge_t, succvec, &edge, - constraint_edge_less); - - /* Make sure we found the edge. */ -#ifdef ENABLE_CHECKING - { - constraint_edge_t tmp = VEC_index (constraint_edge_t, succvec, place); - gcc_assert (constraint_edge_equal (*tmp, edge)); - } -#endif - VEC_ordered_remove (constraint_edge_t, succvec, place); - - /* Remove from the predecessors. */ - place = VEC_lower_bound (constraint_edge_t, predvec, &edge, - constraint_edge_less); - - /* Make sure we found the edge. */ -#ifdef ENABLE_CHECKING - { - constraint_edge_t tmp = VEC_index (constraint_edge_t, predvec, place); - gcc_assert (constraint_edge_equal (*tmp, edge)); - } -#endif - VEC_ordered_remove (constraint_edge_t, predvec, place); -} - /* Remove edges involving NODE from GRAPH. */ static void clear_edges_for_node (constraint_graph_t graph, unsigned int node) { - VEC(constraint_edge_t,heap) *succvec = graph->succs[node]; - VEC(constraint_edge_t,heap) *predvec = graph->preds[node]; - bitmap_iterator bi; - unsigned int j; - constraint_edge_t c = NULL; - int i; - - /* Walk the successors, erase the associated preds. */ - - EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_succs[node], 0, j, bi) - if (j != node) - bitmap_clear_bit (graph->zero_weight_preds[j], node); - - for (i = 0; VEC_iterate (constraint_edge_t, succvec, i, c); i++) - if (c->dest != node) - { - unsigned int place; - struct constraint_edge lookfor; - constraint_edge_t result; - - lookfor.dest = node; - place = VEC_lower_bound (constraint_edge_t, graph->preds[c->dest], - &lookfor, constraint_edge_less); - result = VEC_ordered_remove (constraint_edge_t, - graph->preds[c->dest], place); - pool_free (constraint_edge_pool, result); - } - - /* Walk the preds, erase the associated succs. */ - - EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_preds[node], 0, j, bi) - if (j != node) - bitmap_clear_bit (graph->zero_weight_succs[j], node); - - for (i =0; VEC_iterate (constraint_edge_t, predvec, i, c); i++) - if (c->dest != node) - { - unsigned int place; - struct constraint_edge lookfor; - constraint_edge_t result; - - lookfor.dest = node; - place = VEC_lower_bound (constraint_edge_t, graph->succs[c->dest], - &lookfor, constraint_edge_less); - result = VEC_ordered_remove (constraint_edge_t, - graph->succs[c->dest], place); - pool_free (constraint_edge_pool, result); - - } - - if (graph->zero_weight_preds[node]) - { - BITMAP_FREE (graph->zero_weight_preds[node]); - graph->zero_weight_preds[node] = NULL; - } - - if (graph->zero_weight_succs[node]) - { - BITMAP_FREE (graph->zero_weight_succs[node]); - graph->zero_weight_succs[node] = NULL; - } - - VEC_free (constraint_edge_t, heap, graph->preds[node]); - VEC_free (constraint_edge_t, heap, graph->succs[node]); - graph->preds[node] = NULL; - graph->succs[node] = NULL; + if (graph->succs[node]) + BITMAP_FREE (graph->succs[node]); } -static bool edge_added = false; - -/* Add edge (src, dest) to the graph. */ - -static bool -add_graph_edge (constraint_graph_t graph, unsigned int src, unsigned int dest) -{ - unsigned int place; - VEC(constraint_edge_t,heap) *vec; - struct constraint_edge newe; - newe.dest = dest; - - vec = graph->preds[src]; - place = VEC_lower_bound (constraint_edge_t, vec, &newe, - constraint_edge_less); - if (place == VEC_length (constraint_edge_t, vec) - || VEC_index (constraint_edge_t, vec, place)->dest != dest) - { - constraint_edge_t edge = new_constraint_edge (dest); - - VEC_safe_insert (constraint_edge_t, heap, graph->preds[src], - place, edge); - edge = new_constraint_edge (src); - - place = VEC_lower_bound (constraint_edge_t, graph->succs[dest], - edge, constraint_edge_less); - VEC_safe_insert (constraint_edge_t, heap, graph->succs[dest], - place, edge); - edge_added = true; - stats.num_edges++; - return true; - } - else - return false; -} - - -/* Return the bitmap representing the weights of edge (SRC, DEST). */ - -static bitmap * -get_graph_weights (constraint_graph_t graph, unsigned int src, - unsigned int dest) -{ - constraint_edge_t edge; - VEC(constraint_edge_t,heap) *vec; - struct constraint_edge lookfor; - - lookfor.dest = dest; - - vec = graph->preds[src]; - edge = constraint_edge_vec_find (vec, lookfor); - gcc_assert (edge != NULL); - return &edge->weights; -} - -/* Allocate graph weight bitmap for the edges associated with SRC and - DEST in GRAPH. Both the pred and the succ edges share a single - bitmap, so we need to set both edges to that bitmap. */ - -static bitmap -allocate_graph_weights (constraint_graph_t graph, unsigned int src, - unsigned int dest) -{ - bitmap result; - constraint_edge_t edge; - VEC(constraint_edge_t,heap) *vec; - struct constraint_edge lookfor; - - result = BITMAP_ALLOC (&ptabitmap_obstack); - - /* Set the pred weight. */ - lookfor.dest = dest; - vec = graph->preds[src]; - edge = constraint_edge_vec_find (vec, lookfor); - gcc_assert (edge != NULL); - edge->weights = result; - - /* Set the succ weight. */ - lookfor.dest = src; - vec = graph->succs[dest]; - edge = constraint_edge_vec_find (vec, lookfor); - gcc_assert (edge != NULL); - edge->weights = result; - - return result; -} - - /* Merge GRAPH nodes FROM and TO into node TO. */ static void -merge_graph_nodes (constraint_graph_t graph, unsigned int to, +merge_graph_nodes (constraint_graph_t graph, unsigned int to, unsigned int from) { - VEC(constraint_edge_t,heap) *succvec = graph->succs[from]; - VEC(constraint_edge_t,heap) *predvec = graph->preds[from]; - int i; - constraint_edge_t c; - unsigned int j; - bitmap_iterator bi; - - /* Merge all the zero weighted predecessor edges. */ - if (graph->zero_weight_preds[from]) + if (graph->indirect_cycles[from] != -1) { - if (!graph->zero_weight_preds[to]) - graph->zero_weight_preds[to] = BITMAP_ALLOC (&predbitmap_obstack); - - EXECUTE_IF_SET_IN_BITMAP (graph->zero_weight_preds[from], 0, j, bi) + /* If we have indirect cycles with the from node, and we have + none on the to node, the to node has indirect cycles from the + from node now that they are unified. + If indirect cycles exist on both, unify the nodes that they + are in a cycle with, since we know they are in a cycle with + each other. */ + if (graph->indirect_cycles[to] == -1) { - if (j != to) - { - bitmap_clear_bit (graph->zero_weight_succs[j], from); - bitmap_set_bit (graph->zero_weight_succs[j], to); - } + graph->indirect_cycles[to] = graph->indirect_cycles[from]; } - bitmap_ior_into (graph->zero_weight_preds[to], - graph->zero_weight_preds[from]); - } + else + { + unsigned int tonode = find (graph->indirect_cycles[to]); + unsigned int fromnode = find (graph->indirect_cycles[from]); - /* Merge all the zero weighted successor edges. */ - if (graph->zero_weight_succs[from]) - { - if (!graph->zero_weight_succs[to]) - graph->zero_weight_succs[to] = BITMAP_ALLOC (&ptabitmap_obstack); - EXECUTE_IF_SET_IN_BITMAP (graph->zero_weight_succs[from], 0, j, bi) - { - bitmap_clear_bit (graph->zero_weight_preds[j], from); - bitmap_set_bit (graph->zero_weight_preds[j], to); + if (unite (tonode, fromnode)) + unify_nodes (graph, tonode, fromnode, true); } - bitmap_ior_into (graph->zero_weight_succs[to], - graph->zero_weight_succs[from]); } - /* Merge all the nonzero weighted predecessor edges. */ - for (i = 0; VEC_iterate (constraint_edge_t, predvec, i, c); i++) + /* Merge all the successor edges. */ + if (graph->succs[from]) { - unsigned int d = c->dest; - bitmap temp; - bitmap *weights; + if (!graph->succs[to]) + graph->succs[to] = BITMAP_ALLOC (&pta_obstack); + bitmap_ior_into (graph->succs[to], + graph->succs[from]); + } - if (c->dest == from) - d = to; + clear_edges_for_node (graph, from); +} - add_graph_edge (graph, to, d); - temp = *(get_graph_weights (graph, from, c->dest)); - if (temp) - { - weights = get_graph_weights (graph, to, d); - if (!*weights) - *weights = allocate_graph_weights (graph, to, d); - - bitmap_ior_into (*weights, temp); - } - - } - - /* Merge all the nonzero weighted successor edges. */ - for (i = 0; VEC_iterate (constraint_edge_t, succvec, i, c); i++) - { - unsigned int d = c->dest; - bitmap temp; - bitmap *weights; +/* Add an indirect graph edge to GRAPH, going from TO to FROM if + it doesn't exist in the graph already. */ - if (c->dest == from) - d = to; +static void +add_implicit_graph_edge (constraint_graph_t graph, unsigned int to, + unsigned int from) +{ + if (to == from) + return; - add_graph_edge (graph, d, to); + if (!graph->implicit_preds[to]) + graph->implicit_preds[to] = BITMAP_ALLOC (&predbitmap_obstack); - temp = *(get_graph_weights (graph, c->dest, from)); - if (temp) - { - weights = get_graph_weights (graph, d, to); - if (!*weights) - *weights = allocate_graph_weights (graph, d, to); - bitmap_ior_into (*weights, temp); - } + if (!bitmap_bit_p (graph->implicit_preds[to], from)) + { + stats.num_implicit_edges++; + bitmap_set_bit (graph->implicit_preds[to], from); } - clear_edges_for_node (graph, from); } -/* Add a graph edge to GRAPH, going from TO to FROM, with WEIGHT, if +/* Add a predecessor graph edge to GRAPH, going from TO to FROM if it doesn't exist in the graph already. Return false if the edge already existed, true otherwise. */ +static void +add_pred_graph_edge (constraint_graph_t graph, unsigned int to, + unsigned int from) +{ + if (!graph->preds[to]) + graph->preds[to] = BITMAP_ALLOC (&predbitmap_obstack); + if (!bitmap_bit_p (graph->preds[to], from)) + bitmap_set_bit (graph->preds[to], from); +} + +/* Add a graph edge to GRAPH, going from FROM to TO if + it doesn't exist in the graph already. + Return false if the edge already existed, true otherwise. */ + static bool -int_add_graph_edge (constraint_graph_t graph, unsigned int to, - unsigned int from, unsigned HOST_WIDE_INT weight) +add_graph_edge (constraint_graph_t graph, unsigned int to, + unsigned int from) { - if (to == from && weight == 0) + if (to == from) { return false; } @@ -1125,41 +907,15 @@ { bool r = false; - if (weight == 0) + if (!graph->succs[from]) + graph->succs[from] = BITMAP_ALLOC (&pta_obstack); + if (!bitmap_bit_p (graph->succs[from], to)) { - if (!graph->zero_weight_preds[to]) - graph->zero_weight_preds[to] = BITMAP_ALLOC (&predbitmap_obstack); - if (!graph->zero_weight_succs[from]) - graph->zero_weight_succs[from] = BITMAP_ALLOC (&ptabitmap_obstack); - if (!bitmap_bit_p (graph->zero_weight_succs[from], to)) - { - edge_added = true; - r = true; - stats.num_edges++; - bitmap_set_bit (graph->zero_weight_preds[to], from); - bitmap_set_bit (graph->zero_weight_succs[from], to); - } + r = true; + if (to < FIRST_REF_NODE && from < FIRST_REF_NODE) + stats.num_edges++; + bitmap_set_bit (graph->succs[from], to); } - else - { - bitmap *weights; - - r = add_graph_edge (graph, to, from); - weights = get_graph_weights (graph, to, from); - - if (!*weights) - { - r = true; - *weights = allocate_graph_weights (graph, to, from); - bitmap_set_bit (*weights, weight); - } - else - { - r |= !bitmap_bit_p (*weights, weight); - bitmap_set_bit (*weights, weight); - } - } - return r; } } @@ -1168,46 +924,51 @@ /* Return true if {DEST.SRC} is an existing graph edge in GRAPH. */ static bool -valid_graph_edge (constraint_graph_t graph, unsigned int src, +valid_graph_edge (constraint_graph_t graph, unsigned int src, unsigned int dest) { - struct constraint_edge lookfor; - lookfor.dest = src; - - return (graph->zero_weight_succs[dest] - && bitmap_bit_p (graph->zero_weight_succs[dest], src)) - || constraint_edge_vec_find (graph->succs[dest], lookfor) != NULL; + return (graph->succs[dest] + && bitmap_bit_p (graph->succs[dest], src)); } -/* Return true if {DEST, SRC} is an existing weighted graph edge (IE has - a weight other than 0) in GRAPH. */ -static bool -valid_weighted_graph_edge (constraint_graph_t graph, unsigned int src, - unsigned int dest) -{ - struct constraint_edge lookfor; - lookfor.dest = src; - - return graph->preds[src] - && constraint_edge_vec_find (graph->succs[dest], lookfor) != NULL; -} +/* Build the constraint graph, adding only predecessor edges right now. */ - -/* Build the constraint graph. */ - static void -build_constraint_graph (void) +build_pred_graph (void) { - int i = 0; + int i; constraint_t c; + unsigned int j; graph = XNEW (struct constraint_graph); - graph_size = VEC_length (varinfo_t, varmap) + 1; - graph->succs = XCNEWVEC (VEC(constraint_edge_t,heap) *, graph_size); - graph->preds = XCNEWVEC (VEC(constraint_edge_t,heap) *, graph_size); - graph->zero_weight_succs = XCNEWVEC (bitmap, graph_size); - graph->zero_weight_preds = XCNEWVEC (bitmap, graph_size); + graph->size = (VEC_length (varinfo_t, varmap)) * 3; + graph->succs = XCNEWVEC (bitmap, graph->size); + graph->implicit_preds = XCNEWVEC (bitmap, graph->size); + graph->preds = XCNEWVEC (bitmap, graph->size); + graph->indirect_cycles = XNEWVEC (int, VEC_length (varinfo_t, varmap)); + graph->label = XCNEWVEC (unsigned int, graph->size); + graph->rep = XNEWVEC (unsigned int, graph->size); + graph->eq_rep = XNEWVEC (int, graph->size); + graph->complex = XCNEWVEC (VEC(constraint_t, heap) *, + VEC_length (varinfo_t, varmap)); + graph->direct_nodes = sbitmap_alloc (graph->size); + sbitmap_zero (graph->direct_nodes); + for (j = 0; j < FIRST_REF_NODE; j++) + { + if (!get_varinfo (j)->is_special_var) + SET_BIT (graph->direct_nodes, j); + } + + for (j = 0; j < graph->size; j++) + { + graph->rep[j] = j; + graph->eq_rep[j] = -1; + } + + for (j = 0; j < VEC_length (varinfo_t, varmap); j++) + graph->indirect_cycles[j] = -1; + for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++) { struct constraint_expr lhs = c->lhs; @@ -1217,31 +978,92 @@ if (lhs.type == DEREF) { - /* *x = y or *x = &y (complex) */ - if (rhs.type == ADDRESSOF || rhsvar > anything_id) - insert_into_complex (lhsvar, c); + /* *x = y. */ + if (rhs.offset == 0 && lhs.offset == 0 && rhs.type == SCALAR) + add_pred_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar); + if (rhs.type == ADDRESSOF) + RESET_BIT (graph->direct_nodes, rhsvar); } else if (rhs.type == DEREF) { - /* !special var= *y */ - if (!(get_varinfo (lhsvar)->is_special_var)) - insert_into_complex (rhsvar, c); + /* x = *y */ + if (rhs.offset == 0 && lhs.offset == 0 && lhs.type == SCALAR) + add_pred_graph_edge (graph, lhsvar, FIRST_REF_NODE + rhsvar); + else + RESET_BIT (graph->direct_nodes, lhsvar); } else if (rhs.type == ADDRESSOF) { /* x = &y */ + add_pred_graph_edge (graph, lhsvar, FIRST_ADDR_NODE + rhsvar); + /* Implicitly, *x = y */ + add_implicit_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar); + + RESET_BIT (graph->direct_nodes, rhsvar); + } + else if (lhsvar > anything_id + && lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0) + { + /* x = y */ + add_pred_graph_edge (graph, lhsvar, rhsvar); + /* Implicitly, *x = *y */ + add_implicit_graph_edge (graph, FIRST_REF_NODE + lhsvar, + FIRST_REF_NODE + rhsvar); + } + else if (lhs.offset != 0 || rhs.offset != 0) + { + if (rhs.offset != 0) + RESET_BIT (graph->direct_nodes, lhs.var); + if (lhs.offset != 0) + RESET_BIT (graph->direct_nodes, rhs.var); + } + } +} + +/* Build the constraint graph, adding successor edges. */ + +static void +build_succ_graph (void) +{ + int i; + constraint_t c; + + for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++) + { + struct constraint_expr lhs; + struct constraint_expr rhs; + unsigned int lhsvar; + unsigned int rhsvar; + + if (!c) + continue; + + lhs = c->lhs; + rhs = c->rhs; + lhsvar = find (get_varinfo_fc (lhs.var)->id); + rhsvar = find (get_varinfo_fc (rhs.var)->id); + + if (lhs.type == DEREF) + { + if (rhs.offset == 0 && lhs.offset == 0 && rhs.type == SCALAR) + add_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar); + } + else if (rhs.type == DEREF) + { + if (rhs.offset == 0 && lhs.offset == 0 && lhs.type == SCALAR) + add_graph_edge (graph, lhsvar, FIRST_REF_NODE + rhsvar); + } + else if (rhs.type == ADDRESSOF) + { + /* x = &y */ + gcc_assert (find (get_varinfo_fc (rhs.var)->id) + == get_varinfo_fc (rhs.var)->id); bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar); } - else if (lhsvar > anything_id) + else if (lhsvar > anything_id + && lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0) { - /* Ignore 0 weighted self edges, as they can't possibly contribute - anything */ - if (lhsvar != rhsvar || rhs.offset != 0 || lhs.offset != 0) - { - /* x = y (simple) */ - int_add_graph_edge (graph, lhs.var, rhs.var, rhs.offset); - } - + add_graph_edge (graph, lhsvar, rhsvar); } } } @@ -1260,20 +1082,20 @@ struct scc_info { sbitmap visited; - sbitmap in_component; + sbitmap roots; + unsigned int *dfs; + unsigned int *node_mapping; int current_index; - unsigned int *visited_index; VEC(unsigned,heap) *scc_stack; - VEC(unsigned,heap) *unification_queue; }; /* Recursive routine to find strongly connected components in GRAPH. SI is the SCC info to store the information in, and N is the id of current graph node we are processing. - + This is Tarjan's strongly connected component finding algorithm, as - modified by Nuutila to keep only non-root nodes on the stack. + modified by Nuutila to keep only non-root nodes on the stack. The algorithm can be found in "On finding the strongly connected connected components in a directed graph" by Esko Nuutila and Eljas Soisalon-Soininen, in Information Processing Letters volume 49, @@ -1284,188 +1106,144 @@ { unsigned int i; bitmap_iterator bi; + unsigned int my_dfs; - gcc_assert (get_varinfo (n)->node == n); SET_BIT (si->visited, n); - RESET_BIT (si->in_component, n); - si->visited_index[n] = si->current_index ++; - + si->dfs[n] = si->current_index ++; + my_dfs = si->dfs[n]; + /* Visit all the successors. */ - EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_succs[n], 0, i, bi) + EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[n], 0, i, bi) { - unsigned int w = i; + unsigned int w; + + if (i > LAST_REF_NODE) + break; + + w = find (i); + if (TEST_BIT (si->roots, w)) + continue; + if (!TEST_BIT (si->visited, w)) scc_visit (graph, si, w); - if (!TEST_BIT (si->in_component, w)) - { - unsigned int t = get_varinfo (w)->node; - unsigned int nnode = get_varinfo (n)->node; - if (si->visited_index[t] < si->visited_index[nnode]) - get_varinfo (n)->node = t; - } + { + unsigned int t = find (w); + unsigned int nnode = find (n); + gcc_assert (nnode == n); + + if (si->dfs[t] < si->dfs[nnode]) + si->dfs[n] = si->dfs[t]; + } } - + /* See if any components have been identified. */ - if (get_varinfo (n)->node == n) + if (si->dfs[n] == my_dfs) { - unsigned int t = si->visited_index[n]; - SET_BIT (si->in_component, n); - while (VEC_length (unsigned, si->scc_stack) != 0 - && t < si->visited_index[VEC_last (unsigned, si->scc_stack)]) + if (VEC_length (unsigned, si->scc_stack) > 0 + && si->dfs[VEC_last (unsigned, si->scc_stack)] >= my_dfs) { - unsigned int w = VEC_pop (unsigned, si->scc_stack); - get_varinfo (w)->node = n; - SET_BIT (si->in_component, w); - /* Mark this node for collapsing. */ - VEC_safe_push (unsigned, heap, si->unification_queue, w); - } - } - else - VEC_safe_push (unsigned, heap, si->scc_stack, n); -} + bitmap scc = BITMAP_ALLOC (NULL); + bool have_ref_node = n >= FIRST_REF_NODE; + unsigned int lowest_node; + bitmap_iterator bi; + bitmap_set_bit (scc, n); -/* Collapse two variables into one variable. */ + while (VEC_length (unsigned, si->scc_stack) != 0 + && si->dfs[VEC_last (unsigned, si->scc_stack)] >= my_dfs) + { + unsigned int w = VEC_pop (unsigned, si->scc_stack); -static void -collapse_nodes (constraint_graph_t graph, unsigned int to, unsigned int from) -{ - bitmap tosol, fromsol; + bitmap_set_bit (scc, w); + if (w >= FIRST_REF_NODE) + have_ref_node = true; + } - condense_varmap_nodes (to, from); - tosol = get_varinfo (to)->solution; - fromsol = get_varinfo (from)->solution; - bitmap_ior_into (tosol, fromsol); - merge_graph_nodes (graph, to, from); - - if (valid_graph_edge (graph, to, to)) - { - if (graph->zero_weight_preds[to]) - { - bitmap_clear_bit (graph->zero_weight_preds[to], to); - bitmap_clear_bit (graph->zero_weight_succs[to], to); + lowest_node = bitmap_first_set_bit (scc); + gcc_assert (lowest_node < FIRST_REF_NODE); + EXECUTE_IF_SET_IN_BITMAP (scc, 0, i, bi) + { + if (i < FIRST_REF_NODE) + { + /* Mark this node for collapsing. */ + if (unite (lowest_node, i)) + unify_nodes (graph, lowest_node, i, false); + } + else + { + unite (lowest_node, i); + graph->indirect_cycles[i - FIRST_REF_NODE] = lowest_node; + } + } } - if (valid_weighted_graph_edge (graph, to, to)) - { - bitmap weights = *(get_graph_weights (graph, to, to)); - if (!weights || bitmap_empty_p (weights)) - erase_graph_self_edge (graph, to); - } + SET_BIT (si->roots, n); } - BITMAP_FREE (fromsol); - get_varinfo (to)->address_taken |= get_varinfo (from)->address_taken; - get_varinfo (to)->indirect_target |= get_varinfo (from)->indirect_target; + else + VEC_safe_push (unsigned, heap, si->scc_stack, n); } +/* Unify node FROM into node TO, updating the changed count if + necessary when UPDATE_CHANGED is true. */ -/* Unify nodes in GRAPH that we have found to be part of a cycle. - SI is the Strongly Connected Components information structure that tells us - what components to unify. - UPDATE_CHANGED should be set to true if the changed sbitmap and changed - count should be updated to reflect the unification. */ - static void -process_unification_queue (constraint_graph_t graph, struct scc_info *si, - bool update_changed) +unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from, + bool update_changed) { - size_t i = 0; - bitmap tmp = BITMAP_ALLOC (update_changed ? &iteration_obstack : NULL); - bitmap_clear (tmp); - /* We proceed as follows: + gcc_assert (to != from && find (to) == to); + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Unifying %s to %s\n", + get_varinfo (from)->name, + get_varinfo (to)->name); - For each component in the queue (components are delineated by - when current_queue_element->node != next_queue_element->node): + if (update_changed) + stats.unified_vars_dynamic++; + else + stats.unified_vars_static++; - rep = representative node for component + merge_graph_nodes (graph, to, from); + merge_node_constraints (graph, to, from); - For each node (tounify) to be unified in the component, - merge the solution for tounify into tmp bitmap - - clear solution for tounify - - merge edges from tounify into rep - - merge complex constraints from tounify into rep - - update changed count to note that tounify will never change - again - - Merge tmp into solution for rep, marking rep changed if this - changed rep's solution. - - Delete any 0 weighted self-edges we now have for rep. */ - while (i != VEC_length (unsigned, si->unification_queue)) + if (update_changed && TEST_BIT (changed, from)) { - unsigned int tounify = VEC_index (unsigned, si->unification_queue, i); - unsigned int n = get_varinfo (tounify)->node; - - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Unifying %s to %s\n", - get_varinfo (tounify)->name, - get_varinfo (n)->name); - if (update_changed) - stats.unified_vars_dynamic++; + RESET_BIT (changed, from); + if (!TEST_BIT (changed, to)) + SET_BIT (changed, to); else - stats.unified_vars_static++; - bitmap_ior_into (tmp, get_varinfo (tounify)->solution); - merge_graph_nodes (graph, n, tounify); - condense_varmap_nodes (n, tounify); - - if (update_changed && TEST_BIT (changed, tounify)) { - RESET_BIT (changed, tounify); - if (!TEST_BIT (changed, n)) - SET_BIT (changed, n); - else - { - gcc_assert (changed_count > 0); - changed_count--; - } + gcc_assert (changed_count > 0); + changed_count--; } + } - bitmap_clear (get_varinfo (tounify)->solution); - ++i; - - /* If we've either finished processing the entire queue, or - finished processing all nodes for component n, update the solution for - n. */ - if (i == VEC_length (unsigned, si->unification_queue) - || get_varinfo (VEC_index (unsigned, si->unification_queue, i))->node != n) + /* If the solution changes because of the merging, we need to mark + the variable as changed. */ + if (bitmap_ior_into (get_varinfo (to)->solution, + get_varinfo (from)->solution)) + { + if (update_changed && !TEST_BIT (changed, to)) { - /* If the solution changes because of the merging, we need to mark - the variable as changed. */ - if (bitmap_ior_into (get_varinfo (n)->solution, tmp)) - { - if (update_changed && !TEST_BIT (changed, n)) - { - SET_BIT (changed, n); - changed_count++; - } - } - bitmap_clear (tmp); - - if (valid_graph_edge (graph, n, n)) - { - if (graph->zero_weight_succs[n]) - { - if (graph->zero_weight_preds[n]) - bitmap_clear_bit (graph->zero_weight_preds[n], n); - bitmap_clear_bit (graph->zero_weight_succs[n], n); - } - if (valid_weighted_graph_edge (graph, n, n)) - { - bitmap weights = *(get_graph_weights (graph, n, n)); - if (!weights || bitmap_empty_p (weights)) - erase_graph_self_edge (graph, n); - } - } + SET_BIT (changed, to); + changed_count++; } } - BITMAP_FREE (tmp); + + BITMAP_FREE (get_varinfo (from)->solution); + BITMAP_FREE (get_varinfo (from)->oldsolution); + + if (stats.iterations > 0) + { + BITMAP_FREE (get_varinfo (to)->oldsolution); + get_varinfo (to)->oldsolution = BITMAP_ALLOC (&oldpta_obstack); + } + + if (valid_graph_edge (graph, to, to)) + { + if (graph->succs[to]) + bitmap_clear_bit (graph->succs[to], to); + } } - /* Information needed to compute the topological ordering of a graph. */ struct topo_info @@ -1509,37 +1287,24 @@ topo_visit (constraint_graph_t graph, struct topo_info *ti, unsigned int n) { - VEC(constraint_edge_t,heap) *succs = graph->succs[n]; - bitmap temp; bitmap_iterator bi; - constraint_edge_t c; - int i; unsigned int j; SET_BIT (ti->visited, n); - if (VEC_length (constraint_edge_t, succs) != 0) - { - temp = BITMAP_ALLOC (&iteration_obstack); - if (graph->zero_weight_succs[n]) - bitmap_ior_into (temp, graph->zero_weight_succs[n]); - for (i = 0; VEC_iterate (constraint_edge_t, succs, i, c); i++) - bitmap_set_bit (temp, c->dest); - } - else - temp = graph->zero_weight_succs[n]; - if (temp) - EXECUTE_IF_SET_IN_BITMAP (temp, 0, j, bi) + if (graph->succs[n]) + EXECUTE_IF_SET_IN_BITMAP (graph->succs[n], 0, j, bi) { if (!TEST_BIT (ti->visited, j)) topo_visit (graph, ti, j); } + VEC_safe_push (unsigned, heap, ti->topo_order, n); } /* Return true if variable N + OFFSET is a legal field of N. */ -static bool +static bool type_safe (unsigned int n, unsigned HOST_WIDE_INT *offset) { varinfo_t ninfo = get_varinfo (n); @@ -1582,10 +1347,10 @@ v = first_vi_for_offset (get_varinfo (j), fieldoffset); if (!v) continue; - t = v->node; + t = find (v->id); sol = get_varinfo (t)->solution; if (!bitmap_bit_p (sol, rhs)) - { + { bitmap_set_bit (sol, rhs); if (!TEST_BIT (changed, t)) { @@ -1596,7 +1361,7 @@ } else if (0 && dump_file && !(get_varinfo (j)->is_special_var)) fprintf (dump_file, "Untypesafe usage in do_da_constraint.\n"); - + } } @@ -1607,7 +1372,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c, bitmap delta) { - unsigned int lhs = get_varinfo (c->lhs.var)->node; + unsigned int lhs = find (c->lhs.var); bool flag = false; bitmap sol = get_varinfo (lhs)->solution; unsigned int j; @@ -1620,7 +1385,7 @@ bitmap_set_bit (sol, anything_id); goto done; } - /* For each variable j in delta (Sol(y)), add + /* For each variable j in delta (Sol(y)), add an edge in the graph from j to x, and union Sol(j) into Sol(x). */ EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi) { @@ -1634,18 +1399,18 @@ v = first_vi_for_offset (get_varinfo (j), fieldoffset); if (!v) continue; - t = v->node; + t = find (v->id); /* Adding edges from the special vars is pointless. They don't have sets that can change. */ if (get_varinfo (t) ->is_special_var) flag |= bitmap_ior_into (sol, get_varinfo (t)->solution); - else if (int_add_graph_edge (graph, lhs, t, 0)) + else if (add_graph_edge (graph, lhs, t)) flag |= bitmap_ior_into (sol, get_varinfo (t)->solution); } else if (0 && dump_file && !(get_varinfo (j)->is_special_var)) fprintf (dump_file, "Untypesafe usage in do_sd_constraint\n"); - + } done: @@ -1658,15 +1423,15 @@ SET_BIT (changed, lhs); changed_count++; } - } + } } /* Process a constraint C that represents *x = y. */ static void -do_ds_constraint (constraint_graph_t graph, constraint_t c, bitmap delta) +do_ds_constraint (constraint_t c, bitmap delta) { - unsigned int rhs = get_varinfo (c->rhs.var)->node; + unsigned int rhs = find (c->rhs.var); unsigned HOST_WIDE_INT roff = c->rhs.offset; bitmap sol = get_varinfo (rhs)->solution; unsigned int j; @@ -1685,8 +1450,8 @@ v = first_vi_for_offset (get_varinfo (j), fieldoffset); if (!v) continue; - t = v->node; - + t = find (v->id); + if (!bitmap_bit_p (get_varinfo (t)->solution, anything_id)) { bitmap_set_bit (get_varinfo (t)->solution, anything_id); @@ -1705,40 +1470,39 @@ EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi) { unsigned HOST_WIDE_INT loff = c->lhs.offset; - if (type_safe (j, &loff) && !(get_varinfo(j)->is_special_var)) + if (type_safe (j, &loff) && !(get_varinfo (j)->is_special_var)) { varinfo_t v; unsigned int t; unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + loff; + bitmap tmp; v = first_vi_for_offset (get_varinfo (j), fieldoffset); if (!v) continue; - t = v->node; - if (int_add_graph_edge (graph, t, rhs, roff)) + t = find (v->id); + tmp = get_varinfo (t)->solution; + + if (set_union_with_increment (tmp, sol, roff)) { - bitmap tmp = get_varinfo (t)->solution; - if (set_union_with_increment (tmp, sol, roff)) + get_varinfo (t)->solution = tmp; + if (t == rhs) + sol = get_varinfo (rhs)->solution; + if (!TEST_BIT (changed, t)) { - get_varinfo (t)->solution = tmp; - if (t == rhs) - sol = get_varinfo (rhs)->solution; - if (!TEST_BIT (changed, t)) - { - SET_BIT (changed, t); - changed_count++; - } + SET_BIT (changed, t); + changed_count++; } } - } + } else if (0 && dump_file && !(get_varinfo (j)->is_special_var)) fprintf (dump_file, "Untypesafe usage in do_ds_constraint\n"); } } -/* Handle a non-simple (simple meaning requires no iteration), non-copy - constraint (IE *x = &y, x = *y, and *x = y). */ - +/* Handle a non-simple (simple meaning requires no iteration), + constraint (IE *x = &y, x = *y, *x = y, and x = y with offsets involved). */ + static void do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta) { @@ -1752,33 +1516,62 @@ else { /* *x = y */ - do_ds_constraint (graph, c, delta); + do_ds_constraint (c, delta); } } - else + else if (c->rhs.type == DEREF) { /* x = *y */ if (!(get_varinfo (c->lhs.var)->is_special_var)) do_sd_constraint (graph, c, delta); } + else + { + bitmap tmp; + bitmap solution; + bool flag = false; + unsigned int t; + + gcc_assert (c->rhs.type == SCALAR && c->lhs.type == SCALAR); + t = find (c->rhs.var); + solution = get_varinfo (t)->solution; + t = find (c->lhs.var); + tmp = get_varinfo (t)->solution; + + flag = set_union_with_increment (tmp, solution, c->rhs.offset); + + if (flag) + { + get_varinfo (t)->solution = tmp; + if (!TEST_BIT (changed, t)) + { + SET_BIT (changed, t); + changed_count++; + } + } + } } /* Initialize and return a new SCC info structure. */ static struct scc_info * -init_scc_info (void) +init_scc_info (size_t size) { struct scc_info *si = XNEW (struct scc_info); - size_t size = VEC_length (varinfo_t, varmap); + size_t i; si->current_index = 0; si->visited = sbitmap_alloc (size); sbitmap_zero (si->visited); - si->in_component = sbitmap_alloc (size); - sbitmap_ones (si->in_component); - si->visited_index = XCNEWVEC (unsigned int, size + 1); + si->roots = sbitmap_alloc (size); + sbitmap_zero (si->roots); + si->node_mapping = XNEWVEC (unsigned int, size); + si->dfs = XCNEWVEC (unsigned int, size); + + for (i = 0; i < size; i++) + si->node_mapping[i] = i; + si->scc_stack = VEC_alloc (unsigned, heap, 1); - si->unification_queue = VEC_alloc (unsigned, heap, 1); return si; } @@ -1786,209 +1579,430 @@ static void free_scc_info (struct scc_info *si) -{ +{ sbitmap_free (si->visited); - sbitmap_free (si->in_component); - free (si->visited_index); + sbitmap_free (si->roots); + free (si->node_mapping); + free (si->dfs); VEC_free (unsigned, heap, si->scc_stack); - VEC_free (unsigned, heap, si->unification_queue); - free(si); + free (si); } -/* Find cycles in GRAPH that occur, using strongly connected components, and - collapse the cycles into a single representative node. if UPDATE_CHANGED - is true, then update the changed sbitmap to note those nodes whose - solutions have changed as a result of collapsing. */ +/* Find indirect cycles in GRAPH that occur, using strongly connected + components, and note them in the indirect cycles map. + This technique comes from Ben Hardekopf and Calvin Lin, + "It Pays to be Lazy: Fast and Accurate Pointer Analysis for Millions of + Lines of Code", submitted to PLDI 2007. */ + static void -find_and_collapse_graph_cycles (constraint_graph_t graph, bool update_changed) +find_indirect_cycles (constraint_graph_t graph) { unsigned int i; - unsigned int size = VEC_length (varinfo_t, varmap); - struct scc_info *si = init_scc_info (); + unsigned int size = graph->size; + struct scc_info *si = init_scc_info (size); - for (i = 0; i != size; ++i) - if (!TEST_BIT (si->visited, i) && get_varinfo (i)->node == i) + for (i = 0; i < MIN (LAST_REF_NODE, size); i ++ ) + if (!TEST_BIT (si->visited, i) && find (i) == i) scc_visit (graph, si, i); - - process_unification_queue (graph, si, update_changed); + free_scc_info (si); } /* Compute a topological ordering for GRAPH, and store the result in the topo_info structure TI. */ -static void +static void compute_topo_order (constraint_graph_t graph, struct topo_info *ti) { unsigned int i; unsigned int size = VEC_length (varinfo_t, varmap); - + for (i = 0; i != size; ++i) - if (!TEST_BIT (ti->visited, i) && get_varinfo (i)->node == i) + if (!TEST_BIT (ti->visited, i) && find (i) == i) topo_visit (graph, ti, i); } -/* Return true if bitmap B is empty, or a bitmap other than bit 0 is set. */ +/* Perform offline variable substitution. -static bool -bitmap_other_than_zero_bit_set (bitmap b) -{ - unsigned int i; - bitmap_iterator bi; - - if (bitmap_empty_p (b)) - return false; - EXECUTE_IF_SET_IN_BITMAP (b, 1, i, bi) - return true; - return false; -} - -/* Perform offline variable substitution. - This is a linear time way of identifying variables that must have equivalent points-to sets, including those caused by static cycles, and single entry subgraphs, in the constraint graph. The technique is described in "Off-line variable substitution for scaling points-to analysis" by Atanas Rountev and Satish Chandra, - in "ACM SIGPLAN Notices" volume 35, number 5, pages 47-56. */ + in "ACM SIGPLAN Notices" volume 35, number 5, pages 47-56. + There is an optimal way to do this involving hash based value + numbering, once the technique is published i will implement it + here. + + The general method of finding equivalence classes is as follows: + Add fake nodes (REF nodes) and edges for *a = b and a = *b constraints. + Add fake nodes (ADDRESS nodes) and edges for a = &b constraints. + Initialize all non-REF/ADDRESS nodes to be direct nodes + For each SCC in the predecessor graph: + for each member (x) of the SCC + if x is not a direct node: + set rootnode(SCC) to be not a direct node + collapse node x into rootnode(SCC). + if rootnode(SCC) is not a direct node: + label rootnode(SCC) with a new equivalence class + else: + if all labeled predecessors of rootnode(SCC) have the same + label: + label rootnode(SCC) with this label + else: + label rootnode(SCC) with a new equivalence class + + All direct nodes with the same equivalence class can be replaced + with a single representative node. + All unlabeled nodes (label == 0) are not pointers and all edges + involving them can be eliminated. + We perform these optimizations during move_complex_constraints. +*/ + +static int equivalence_class; + +/* Recursive routine to find strongly connected components in GRAPH, + and label it's nodes with equivalence classes. + This is used during variable substitution to find cycles involving + the regular or implicit predecessors, and label them as equivalent. + The SCC finding algorithm used is the same as that for scc_visit. */ + static void -perform_var_substitution (constraint_graph_t graph) +label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n) { - struct topo_info *ti = init_topo_info (); - - bitmap_obstack_initialize (&iteration_obstack); - /* Compute the topological ordering of the graph, then visit each - node in topological order. */ - compute_topo_order (graph, ti); - - while (VEC_length (unsigned, ti->topo_order) != 0) + unsigned int i; + bitmap_iterator bi; + unsigned int my_dfs; + + gcc_assert (si->node_mapping[n] == n); + SET_BIT (si->visited, n); + si->dfs[n] = si->current_index ++; + my_dfs = si->dfs[n]; + + /* Visit all the successors. */ + EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[n], 0, i, bi) { - unsigned int i = VEC_pop (unsigned, ti->topo_order); - unsigned int pred; - varinfo_t vi = get_varinfo (i); - bool okay_to_elim = false; - unsigned int root = VEC_length (varinfo_t, varmap); - VEC(constraint_edge_t,heap) *predvec = graph->preds[i]; - constraint_edge_t ce = NULL; - bitmap tmp; - unsigned int k; - bitmap_iterator bi; + unsigned int w = si->node_mapping[i]; - /* We can't eliminate things whose address is taken, or which is - the target of a dereference. */ - if (vi->address_taken || vi->indirect_target) + if (TEST_BIT (si->roots, w)) continue; - /* See if all predecessors of I are ripe for elimination */ - EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_preds[i], 0, k, bi) - { - unsigned int w; - w = get_varinfo (k)->node; + if (!TEST_BIT (si->visited, w)) + label_visit (graph, si, w); + { + unsigned int t = si->node_mapping[w]; + unsigned int nnode = si->node_mapping[n]; + gcc_assert (nnode == n); - /* We can't eliminate the node if one of the predecessors is - part of a different strongly connected component. */ - if (!okay_to_elim) - { - root = w; - okay_to_elim = true; - } - else if (w != root) - { - okay_to_elim = false; - break; - } + if (si->dfs[t] < si->dfs[nnode]) + si->dfs[n] = si->dfs[t]; + } + } - /* Theorem 4 in Rountev and Chandra: If i is a direct node, - then Solution(i) is a subset of Solution (w), where w is a - predecessor in the graph. - Corollary: If all predecessors of i have the same - points-to set, then i has that same points-to set as - those predecessors. */ - tmp = BITMAP_ALLOC (NULL); - bitmap_and_compl (tmp, get_varinfo (i)->solution, - get_varinfo (w)->solution); - if (!bitmap_empty_p (tmp)) - { - okay_to_elim = false; - BITMAP_FREE (tmp); - break; - } - BITMAP_FREE (tmp); - } + /* Visit all the implicit predecessors. */ + EXECUTE_IF_IN_NONNULL_BITMAP (graph->implicit_preds[n], 0, i, bi) + { + unsigned int w = si->node_mapping[i]; - if (okay_to_elim) - for (pred = 0; - VEC_iterate (constraint_edge_t, predvec, pred, ce); - pred++) - { - bitmap weight; - unsigned int w; - weight = *(get_graph_weights (graph, i, ce->dest)); + if (TEST_BIT (si->roots, w)) + continue; - /* We can't eliminate variables that have nonzero weighted - edges between them. */ - if (weight && bitmap_other_than_zero_bit_set (weight)) - { - okay_to_elim = false; - break; - } - w = get_varinfo (ce->dest)->node; + if (!TEST_BIT (si->visited, w)) + label_visit (graph, si, w); + { + unsigned int t = si->node_mapping[w]; + unsigned int nnode = si->node_mapping[n]; + gcc_assert (nnode == n); - /* We can't eliminate the node if one of the predecessors is - part of a different strongly connected component. */ - if (!okay_to_elim) - { - root = w; - okay_to_elim = true; - } - else if (w != root) - { - okay_to_elim = false; - break; - } + if (si->dfs[t] < si->dfs[nnode]) + si->dfs[n] = si->dfs[t]; + } + } - /* Theorem 4 in Rountev and Chandra: If i is a direct node, - then Solution(i) is a subset of Solution (w), where w is a - predecessor in the graph. - Corollary: If all predecessors of i have the same - points-to set, then i has that same points-to set as - those predecessors. */ - tmp = BITMAP_ALLOC (NULL); - bitmap_and_compl (tmp, get_varinfo (i)->solution, - get_varinfo (w)->solution); - if (!bitmap_empty_p (tmp)) - { - okay_to_elim = false; - BITMAP_FREE (tmp); - break; - } - BITMAP_FREE (tmp); - } + /* See if any components have been identified. */ + if (si->dfs[n] == my_dfs) + { + while (VEC_length (unsigned, si->scc_stack) != 0 + && si->dfs[VEC_last (unsigned, si->scc_stack)] >= my_dfs) + { + unsigned int w = VEC_pop (unsigned, si->scc_stack); + si->node_mapping[w] = n; - /* See if the root is different than the original node. - If so, we've found an equivalence. */ - if (root != get_varinfo (i)->node && okay_to_elim) + if (!TEST_BIT (graph->direct_nodes, w)) + RESET_BIT (graph->direct_nodes, n); + } + SET_BIT (si->roots, n); + + if (!TEST_BIT (graph->direct_nodes, n)) { - /* Found an equivalence */ - get_varinfo (i)->node = root; - collapse_nodes (graph, root, i); + graph->label[n] = equivalence_class++; + } + else + { + unsigned int size = 0; + unsigned int firstlabel = ~0; + + EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[n], 0, i, bi) + { + unsigned int j = si->node_mapping[i]; + + if (j == n || graph->label[j] == 0) + continue; + + if (firstlabel == (unsigned int)~0) + { + firstlabel = graph->label[j]; + size++; + } + else if (graph->label[j] != firstlabel) + size++; + } + + if (size == 0) + graph->label[n] = 0; + else if (size == 1) + graph->label[n] = firstlabel; + else + graph->label[n] = equivalence_class++; + } + } + else + VEC_safe_push (unsigned, heap, si->scc_stack, n); +} + +/* Perform offline variable substitution, discovering equivalence + classes, and eliminating non-pointer variables. */ + +static struct scc_info * +perform_var_substitution (constraint_graph_t graph) +{ + unsigned int i; + unsigned int size = graph->size; + struct scc_info *si = init_scc_info (size); + + bitmap_obstack_initialize (&iteration_obstack); + equivalence_class = 0; + + /* We only need to visit the non-address nodes for labeling + purposes, as the address nodes will never have any predecessors, + because &x never appears on the LHS of a constraint. */ + for (i = 0; i < LAST_REF_NODE; i++) + if (!TEST_BIT (si->visited, si->node_mapping[i])) + label_visit (graph, si, si->node_mapping[i]); + + if (dump_file && (dump_flags & TDF_DETAILS)) + for (i = 0; i < FIRST_REF_NODE; i++) + { + bool direct_node = TEST_BIT (graph->direct_nodes, i); + fprintf (dump_file, + "Equivalence class for %s node id %d:%s is %d\n", + direct_node ? "Direct node" : "Indirect node", i, + get_varinfo (i)->name, + graph->label[si->node_mapping[i]]); + } + + /* Quickly eliminate our non-pointer variables. */ + + for (i = 0; i < FIRST_REF_NODE; i++) + { + unsigned int node = si->node_mapping[i]; + + if (graph->label[node] == 0 && TEST_BIT (graph->direct_nodes, node)) + { if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Collapsing %s into %s\n", - get_varinfo (i)->name, - get_varinfo (root)->name); - stats.collapsed_vars++; + fprintf (dump_file, + "%s is a non-pointer variable, eliminating edges.\n", + get_varinfo (node)->name); + stats.nonpointer_vars++; + clear_edges_for_node (graph, node); } } + return si; +} +/* Free information that was only necessary for variable + substitution. */ + +static void +free_var_substitution_info (struct scc_info *si) +{ + free_scc_info (si); + free (graph->label); + free (graph->eq_rep); + sbitmap_free (graph->direct_nodes); bitmap_obstack_release (&iteration_obstack); - free_topo_info (ti); } +/* Return an existing node that is equivalent to NODE, which has + equivalence class LABEL, if one exists. Return NODE otherwise. */ + +static unsigned int +find_equivalent_node (constraint_graph_t graph, + unsigned int node, unsigned int label) +{ + /* If the address version of this variable is unused, we can + substitute it for anything else with the same label. + Otherwise, we know the pointers are equivalent, but not the + locations. */ + + if (graph->label[FIRST_ADDR_NODE + node] == 0) + { + gcc_assert (label < graph->size); + + if (graph->eq_rep[label] != -1) + { + /* Unify the two variables since we know they are equivalent. */ + if (unite (graph->eq_rep[label], node)) + unify_nodes (graph, graph->eq_rep[label], node, false); + return graph->eq_rep[label]; + } + else + { + graph->eq_rep[label] = node; + } + } + return node; +} + +/* Move complex constraints to the appropriate nodes, and collapse + variables we've discovered are equivalent during variable + substitution. SI is the SCC_INFO that is the result of + perform_variable_substitution. */ + +static void +move_complex_constraints (constraint_graph_t graph, + struct scc_info *si) +{ + int i; + unsigned int j; + constraint_t c; + + for (j = 0; j < graph->size; j++) + gcc_assert (find (j) == j); + + for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++) + { + struct constraint_expr lhs = c->lhs; + struct constraint_expr rhs = c->rhs; + unsigned int lhsvar = find (get_varinfo_fc (lhs.var)->id); + unsigned int rhsvar = find (get_varinfo_fc (rhs.var)->id); + unsigned int lhsnode, rhsnode; + unsigned int lhslabel, rhslabel; + + lhsnode = si->node_mapping[lhsvar]; + rhsnode = si->node_mapping[rhsvar]; + lhslabel = graph->label[lhsnode]; + rhslabel = graph->label[rhsnode]; + + /* See if it is really a non-pointer variable, and if so, ignore + the constraint. */ + if (lhslabel == 0) + { + if (!TEST_BIT (graph->direct_nodes, lhsnode)) + lhslabel = graph->label[lhsnode] = equivalence_class++; + else + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + + fprintf (dump_file, "%s is a non-pointer variable," + "ignoring constraint:", + get_varinfo (lhs.var)->name); + dump_constraint (dump_file, c); + } + VEC_replace (constraint_t, constraints, i, NULL); + continue; + } + } + + if (rhslabel == 0) + { + if (!TEST_BIT (graph->direct_nodes, rhsnode)) + rhslabel = graph->label[rhsnode] = equivalence_class++; + else + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + + fprintf (dump_file, "%s is a non-pointer variable," + "ignoring constraint:", + get_varinfo (rhs.var)->name); + dump_constraint (dump_file, c); + } + VEC_replace (constraint_t, constraints, i, NULL); + continue; + } + } + + lhsvar = find_equivalent_node (graph, lhsvar, lhslabel); + rhsvar = find_equivalent_node (graph, rhsvar, rhslabel); + c->lhs.var = lhsvar; + c->rhs.var = rhsvar; + + if (lhs.type == DEREF) + { + if (rhs.type == ADDRESSOF || rhsvar > anything_id) + insert_into_complex (graph, lhsvar, c); + } + else if (rhs.type == DEREF) + { + if (!(get_varinfo (lhsvar)->is_special_var)) + insert_into_complex (graph, rhsvar, c); + } + else if (rhs.type != ADDRESSOF && lhsvar > anything_id + && (lhs.offset != 0 || rhs.offset != 0)) + { + insert_into_complex (graph, rhsvar, c); + } + + } +} + +/* Eliminate indirect cycles involving NODE. Return true if NODE was + part of an SCC, false otherwise. */ + +static bool +eliminate_indirect_cycles (unsigned int node) +{ + if (graph->indirect_cycles[node] != -1 + && !bitmap_empty_p (get_varinfo (node)->solution)) + { + unsigned int i; + VEC(unsigned,heap) *queue = NULL; + int queuepos; + unsigned int to = find (graph->indirect_cycles[node]); + bitmap_iterator bi; + + /* We can't touch the solution set and call unify_nodes + at the same time, because unify_nodes is going to do + bitmap unions into it. */ + + EXECUTE_IF_SET_IN_BITMAP (get_varinfo (node)->solution, 0, i, bi) + { + if (find (i) == i && i != to) + { + if (unite (to, i)) + VEC_safe_push (unsigned, heap, queue, i); + } + } + + for (queuepos = 0; + VEC_iterate (unsigned, queue, queuepos, i); + queuepos++) + { + unify_nodes (graph, to, i, true); + } + VEC_free (unsigned, heap, queue); + return true; + } + return false; +} + /* Solve the constraint graph GRAPH using our worklist solver. This is based on the PW* family of solvers from the "Efficient Field Sensitive Pointer Analysis for C" paper. @@ -2001,17 +2015,28 @@ { unsigned int size = VEC_length (varinfo_t, varmap); unsigned int i; + bitmap pts; - changed_count = size; + changed_count = 0; changed = sbitmap_alloc (size); - sbitmap_ones (changed); - - /* The already collapsed/unreachable nodes will never change, so we - need to account for them in changed_count. */ + sbitmap_zero (changed); + + /* Mark all initial non-collapsed nodes as changed. */ for (i = 0; i < size; i++) - if (get_varinfo (i)->node != i) - changed_count--; - + { + varinfo_t ivi = get_varinfo (i); + if (find (i) == i && !bitmap_empty_p (ivi->solution) + && ((graph->succs[i] && !bitmap_empty_p (graph->succs[i])) + || VEC_length (constraint_t, graph->complex[i]) > 0)) + { + SET_BIT (changed, i); + changed_count++; + } + } + + /* Allocate a bitmap to be used to store the changed bits. */ + pts = BITMAP_ALLOC (&pta_obstack); + while (changed_count > 0) { unsigned int i; @@ -2019,41 +2044,45 @@ stats.iterations++; bitmap_obstack_initialize (&iteration_obstack); - - if (edge_added) - { - /* We already did cycle elimination once, when we did - variable substitution, so we don't need it again for the - first iteration. */ - if (stats.iterations > 1) - find_and_collapse_graph_cycles (graph, true); - edge_added = false; - } - compute_topo_order (graph, ti); while (VEC_length (unsigned, ti->topo_order) != 0) { + i = VEC_pop (unsigned, ti->topo_order); - gcc_assert (get_varinfo (i)->node == i); + /* If this variable is not a representative, skip it. */ + if (find (i) != i) + continue; + + /* In certain indirect cycle cases, we may merge this + variable to another. */ + if (eliminate_indirect_cycles (i) && find (i) != i) + continue; + /* If the node has changed, we need to process the complex constraints and outgoing edges again. */ if (TEST_BIT (changed, i)) { unsigned int j; constraint_t c; - constraint_edge_t e = NULL; bitmap solution; - bitmap_iterator bi; - VEC(constraint_t,heap) *complex = get_varinfo (i)->complex; - VEC(constraint_edge_t,heap) *succs; + VEC(constraint_t,heap) *complex = graph->complex[i]; bool solution_empty; RESET_BIT (changed, i); changed_count--; + /* Compute the changed set of solution bits. */ + bitmap_and_compl (pts, get_varinfo (i)->solution, + get_varinfo (i)->oldsolution); + + if (bitmap_empty_p (pts)) + continue; + + bitmap_ior_into (get_varinfo (i)->oldsolution, pts); + solution = get_varinfo (i)->solution; solution_empty = bitmap_empty_p (solution); @@ -2065,52 +2094,38 @@ is a constraint where the lhs side is receiving some set from elsewhere. */ if (!solution_empty || c->lhs.type != DEREF) - do_complex_constraint (graph, c, solution); + do_complex_constraint (graph, c, pts); } solution_empty = bitmap_empty_p (solution); if (!solution_empty) { + bitmap_iterator bi; + /* Propagate solution to all successors. */ - succs = graph->succs[i]; - - EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_succs[i], + EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i], 0, j, bi) { - bitmap tmp = get_varinfo (j)->solution; - bool flag = false; - - flag = set_union_with_increment (tmp, solution, 0); - - if (flag) - { - get_varinfo (j)->solution = tmp; - if (!TEST_BIT (changed, j)) - { - SET_BIT (changed, j); - changed_count++; - } - } - } - for (j = 0; VEC_iterate (constraint_edge_t, succs, j, e); j++) - { - bitmap tmp = get_varinfo (e->dest)->solution; - bool flag = false; - unsigned int k; - bitmap weights = e->weights; - bitmap_iterator bi; + bitmap tmp; + bool flag; - gcc_assert (weights && !bitmap_empty_p (weights)); - EXECUTE_IF_SET_IN_BITMAP (weights, 0, k, bi) - flag |= set_union_with_increment (tmp, solution, k); + unsigned int to = find (j); + tmp = get_varinfo (to)->solution; + flag = false; + /* Don't try to propagate to ourselves. */ + if (to == i) + continue; + + flag = set_union_with_increment (tmp, pts, 0); + if (flag) { - get_varinfo (e->dest)->solution = tmp; - if (!TEST_BIT (changed, e->dest)) + get_varinfo (to)->solution = tmp; + if (!TEST_BIT (changed, to)) { - SET_BIT (changed, e->dest); + SET_BIT (changed, to); changed_count++; } } @@ -2122,74 +2137,37 @@ bitmap_obstack_release (&iteration_obstack); } + BITMAP_FREE (pts); sbitmap_free (changed); + bitmap_obstack_release (&oldpta_obstack); } +/* Map from trees to variable infos. */ +static struct pointer_map_t *vi_for_tree; -/* CONSTRAINT AND VARIABLE GENERATION FUNCTIONS */ -/* Map from trees to variable ids. */ -static htab_t id_for_tree; +/* Insert ID as the variable id for tree T in the vi_for_tree map. */ -typedef struct tree_id +static void +insert_vi_for_tree (tree t, varinfo_t vi) { - tree t; - unsigned int id; -} *tree_id_t; - -/* Hash a tree id structure. */ - -static hashval_t -tree_id_hash (const void *p) -{ - const tree_id_t ta = (tree_id_t) p; - return htab_hash_pointer (ta->t); -} - -/* Return true if the tree in P1 and the tree in P2 are the same. */ - -static int -tree_id_eq (const void *p1, const void *p2) -{ - const tree_id_t ta1 = (tree_id_t) p1; - const tree_id_t ta2 = (tree_id_t) p2; - return ta1->t == ta2->t; -} - -/* Insert ID as the variable id for tree T in the hashtable. */ - -static void -insert_id_for_tree (tree t, int id) -{ - void **slot; - struct tree_id finder; - tree_id_t new_pair; - - finder.t = t; - slot = htab_find_slot (id_for_tree, &finder, INSERT); + void **slot = pointer_map_insert (vi_for_tree, t); + gcc_assert (vi); gcc_assert (*slot == NULL); - new_pair = XNEW (struct tree_id); - new_pair->t = t; - new_pair->id = id; - *slot = (void *)new_pair; + *slot = vi; } -/* Find the variable id for tree T in ID_FOR_TREE. If T does not - exist in the hash table, return false, otherwise, return true and - set *ID to the id we found. */ +/* Find the variable info for tree T in VI_FOR_TREE. If T does not + exist in the map, return NULL, otherwise, return the varinfo we found. */ -static bool -lookup_id_for_tree (tree t, unsigned int *id) +static varinfo_t +lookup_vi_for_tree (tree t) { - tree_id_t pair; - struct tree_id finder; + void **slot = pointer_map_contains (vi_for_tree, t); + if (slot == NULL) + return NULL; - finder.t = t; - pair = htab_find (id_for_tree, &finder); - if (pair == NULL) - return false; - *id = pair->id; - return true; + return (varinfo_t) *slot; } /* Return a printable name for DECL */ @@ -2210,7 +2188,7 @@ if (TREE_CODE (decl) == SSA_NAME) { - num_printed = asprintf (&temp, "%s_%u", + num_printed = asprintf (&temp, "%s_%u", alias_get_name (SSA_NAME_VAR (decl)), SSA_NAME_VERSION (decl)); } @@ -2226,21 +2204,17 @@ return res; } -/* Find the variable id for tree T in the hashtable. - If T doesn't exist in the hash table, create an entry for it. */ +/* Find the variable id for tree T in the map. + If T doesn't exist in the map, create an entry for it and return it. */ -static unsigned int -get_id_for_tree (tree t) +static varinfo_t +get_vi_for_tree (tree t) { - tree_id_t pair; - struct tree_id finder; + void **slot = pointer_map_contains (vi_for_tree, t); + if (slot == NULL) + return get_varinfo (create_variable_info_for (t, alias_get_name (t))); - finder.t = t; - pair = htab_find (id_for_tree, &finder); - if (pair == NULL) - return create_variable_info_for (t, alias_get_name (t)); - - return pair->id; + return (varinfo_t) *slot; } /* Get a constraint expression from an SSA_VAR_P node. */ @@ -2254,14 +2228,14 @@ /* For parameters, get at the points-to set for the actual parm decl. */ - if (TREE_CODE (t) == SSA_NAME - && TREE_CODE (SSA_NAME_VAR (t)) == PARM_DECL + if (TREE_CODE (t) == SSA_NAME + && TREE_CODE (SSA_NAME_VAR (t)) == PARM_DECL && default_def (SSA_NAME_VAR (t)) == t) return get_constraint_exp_from_ssa_var (SSA_NAME_VAR (t)); cexpr.type = SCALAR; - - cexpr.var = get_id_for_tree (t); + + cexpr.var = get_vi_for_tree (t)->id; /* If we determine the result is "anything", and we know this is readonly, say it points to readonly memory instead. */ if (cexpr.var == anything_id && TREE_READONLY (t)) @@ -2269,7 +2243,7 @@ cexpr.type = ADDRESSOF; cexpr.var = readonly_id; } - + cexpr.offset = 0; return cexpr; } @@ -2290,7 +2264,13 @@ get_varinfo (lhs.var)->directly_dereferenced = true; if (rhs.type == DEREF) get_varinfo (rhs.var)->directly_dereferenced = true; - + + if (!use_field_sensitive) + { + t->rhs.offset = 0; + t->lhs.offset = 0; + } + /* ANYTHING == ANYTHING is pointless. */ if (lhs.var == anything_id && rhs.var == anything_id) return; @@ -2302,7 +2282,7 @@ t->lhs = t->rhs; t->rhs = rhs; process_constraint (t); - } + } /* This can happen in our IR with things like n->a = *p */ else if (rhs.type == DEREF && lhs.type == DEREF && rhs.var != anything_id) { @@ -2312,33 +2292,19 @@ tree pointedtotype = TREE_TYPE (pointertype); tree tmpvar = create_tmp_var_raw (pointedtotype, "doubledereftmp"); struct constraint_expr tmplhs = get_constraint_exp_from_ssa_var (tmpvar); - + /* If this is an aggregate of known size, we should have passed this off to do_structure_copy, and it should have broken it up. */ - gcc_assert (!AGGREGATE_TYPE_P (pointedtotype) + gcc_assert (!AGGREGATE_TYPE_P (pointedtotype) || get_varinfo (rhs.var)->is_unknown_size_var); - + process_constraint (new_constraint (tmplhs, rhs)); process_constraint (new_constraint (lhs, tmplhs)); } - else if (rhs.type == ADDRESSOF) - { - varinfo_t vi; - gcc_assert (rhs.offset == 0); - - /* No need to mark address taken simply because of escaped vars - constraints. */ - if (lhs.var != escaped_vars_id) - for (vi = get_varinfo (rhs.var); vi != NULL; vi = vi->next) - vi->address_taken = true; - - VEC_safe_push (constraint_t, heap, constraints, t); - } else { - if (lhs.type != DEREF && rhs.type == DEREF) - get_varinfo (lhs.var)->indirect_target = true; + gcc_assert (rhs.type != ADDRESSOF || rhs.offset == 0); VEC_safe_push (constraint_t, heap, constraints, t); } } @@ -2350,10 +2316,12 @@ could_have_pointers (tree t) { tree type = TREE_TYPE (t); - - if (POINTER_TYPE_P (type) || AGGREGATE_TYPE_P (type) + + if (POINTER_TYPE_P (type) + || AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE) return true; + return false; } @@ -2367,9 +2335,9 @@ if (TREE_CODE (DECL_FIELD_OFFSET (fdecl)) != INTEGER_CST || TREE_CODE (DECL_FIELD_BIT_OFFSET (fdecl)) != INTEGER_CST) return -1; - - return (tree_low_cst (DECL_FIELD_OFFSET (fdecl), 1) * 8) - + tree_low_cst (DECL_FIELD_BIT_OFFSET (fdecl), 1); + + return (tree_low_cst (DECL_FIELD_OFFSET (fdecl), 1) * 8) + + tree_low_cst (DECL_FIELD_BIT_OFFSET (fdecl), 1); } @@ -2388,7 +2356,7 @@ return true; if (accesspos < fieldpos && (accesspos + accesssize > fieldpos)) return true; - + return false; } @@ -2411,20 +2379,20 @@ while (!SSA_VAR_P (forzero) && !CONSTANT_CLASS_P (forzero)) forzero = TREE_OPERAND (forzero, 0); - if (CONSTANT_CLASS_P (forzero) && integer_zerop (forzero)) + if (CONSTANT_CLASS_P (forzero) && integer_zerop (forzero)) { struct constraint_expr temp; - + temp.offset = 0; temp.var = integer_id; temp.type = SCALAR; VEC_safe_push (ce_s, heap, *results, &temp); return; } - + t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize); - /* String constants's are readonly, so there is nothing to really do + /* String constants are readonly, so there is nothing to really do here. */ if (TREE_CODE (t) == STRING_CST) return; @@ -2438,21 +2406,21 @@ /* This can also happen due to weird offsetof type macros. */ if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF) result->type = SCALAR; - + if (result->type == SCALAR) { /* In languages like C, you can access one past the end of an array. You aren't allowed to dereference it, so we can ignore this constraint. When we handle pointer subtraction, we may have to do something cute here. */ - + if (result->offset < get_varinfo (result->var)->fullsize && bitmaxsize != 0) { /* It's also not true that the constraint will actually start at the right offset, it may start in some padding. We only care about setting the constraint to the first actual field it touches, so - walk to find it. */ + walk to find it. */ varinfo_t curr; for (curr = get_varinfo (result->var); curr; curr = curr->next) { @@ -2495,6 +2463,7 @@ { struct constraint_expr *c; unsigned int i = 0; + for (i = 0; VEC_iterate (ce_s, *constraints, i, c); i++) { if (c->type == SCALAR) @@ -2576,6 +2545,7 @@ tree pttype = TREE_TYPE (TREE_TYPE (t)); get_constraint_for (exp, results); + /* Make sure we capture constraints to all elements of an array. */ if ((handled_component_p (exp) @@ -2588,7 +2558,7 @@ if (VEC_length (ce_s, *results) == 0) return; - + gcc_assert (VEC_length (ce_s, *results) == 1); origrhs = VEC_last (ce_s, *results); tmp = *origrhs; @@ -2619,12 +2589,12 @@ VEC_safe_push (ce_s, heap, *results, &tmp); } } - + for (i = 0; VEC_iterate (ce_s, *results, i, c); i++) { if (c->type == DEREF) c->type = SCALAR; - else + else c->type = ADDRESSOF; } return; @@ -2638,9 +2608,9 @@ { varinfo_t vi; tree heapvar = heapvar_lookup (t); - + if (heapvar == NULL) - { + { heapvar = create_tmp_var_raw (ptr_type_node, "HEAP"); DECL_EXTERNAL (heapvar) = 1; if (referenced_vars) @@ -2650,7 +2620,7 @@ temp.var = create_variable_info_for (heapvar, alias_get_name (heapvar)); - + vi = get_varinfo (temp.var); vi->is_artificial_var = 1; vi->is_heap_var = 1; @@ -2712,7 +2682,7 @@ case NON_LVALUE_EXPR: { tree op = TREE_OPERAND (t, 0); - + /* Cast from non-pointer to pointers are bad news for us. Anything else, we see through */ if (!(POINTER_TYPE_P (TREE_TYPE (t)) @@ -2738,7 +2708,7 @@ { switch (TREE_CODE (t)) { - case PHI_NODE: + case PHI_NODE: { get_constraint_for (PHI_RESULT (t), results); return; @@ -2782,8 +2752,8 @@ /* Handle the structure copy case where we have a simple structure copy - between LHS and RHS that is of SIZE (in bits) - + between LHS and RHS that is of SIZE (in bits) + For each field of the lhs variable (lhsfield) For each field of the rhs variable at lhsfield.offset (rhsfield) add the constraint lhsfield = rhsfield @@ -2808,7 +2778,7 @@ struct constraint_expr temprhs = rhs; unsigned HOST_WIDE_INT fieldoffset; - templhs.var = p->id; + templhs.var = p->id; q = get_varinfo (temprhs.var); fieldoffset = p->offset - pstart; q = first_vi_for_offset (q, q->offset + fieldoffset); @@ -2823,8 +2793,8 @@ /* Handle the structure copy case where we have a structure copy between a aggregate on the LHS and a dereference of a pointer on the RHS - that is of SIZE (in bits) - + that is of SIZE (in bits) + For each field of the lhs variable (lhsfield) rhs.offset = lhsfield->offset add the constraint lhsfield = rhs @@ -2849,12 +2819,12 @@ if (templhs.type == SCALAR) - templhs.var = p->id; + templhs.var = p->id; else templhs.offset = p->offset; - + q = get_varinfo (temprhs.var); - fieldoffset = p->offset - pstart; + fieldoffset = p->offset - pstart; temprhs.offset += fieldoffset; process_constraint (new_constraint (templhs, temprhs)); } @@ -2862,7 +2832,7 @@ /* Handle the structure copy case where we have a structure copy between a aggregate on the RHS and a dereference of a pointer on - the LHS that is of SIZE (in bits) + the LHS that is of SIZE (in bits) For each field of the rhs variable (rhsfield) lhs.offset = rhsfield->offset @@ -2888,12 +2858,12 @@ if (temprhs.type == SCALAR) - temprhs.var = p->id; + temprhs.var = p->id; else temprhs.offset = p->offset; - + q = get_varinfo (templhs.var); - fieldoffset = p->offset - pstart; + fieldoffset = p->offset - pstart; templhs.offset += fieldoffset; process_constraint (new_constraint (templhs, temprhs)); } @@ -2901,7 +2871,7 @@ /* Sometimes, frontends like to give us bad type information. This function will collapse all the fields from VAR to the end of VAR, - into VAR, so that we treat those fields as a single variable. + into VAR, so that we treat those fields as a single variable. We return the variable they were collapsed into. */ static unsigned int @@ -2913,16 +2883,16 @@ for (field = currvar->next; field; field = field->next) { if (dump_file) - fprintf (dump_file, "Type safety: Collapsing var %s into %s\n", + fprintf (dump_file, "Type safety: Collapsing var %s into %s\n", field->name, currvar->name); - + gcc_assert (!field->collapsed_to); field->collapsed_to = currvar; } currvar->next = NULL; currvar->size = currvar->fullsize - currvar->offset; - + return currvar->id; } @@ -2944,7 +2914,7 @@ gcc_assert (VEC_length (ce_s, rhsc) == 1); lhs = *(VEC_last (ce_s, lhsc)); rhs = *(VEC_last (ce_s, rhsc)); - + VEC_free (ce_s, heap, lhsc); VEC_free (ce_s, heap, rhsc); @@ -2955,7 +2925,7 @@ lhs = rhs; rhs = tmp; } - + /* This is fairly conservative for the RHS == ADDRESSOF case, in that it's possible it's something we could handle. However, most cases falling into this are dealing with transparent unions, which are slightly @@ -3021,11 +2991,11 @@ else lhssize = TREE_INT_CST_LOW (lhstypesize); - - if (rhs.type == SCALAR && lhs.type == SCALAR) + + if (rhs.type == SCALAR && lhs.type == SCALAR) { if (!do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize))) - { + { lhs.var = collapse_rest_of_var (lhs.var); rhs.var = collapse_rest_of_var (rhs.var); lhs.offset = 0; @@ -3042,7 +3012,7 @@ else { tree pointedtotype = lhstype; - tree tmpvar; + tree tmpvar; gcc_assert (rhs.type == DEREF && lhs.type == DEREF); tmpvar = create_tmp_var_raw (pointedtotype, "structcopydereftmp"); @@ -3052,6 +3022,7 @@ } } + /* Update related alias information kept in AI. This is used when building name tags, alias sets and deciding grouping heuristics. STMT is the statement to process. This function also updates @@ -3261,7 +3232,6 @@ } } - /* Handle pointer arithmetic EXPR when creating aliasing constraints. Expressions of the type PTR + CST can be handled in two ways: @@ -3307,6 +3277,7 @@ else return false; + for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++) for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++) { @@ -3360,12 +3331,12 @@ { int i; unsigned int j; - + /* For a phi node, assign all the arguments to the result. */ get_constraint_for (PHI_RESULT (t), &lhsc); for (i = 0; i < PHI_NUM_ARGS (t); i++) - { + { tree rhstype; tree strippedrhs = PHI_ARG_DEF (t, i); @@ -3401,7 +3372,6 @@ { tree lhsop; tree rhsop; - unsigned int varid; tree arglist; varinfo_t fi; int i = 1; @@ -3423,17 +3393,16 @@ we should still be able to handle. */ if (decl) { - varid = get_id_for_tree (decl); + fi = get_vi_for_tree (decl); } else { decl = TREE_OPERAND (rhsop, 0); - varid = get_id_for_tree (decl); + fi = get_vi_for_tree (decl); } /* Assign all the passed arguments to the appropriate incoming parameters of the function. */ - fi = get_varinfo (varid); arglist = TREE_OPERAND (rhsop, 1); for (;arglist; arglist = TREE_CHAIN (arglist)) @@ -3463,13 +3432,14 @@ } i++; } + /* If we are returning a value, assign it to the result. */ if (lhsop) { struct constraint_expr rhs; struct constraint_expr *lhsp; unsigned int j = 0; - + get_constraint_for (lhsop, &lhsc); if (TREE_CODE (decl) != FUNCTION_DECL) { @@ -3485,7 +3455,7 @@ } for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) process_constraint (new_constraint (*lhsp, rhs)); - } + } } /* Otherwise, just a regular assignment statement. */ else if (TREE_CODE (t) == MODIFY_EXPR) @@ -3494,7 +3464,7 @@ tree rhsop = TREE_OPERAND (t, 1); int i; - if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop)) + if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop)) || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE) && (AGGREGATE_TYPE_P (TREE_TYPE (rhsop)) || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)) @@ -3513,7 +3483,7 @@ { /* RHS that consist of unary operations, exceptional types, or bare decls/constants, get - handled directly by get_constraint_for. */ + handled directly by get_constraint_for. */ case tcc_reference: case tcc_declaration: case tcc_constant: @@ -3528,7 +3498,7 @@ { struct constraint_expr *c2; unsigned int k; - + for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++) process_constraint (new_constraint (*c, *c2)); } @@ -3570,7 +3540,7 @@ } } } - } + } } } } @@ -3578,7 +3548,7 @@ /* After promoting variables and computing aliasing we will need to re-scan most statements. FIXME: Try to minimize the number of statements re-scanned. It's not really necessary to - re-scan *all* statements. */ + re-scan *all* statements. */ mark_stmt_modified (origt); VEC_free (ce_s, heap, rhsc); VEC_free (ce_s, heap, lhsc); @@ -3591,7 +3561,7 @@ first field that overlaps with OFFSET. Return NULL if we can't find one. */ -static varinfo_t +static varinfo_t first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset) { varinfo_t curr = start; @@ -3617,7 +3587,7 @@ { varinfo_t prev = base; varinfo_t curr = base->next; - + field->next = curr; prev->next = field; } @@ -3630,7 +3600,7 @@ { varinfo_t prev = base; varinfo_t curr = base->next; - + if (curr == NULL) { prev->next = field; @@ -3652,13 +3622,13 @@ /* qsort comparison function for two fieldoff's PA and PB */ -static int +static int fieldoff_compare (const void *pa, const void *pb) { const fieldoff_s *foa = (const fieldoff_s *)pa; const fieldoff_s *fob = (const fieldoff_s *)pb; HOST_WIDE_INT foasize, fobsize; - + if (foa->offset != fob->offset) return foa->offset - fob->offset; @@ -3671,8 +3641,8 @@ void sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack) { - qsort (VEC_address (fieldoff_s, fieldstack), - VEC_length (fieldoff_s, fieldstack), + qsort (VEC_address (fieldoff_s, fieldstack), + VEC_length (fieldoff_s, fieldstack), sizeof (fieldoff_s), fieldoff_compare); } @@ -3686,12 +3656,12 @@ TYPE. */ int -push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, +push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, HOST_WIDE_INT offset, bool *has_union) { tree field; int count = 0; - + if (TREE_CODE (type) == COMPLEX_TYPE) { fieldoff_s *real_part, *img_part; @@ -3700,13 +3670,13 @@ real_part->size = TYPE_SIZE (TREE_TYPE (type)); real_part->offset = offset; real_part->decl = NULL_TREE; - + img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL); img_part->type = TREE_TYPE (type); img_part->size = TYPE_SIZE (TREE_TYPE (type)); img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type))); img_part->decl = NULL_TREE; - + return 2; } @@ -3733,12 +3703,12 @@ { bool push = false; int pushed = 0; - - if (has_union + + if (has_union && (TREE_CODE (TREE_TYPE (type)) == QUAL_UNION_TYPE || TREE_CODE (TREE_TYPE (type)) == UNION_TYPE)) *has_union = true; - + if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) /* var_can_have_subvars */ push = true; else if (!(pushed = push_fields_onto_fieldstack @@ -3772,12 +3742,12 @@ { bool push = false; int pushed = 0; - - if (has_union + + if (has_union && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)) *has_union = true; - + if (!var_can_have_subvars (field)) push = true; else if (!(pushed = push_fields_onto_fieldstack @@ -3789,7 +3759,7 @@ see if we didn't push any subfields and the size is nonzero, push the field onto the stack */ push = true; - + if (push) { fieldoff_s *pair; @@ -3848,15 +3818,15 @@ unsigned int i = 0; tree t; - for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); + for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t)) - { + { if (TREE_VALUE (t) == void_type_node) break; i++; } - + if (!t) *is_varargs = true; return i; @@ -3870,19 +3840,19 @@ { unsigned int index = VEC_length (varinfo_t, varmap); varinfo_t vi; - tree arg; + tree arg; unsigned int i; bool is_varargs = false; /* Create the variable info. */ - vi = new_var_info (decl, index, name, index); + vi = new_var_info (decl, index, name); vi->decl = decl; vi->offset = 0; vi->has_union = 0; vi->size = 1; vi->fullsize = count_num_arguments (decl, &is_varargs) + 1; - insert_id_for_tree (vi->decl, index); + insert_vi_for_tree (vi->decl, vi); VEC_safe_push (varinfo_t, heap, varmap, vi); stats.total_vars++; @@ -3898,12 +3868,12 @@ return index; } - + arg = DECL_ARGUMENTS (decl); /* Set up variables for each argument. */ for (i = 1; i < vi->fullsize; i++) - { + { varinfo_t argvi; const char *newname; char *tempname; @@ -3912,13 +3882,13 @@ if (arg) argdecl = arg; - + newindex = VEC_length (varinfo_t, varmap); asprintf (&tempname, "%s.arg%d", name, i-1); newname = ggc_strdup (tempname); free (tempname); - argvi = new_var_info (argdecl, newindex,newname, newindex); + argvi = new_var_info (argdecl, newindex, newname); argvi->decl = argdecl; VEC_safe_push (varinfo_t, heap, varmap, argvi); argvi->offset = i; @@ -3929,7 +3899,7 @@ stats.total_vars ++; if (arg) { - insert_id_for_tree (arg, newindex); + insert_vi_for_tree (arg, argvi); arg = TREE_CHAIN (arg); } } @@ -3948,13 +3918,13 @@ if (DECL_RESULT (decl)) resultdecl = DECL_RESULT (decl); - + newindex = VEC_length (varinfo_t, varmap); asprintf (&tempname, "%s.result", name); newname = ggc_strdup (tempname); free (tempname); - resultvi = new_var_info (resultdecl, newindex, newname, newindex); + resultvi = new_var_info (resultdecl, newindex, newname); resultvi->decl = resultdecl; VEC_safe_push (varinfo_t, heap, varmap, resultvi); resultvi->offset = i; @@ -3964,13 +3934,13 @@ insert_into_field_list_sorted (vi, resultvi); stats.total_vars ++; if (DECL_RESULT (decl)) - insert_id_for_tree (DECL_RESULT (decl), newindex); + insert_vi_for_tree (DECL_RESULT (decl), resultvi); } return index; -} +} -/* Return true if FIELDSTACK contains fields that overlap. +/* Return true if FIELDSTACK contains fields that overlap. FIELDSTACK is assumed to be sorted by offset. */ static bool @@ -4057,12 +4027,12 @@ bool hasunion; bool is_global = DECL_P (decl) ? is_global_var (decl) : false; VEC (fieldoff_s,heap) *fieldstack = NULL; - + if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode) return create_function_info_for (decl, name); hasunion = TREE_CODE (decltype) == UNION_TYPE - || TREE_CODE (decltype) == QUAL_UNION_TYPE; + || TREE_CODE (decltype) == QUAL_UNION_TYPE; if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion) { push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion); @@ -4072,12 +4042,12 @@ notokay = true; } } - + /* If the variable doesn't have subvars, we may end up needing to sort the field list and create fake variables for all the fields. */ - vi = new_var_info (decl, index, name, index); + vi = new_var_info (decl, index, name); vi->decl = decl; vi->offset = 0; vi->has_union = hasunion; @@ -4095,8 +4065,8 @@ vi->fullsize = TREE_INT_CST_LOW (declsize); vi->size = vi->fullsize; } - - insert_id_for_tree (vi->decl, index); + + insert_vi_for_tree (vi->decl, vi); VEC_safe_push (varinfo_t, heap, varmap, vi); if (is_global && (!flag_whole_program || !in_ipa_mode)) { @@ -4122,9 +4092,9 @@ } stats.total_vars++; - if (use_field_sensitive - && !notokay - && !vi->is_unknown_size_var + if (use_field_sensitive + && !notokay + && !vi->is_unknown_size_var && var_can_have_subvars (decl) && VEC_length (fieldoff_s, fieldstack) <= MAX_FIELDS_FOR_FIELD_SENSITIVE) { @@ -4148,7 +4118,7 @@ without creating varinfos for the fields anyway, so sorting them is a waste to boot. */ if (!notokay) - { + { sort_fieldstack (fieldstack); /* Due to some C++ FE issues, like PR 22488, we might end up what appear to be overlapping fields even though they, @@ -4156,8 +4126,8 @@ we will simply disable field-sensitivity for these cases. */ notokay = check_for_overlaps (fieldstack); } - - + + if (VEC_length (fieldoff_s, fieldstack) != 0) fo = VEC_index (fieldoff_s, fieldstack, 0); @@ -4169,11 +4139,11 @@ VEC_free (fieldoff_s, heap, fieldstack); return index; } - + vi->size = TREE_INT_CST_LOW (fo->size); vi->offset = fo->offset; - for (i = VEC_length (fieldoff_s, fieldstack) - 1; - i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo); + for (i = VEC_length (fieldoff_s, fieldstack) - 1; + i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo); i--) { varinfo_t newvi; @@ -4184,15 +4154,15 @@ if (dump_file) { if (fo->decl) - asprintf (&tempname, "%s.%s", + asprintf (&tempname, "%s.%s", vi->name, alias_get_name (fo->decl)); else - asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC, + asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC, vi->name, fo->offset); newname = ggc_strdup (tempname); free (tempname); } - newvi = new_var_info (decl, newindex, newname, newindex); + newvi = new_var_info (decl, newindex, newname); newvi->offset = fo->offset; newvi->size = TREE_INT_CST_LOW (fo->size); newvi->fullsize = vi->fullsize; @@ -4228,14 +4198,22 @@ { varinfo_t vi = get_varinfo (var); unsigned int i; - bitmap_iterator bi; - - fprintf (file, "%s = { ", vi->name); - EXECUTE_IF_SET_IN_BITMAP (get_varinfo (vi->node)->solution, 0, i, bi) + bitmap_iterator bi; + + if (find (var) != var) { - fprintf (file, "%s ", get_varinfo (i)->name); + varinfo_t vipt = get_varinfo (find (var)); + fprintf (file, "%s = same as %s\n", vi->name, vipt->name); } - fprintf (file, "}\n"); + else + { + fprintf (file, "%s = { ", vi->name); + EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi) + { + fprintf (file, "%s ", get_varinfo (i)->name); + } + fprintf (file, "}\n"); + } } /* Print the points-to solution for VAR to stdout. */ @@ -4266,7 +4244,7 @@ if (!could_have_pointers (t)) continue; - arg_id = get_id_for_tree (t); + arg_id = get_vi_for_tree (t)->id; /* With flag_argument_noalias greater than two means that the incoming argument cannot alias anything except for itself so create a HEAP @@ -4276,11 +4254,10 @@ { varinfo_t vi; tree heapvar = heapvar_lookup (t); - unsigned int id; lhs.offset = 0; lhs.type = SCALAR; - lhs.var = get_id_for_tree (t); + lhs.var = get_vi_for_tree (t)->id; if (heapvar == NULL_TREE) { @@ -4291,11 +4268,11 @@ add_referenced_var (heapvar); heapvar_insert (t, heapvar); } - id = get_id_for_tree (heapvar); - vi = get_varinfo (id); + + vi = get_vi_for_tree (heapvar); vi->is_artificial_var = 1; vi->is_heap_var = 1; - rhs.var = id; + rhs.var = vi->id; rhs.type = ADDRESSOF; rhs.offset = 0; for (p = get_varinfo (lhs.var); p; p = p->next) @@ -4409,8 +4386,8 @@ bool find_what_p_points_to (tree p) { - unsigned int id = 0; tree lookup_p = p; + varinfo_t vi; if (!have_alias_info) return false; @@ -4422,10 +4399,10 @@ && default_def (SSA_NAME_VAR (p)) == p) lookup_p = SSA_NAME_VAR (p); - if (lookup_id_for_tree (lookup_p, &id)) + vi = lookup_vi_for_tree (lookup_p); + if (vi) { - varinfo_t vi = get_varinfo (id); - + if (vi->is_artificial_var) return false; @@ -4447,7 +4424,7 @@ /* This variable may have been collapsed, let's get the real variable. */ - vi = get_varinfo (vi->node); + vi = get_varinfo (find (vi->id)); /* Translate artificial variables into SSA_NAME_PTR_INFO attributes. */ @@ -4506,13 +4483,16 @@ { fprintf (outfile, "Stats:\n"); fprintf (outfile, "Total vars: %d\n", stats.total_vars); + fprintf (outfile, "Non-pointer vars: %d\n", + stats.nonpointer_vars); fprintf (outfile, "Statically unified vars: %d\n", stats.unified_vars_static); - fprintf (outfile, "Collapsed vars: %d\n", stats.collapsed_vars); fprintf (outfile, "Dynamically unified vars: %d\n", stats.unified_vars_dynamic); fprintf (outfile, "Iterations: %d\n", stats.iterations); fprintf (outfile, "Number of edges: %d\n", stats.num_edges); + fprintf (outfile, "Number of implicit edges: %d\n", + stats.num_implicit_edges); } for (i = 0; i < VEC_length (varinfo_t, varmap); i++) @@ -4540,8 +4520,8 @@ /* Create the NULL variable, used to represent that a variable points to NULL. */ nothing_tree = create_tmp_var_raw (void_type_node, "NULL"); - var_nothing = new_var_info (nothing_tree, 0, "NULL", 0); - insert_id_for_tree (nothing_tree, 0); + var_nothing = new_var_info (nothing_tree, 0, "NULL"); + insert_vi_for_tree (nothing_tree, var_nothing); var_nothing->is_artificial_var = 1; var_nothing->offset = 0; var_nothing->size = ~0; @@ -4553,8 +4533,8 @@ /* Create the ANYTHING variable, used to represent that a variable points to some unknown piece of memory. */ anything_tree = create_tmp_var_raw (void_type_node, "ANYTHING"); - var_anything = new_var_info (anything_tree, 1, "ANYTHING", 1); - insert_id_for_tree (anything_tree, 1); + var_anything = new_var_info (anything_tree, 1, "ANYTHING"); + insert_vi_for_tree (anything_tree, var_anything); var_anything->is_artificial_var = 1; var_anything->size = ~0; var_anything->offset = 0; @@ -4573,7 +4553,6 @@ rhs.type = ADDRESSOF; rhs.var = anything_id; rhs.offset = 0; - var_anything->address_taken = true; /* This specifically does not use process_constraint because process_constraint ignores all anything = anything constraints, since all @@ -4583,14 +4562,14 @@ /* Create the READONLY variable, used to represent that a variable points to readonly memory. */ readonly_tree = create_tmp_var_raw (void_type_node, "READONLY"); - var_readonly = new_var_info (readonly_tree, 2, "READONLY", 2); + var_readonly = new_var_info (readonly_tree, 2, "READONLY"); var_readonly->is_artificial_var = 1; var_readonly->offset = 0; var_readonly->size = ~0; var_readonly->fullsize = ~0; var_readonly->next = NULL; var_readonly->is_special_var = 1; - insert_id_for_tree (readonly_tree, 2); + insert_vi_for_tree (readonly_tree, var_readonly); readonly_id = 2; VEC_safe_push (varinfo_t, heap, varmap, var_readonly); @@ -4610,8 +4589,8 @@ /* Create the INTEGER variable, used to represent that a variable points to an INTEGER. */ integer_tree = create_tmp_var_raw (void_type_node, "INTEGER"); - var_integer = new_var_info (integer_tree, 3, "INTEGER", 3); - insert_id_for_tree (integer_tree, 3); + var_integer = new_var_info (integer_tree, 3, "INTEGER"); + insert_vi_for_tree (integer_tree, var_integer); var_integer->is_artificial_var = 1; var_integer->size = ~0; var_integer->fullsize = ~0; @@ -4634,8 +4613,8 @@ /* Create the ESCAPED_VARS variable used to represent variables that escape this function. */ escaped_vars_tree = create_tmp_var_raw (void_type_node, "ESCAPED_VARS"); - var_escaped_vars = new_var_info (escaped_vars_tree, 4, "ESCAPED_VARS", 4); - insert_id_for_tree (escaped_vars_tree, 4); + var_escaped_vars = new_var_info (escaped_vars_tree, 4, "ESCAPED_VARS"); + insert_vi_for_tree (escaped_vars_tree, var_escaped_vars); var_escaped_vars->is_artificial_var = 1; var_escaped_vars->size = ~0; var_escaped_vars->fullsize = ~0; @@ -4660,21 +4639,19 @@ static void init_alias_vars (void) { - bitmap_obstack_initialize (&ptabitmap_obstack); + bitmap_obstack_initialize (&pta_obstack); + bitmap_obstack_initialize (&oldpta_obstack); bitmap_obstack_initialize (&predbitmap_obstack); - constraint_pool = create_alloc_pool ("Constraint pool", + constraint_pool = create_alloc_pool ("Constraint pool", sizeof (struct constraint), 30); variable_info_pool = create_alloc_pool ("Variable info pool", sizeof (struct variable_info), 30); - constraint_edge_pool = create_alloc_pool ("Constraint edges", - sizeof (struct constraint_edge), 30); - constraints = VEC_alloc (constraint_t, heap, 8); varmap = VEC_alloc (varinfo_t, heap, 8); - id_for_tree = htab_create (10, tree_id_hash, tree_id_eq, free); + vi_for_tree = pointer_map_create (); + memset (&stats, 0, sizeof (stats)); - init_base_vars (); } @@ -4777,6 +4754,43 @@ VEC_free (ce_s, heap, rhsc); } + +/* Remove the REF and ADDRESS edges from GRAPH, as well as all the + predecessor edges. */ + +static void +remove_preds_and_fake_succs (constraint_graph_t graph) +{ + unsigned int i; + + /* Clear the implicit ref and address nodes from the successor + lists. */ + for (i = 0; i < FIRST_REF_NODE; i++) + { + if (graph->succs[i]) + bitmap_clear_range (graph->succs[i], FIRST_REF_NODE, + FIRST_REF_NODE * 2); + } + + /* Free the successor list for the non-ref nodes. */ + for (i = FIRST_REF_NODE; i < graph->size; i++) + { + if (graph->succs[i]) + BITMAP_FREE (graph->succs[i]); + } + + /* Now reallocate the size of the successor list as, and blow away + the predecessor bitmaps. */ + graph->size = VEC_length (varinfo_t, varmap); + graph->succs = xrealloc (graph->succs, graph->size * sizeof (bitmap)); + + free (graph->implicit_preds); + graph->implicit_preds = NULL; + free (graph->preds); + graph->preds = NULL; + bitmap_obstack_release (&predbitmap_obstack); +} + /* Create points-to sets for the current function. See the comments at the start of the file for an algorithmic overview. */ @@ -4784,11 +4798,13 @@ compute_points_to_sets (struct alias_info *ai) { basic_block bb; + struct scc_info *si; timevar_push (TV_TREE_PTA); init_alias_vars (); - + init_alias_heapvars (); + intra_create_variable_infos (); /* Now walk all statements and derive aliases. */ @@ -4824,36 +4840,42 @@ } } - build_constraint_graph (); if (dump_file) { fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n"); dump_constraints (dump_file); } - + if (dump_file) fprintf (dump_file, "\nCollapsing static cycles and doing variable " "substitution:\n"); - - find_and_collapse_graph_cycles (graph, false); - perform_var_substitution (graph); - + + build_pred_graph (); + si = perform_var_substitution (graph); + move_complex_constraints (graph, si); + free_var_substitution_info (si); + + build_succ_graph (); + find_indirect_cycles (graph); + + /* Implicit nodes and predecessors are no longer necessary at this + point. */ + remove_preds_and_fake_succs (graph); + if (dump_file) fprintf (dump_file, "\nSolving graph:\n"); - + solve_graph (graph); - + if (dump_file) dump_sa_points_to_info (dump_file); - have_alias_info = true; timevar_pop (TV_TREE_PTA); } - /* Delete created points-to sets. */ void @@ -4861,33 +4883,27 @@ { varinfo_t v; int i; - - htab_delete (id_for_tree); - bitmap_obstack_release (&ptabitmap_obstack); - bitmap_obstack_release (&predbitmap_obstack); + + if (dump_file && (dump_flags & TDF_STATS)) + fprintf (dump_file, "Points to sets created:%d\n", + stats.points_to_sets_created); + + pointer_map_destroy (vi_for_tree); + bitmap_obstack_release (&pta_obstack); VEC_free (constraint_t, heap, constraints); - + for (i = 0; VEC_iterate (varinfo_t, varmap, i, v); i++) - { - /* Nonlocal vars may add more varinfos. */ - if (i >= graph_size) - break; + VEC_free (constraint_t, heap, graph->complex[i]); + free (graph->complex); - VEC_free (constraint_edge_t, heap, graph->succs[i]); - VEC_free (constraint_edge_t, heap, graph->preds[i]); - VEC_free (constraint_t, heap, v->complex); - } - free (graph->zero_weight_preds); - free (graph->zero_weight_succs); + free (graph->rep); free (graph->succs); - free (graph->preds); + free (graph->indirect_cycles); free (graph); VEC_free (varinfo_t, heap, varmap); free_alloc_pool (variable_info_pool); - free_alloc_pool (constraint_pool); - free_alloc_pool (constraint_edge_pool); - + free_alloc_pool (constraint_pool); have_alias_info = false; } @@ -4905,6 +4921,7 @@ static unsigned int ipa_pta_execute (void) { +#if 0 struct cgraph_node *node; in_ipa_mode = 1; init_alias_heapvars (); @@ -4994,6 +5011,7 @@ in_ipa_mode = 0; delete_alias_heapvars (); delete_points_to_sets (); +#endif return 0; } @@ -5018,8 +5036,9 @@ void init_alias_heapvars (void) { - heapvar_for_stmt = htab_create_ggc (11, tree_map_hash, tree_map_eq, - NULL); + if (!heapvar_for_stmt) + heapvar_for_stmt = htab_create_ggc (11, tree_map_hash, tree_map_eq, + NULL); nonlocal_all = NULL_TREE; } @@ -5028,7 +5047,7 @@ { nonlocal_all = NULL_TREE; htab_delete (heapvar_for_stmt); + heapvar_for_stmt = NULL; } - #include "gt-tree-ssa-structalias.h" Index: gcc/config/i386/i386.md =================================================================== --- gcc/config/i386/i386.md (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/i386/i386.md (.../branches/gcc-4_2-branch) (revision 125292) @@ -4749,7 +4749,7 @@ (define_insn "*addti3_1" [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o") (plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0") - (match_operand:TI 2 "general_operand" "roiF,riF"))) + (match_operand:TI 2 "x86_64_general_operand" "roe,re"))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)" "#") @@ -4757,7 +4757,7 @@ (define_split [(set (match_operand:TI 0 "nonimmediate_operand" "") (plus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "general_operand" ""))) + (match_operand:TI 2 "x86_64_general_operand" ""))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed" [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)] @@ -6483,7 +6483,7 @@ (define_insn "*subti3_1" [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o") (minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0") - (match_operand:TI 2 "general_operand" "roiF,riF"))) + (match_operand:TI 2 "x86_64_general_operand" "roe,re"))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)" "#") @@ -6491,7 +6491,7 @@ (define_split [(set (match_operand:TI 0 "nonimmediate_operand" "") (minus:TI (match_operand:TI 1 "nonimmediate_operand" "") - (match_operand:TI 2 "general_operand" ""))) + (match_operand:TI 2 "x86_64_general_operand" ""))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed" [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2))) @@ -9326,7 +9326,7 @@ (define_insn "*negti2_1" [(set (match_operand:TI 0 "nonimmediate_operand" "=ro") - (neg:TI (match_operand:TI 1 "general_operand" "0"))) + (neg:TI (match_operand:TI 1 "nonimmediate_operand" "0"))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_unary_operator_ok (NEG, TImode, operands)" @@ -9334,7 +9334,7 @@ (define_split [(set (match_operand:TI 0 "nonimmediate_operand" "") - (neg:TI (match_operand:TI 1 "general_operand" ""))) + (neg:TI (match_operand:TI 1 "nonimmediate_operand" ""))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && reload_completed" [(parallel Index: gcc/config/i386/sse.md =================================================================== --- gcc/config/i386/sse.md (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/i386/sse.md (.../branches/gcc-4_2-branch) (revision 125292) @@ -2055,11 +2055,11 @@ (match_dup 1)) (parallel [(const_int 0) (const_int 2)])))] - "TARGET_SSE3 && !(MEM_P (operands[1]) && MEM_P (operands[2]))" + "TARGET_SSE3 && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "@ movddup\t{%1, %0|%0, %1} #" - [(set_attr "type" "sselog,ssemov") + [(set_attr "type" "sselog1,ssemov") (set_attr "mode" "V2DF")]) (define_split @@ -3494,9 +3494,10 @@ "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "@ movhps\t{%1, %0|%0, %1} - psrldq\t{$4, %0|%0, 4} + psrldq\t{$8, %0|%0, 8} movq\t{%H1, %0|%0, %H1}" [(set_attr "type" "ssemov,sseishft,ssemov") + (set_attr "memory" "*,none,*") (set_attr "mode" "V2SF,TI,TI")]) ;; Not sure this is ever used, but it doesn't hurt to have it. -aoliva Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/i386/i386.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -15539,13 +15539,13 @@ /* Access to the vec_extract patterns. */ ftype = build_function_type_list (double_type_node, V2DF_type_node, integer_type_node, NULL_TREE); - def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v2df", + def_builtin (MASK_SSE2, "__builtin_ia32_vec_ext_v2df", ftype, IX86_BUILTIN_VEC_EXT_V2DF); ftype = build_function_type_list (long_long_integer_type_node, V2DI_type_node, integer_type_node, NULL_TREE); - def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v2di", + def_builtin (MASK_SSE2, "__builtin_ia32_vec_ext_v2di", ftype, IX86_BUILTIN_VEC_EXT_V2DI); ftype = build_function_type_list (float_type_node, V4SF_type_node, @@ -15555,12 +15555,12 @@ ftype = build_function_type_list (intSI_type_node, V4SI_type_node, integer_type_node, NULL_TREE); - def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v4si", + def_builtin (MASK_SSE2, "__builtin_ia32_vec_ext_v4si", ftype, IX86_BUILTIN_VEC_EXT_V4SI); ftype = build_function_type_list (intHI_type_node, V8HI_type_node, integer_type_node, NULL_TREE); - def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v8hi", + def_builtin (MASK_SSE2, "__builtin_ia32_vec_ext_v8hi", ftype, IX86_BUILTIN_VEC_EXT_V8HI); ftype = build_function_type_list (intHI_type_node, V4HI_type_node, @@ -15577,7 +15577,7 @@ ftype = build_function_type_list (V8HI_type_node, V8HI_type_node, intHI_type_node, integer_type_node, NULL_TREE); - def_builtin (MASK_SSE, "__builtin_ia32_vec_set_v8hi", + def_builtin (MASK_SSE2, "__builtin_ia32_vec_set_v8hi", ftype, IX86_BUILTIN_VEC_SET_V8HI); ftype = build_function_type_list (V4HI_type_node, V4HI_type_node, Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/sh/sh.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -5295,7 +5295,13 @@ temp = scavenge_reg (&temps); } if (temp < 0 && live_regs_mask) - temp = scavenge_reg (live_regs_mask); + { + HARD_REG_SET temps; + + COPY_HARD_REG_SET (temps, *live_regs_mask); + CLEAR_HARD_REG_BIT (temps, REGNO (reg)); + temp = scavenge_reg (&temps); + } if (temp < 0) { rtx adj_reg, tmp_reg, mem; @@ -5344,6 +5350,9 @@ emit_move_insn (adj_reg, mem); mem = gen_tmp_stack_mem (Pmode, gen_rtx_POST_INC (Pmode, reg)); emit_move_insn (tmp_reg, mem); + /* Tell flow the insns that pop r4/r5 aren't dead. */ + emit_insn (gen_rtx_USE (VOIDmode, tmp_reg)); + emit_insn (gen_rtx_USE (VOIDmode, adj_reg)); return; } const_reg = gen_rtx_REG (GET_MODE (reg), temp); @@ -8618,7 +8627,7 @@ else if (TARGET_SH4 && get_attr_type (insn) == TYPE_DYN_SHIFT && get_attr_any_int_load (dep_insn) == ANY_INT_LOAD_YES - && reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)), + && reg_overlap_mentioned_p (SET_DEST (single_set (dep_insn)), XEXP (SET_SRC (single_set (insn)), 1))) cost++; Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/sh/sh.md (.../branches/gcc-4_2-branch) (revision 125292) @@ -413,10 +413,12 @@ (eq_attr "type" "jump") (cond [(eq_attr "med_branch_p" "yes") (const_int 2) - (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") - (symbol_ref "INSN")) - (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") - (symbol_ref "code_for_indirect_jump_scratch"))) + (and (ne (symbol_ref "prev_nonnote_insn (insn)") + (const_int 0)) + (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))") + (symbol_ref "INSN")) + (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))") + (symbol_ref "code_for_indirect_jump_scratch")))) (cond [(eq_attr "braf_branch_p" "yes") (const_int 6) (eq (symbol_ref "flag_pic") (const_int 0)) @@ -750,54 +752,6 @@ (set_attr "type" "arith3")]) (define_insn "cmpeqsi_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (eq:DI (match_operand:SI 1 "logical_operand" "%r") - (match_operand:SI 2 "cmp_operand" "Nr")))] - "TARGET_SHMEDIA" - "cmpeq %1, %N2, %0" - [(set_attr "type" "cmp_media")]) - -(define_insn "cmpeqdi_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (eq:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "cmp_operand" "Nr")))] - "TARGET_SHMEDIA" - "cmpeq %1, %N2, %0" - [(set_attr "type" "cmp_media")]) - -(define_insn "cmpgtsi_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (gt:DI (match_operand:SI 1 "cmp_operand" "Nr") - (match_operand:SI 2 "cmp_operand" "rN")))] - "TARGET_SHMEDIA" - "cmpgt %N1, %N2, %0" - [(set_attr "type" "cmp_media")]) - -(define_insn "cmpgtdi_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") - (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] - "TARGET_SHMEDIA" - "cmpgt %N1, %N2, %0" - [(set_attr "type" "cmp_media")]) - -(define_insn "cmpgtusi_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (gtu:DI (match_operand:SI 1 "cmp_operand" "Nr") - (match_operand:SI 2 "cmp_operand" "rN")))] - "TARGET_SHMEDIA" - "cmpgtu %N1, %N2, %0" - [(set_attr "type" "cmp_media")]) - -(define_insn "cmpgtudi_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") - (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] - "TARGET_SHMEDIA" - "cmpgtu %N1, %N2, %0" - [(set_attr "type" "cmp_media")]) - -(define_insn "cmpsieqsi_media" [(set (match_operand:SI 0 "register_operand" "=r") (eq:SI (match_operand:SI 1 "logical_operand" "%r") (match_operand:SI 2 "cmp_operand" "Nr")))] @@ -805,7 +759,7 @@ "cmpeq %1, %N2, %0" [(set_attr "type" "cmp_media")]) -(define_insn "cmpsieqdi_media" +(define_insn "cmpeqdi_media" [(set (match_operand:SI 0 "register_operand" "=r") (eq:SI (match_operand:DI 1 "register_operand" "%r") (match_operand:DI 2 "cmp_operand" "Nr")))] @@ -813,7 +767,7 @@ "cmpeq %1, %N2, %0" [(set_attr "type" "cmp_media")]) -(define_insn "cmpsigtsi_media" +(define_insn "cmpgtsi_media" [(set (match_operand:SI 0 "register_operand" "=r") (gt:SI (match_operand:SI 1 "cmp_operand" "Nr") (match_operand:SI 2 "cmp_operand" "rN")))] @@ -821,7 +775,7 @@ "cmpgt %N1, %N2, %0" [(set_attr "type" "cmp_media")]) -(define_insn "cmpsigtdi_media" +(define_insn "cmpgtdi_media" [(set (match_operand:SI 0 "register_operand" "=r") (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] @@ -829,7 +783,7 @@ "cmpgt %N1, %N2, %0" [(set_attr "type" "cmp_media")]) -(define_insn "cmpsigtusi_media" +(define_insn "cmpgtusi_media" [(set (match_operand:SI 0 "register_operand" "=r") (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr") (match_operand:SI 2 "cmp_operand" "rN")))] @@ -837,7 +791,7 @@ "cmpgtu %N1, %N2, %0" [(set_attr "type" "cmp_media")]) -(define_insn "cmpsigtudi_media" +(define_insn "cmpgtudi_media" [(set (match_operand:SI 0 "register_operand" "=r") (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] @@ -846,13 +800,6 @@ [(set_attr "type" "cmp_media")]) ; These two patterns are for combine. -(define_insn "*cmpne0si_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (ne:DI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))] - "TARGET_SHMEDIA" - "cmpgtu %1,r63,%0" - [(set_attr "type" "cmp_media")]) - (define_insn "*cmpne0sisi_media" [(set (match_operand:SI 0 "register_operand" "=r") (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))] @@ -1177,7 +1124,7 @@ { emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2], operands[3])); - emit_insn (gen_cmpsigtusi_media (operands[5], operands[4], operands[0])); + emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0])); emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4], operands[0])); DONE; @@ -7200,7 +7147,7 @@ }") (define_expand "bunordered" - [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3))) + [(set (match_dup 1) (unordered:SI (match_dup 2) (match_dup 3))) (set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) (match_operand 0 "" "") @@ -7209,7 +7156,7 @@ " { operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]); - operands[1] = gen_reg_rtx (DImode); + operands[1] = gen_reg_rtx (SImode); operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1); }") @@ -9112,6 +9059,8 @@ { if (TARGET_SHMEDIA) { + rtx reg; + sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode @@ -9126,26 +9075,26 @@ switch (GET_MODE (sh_compare_op0)) { case SImode: - emit_insn (gen_cmpsieqsi_media (operands[0], + emit_insn (gen_cmpeqsi_media (operands[0], sh_compare_op0, sh_compare_op1)); break; case DImode: - emit_insn (gen_cmpsieqdi_media (operands[0], + emit_insn (gen_cmpeqdi_media (operands[0], sh_compare_op0, sh_compare_op1)); break; case SFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpsieqsf_media (operands[0], + emit_insn (gen_cmpeqsf_media (operands[0], sh_compare_op0, sh_compare_op1)); break; case DFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpsieqdf_media (operands[0], + emit_insn (gen_cmpeqdf_media (operands[0], sh_compare_op0, sh_compare_op1)); break; @@ -9155,38 +9104,44 @@ DONE; } - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + reg = operands[0]; + if (GET_MODE (operands[0]) != SImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); switch (GET_MODE (sh_compare_op0)) { case SImode: - emit_insn (gen_cmpeqsi_media (operands[0], + emit_insn (gen_cmpeqsi_media (reg, sh_compare_op0, sh_compare_op1)); break; case DImode: - emit_insn (gen_cmpeqdi_media (operands[0], + emit_insn (gen_cmpeqdi_media (reg, sh_compare_op0, sh_compare_op1)); break; case SFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpeqsf_media (operands[0], + emit_insn (gen_cmpeqsf_media (reg, sh_compare_op0, sh_compare_op1)); break; case DFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpeqdf_media (operands[0], + emit_insn (gen_cmpeqdf_media (reg, sh_compare_op0, sh_compare_op1)); break; default: FAIL; } + + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); + DONE; } if (sh_expand_t_scc (EQ, operands[0])) @@ -9204,8 +9159,8 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + rtx reg; + sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode @@ -9213,35 +9168,44 @@ : GET_MODE (sh_compare_op1), sh_compare_op1); + reg = operands[0]; + if (GET_MODE (operands[0]) != SImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); + switch (GET_MODE (sh_compare_op0)) { case SImode: - emit_insn (gen_cmpgtsi_media (operands[0], + emit_insn (gen_cmpgtsi_media (reg, sh_compare_op1, sh_compare_op0)); break; case DImode: - emit_insn (gen_cmpgtdi_media (operands[0], + emit_insn (gen_cmpgtdi_media (reg, sh_compare_op1, sh_compare_op0)); break; case SFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpgtsf_media (operands[0], + emit_insn (gen_cmpgtsf_media (reg, sh_compare_op1, sh_compare_op0)); break; case DFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpgtdf_media (operands[0], + emit_insn (gen_cmpgtdf_media (reg, sh_compare_op1, sh_compare_op0)); break; default: FAIL; } + + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); + DONE; } if (! currently_expanding_to_rtl) @@ -9258,8 +9222,8 @@ if (TARGET_SHMEDIA) { - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + rtx reg; + sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode @@ -9267,45 +9231,54 @@ : GET_MODE (sh_compare_op1), sh_compare_op1); + reg = operands[0]; + if (GET_MODE (operands[0]) != SImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); + switch (GET_MODE (sh_compare_op0)) { case SImode: { - tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode); emit_insn (gen_cmpgtsi_media (tmp, sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); break; } case DImode: { - tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode); emit_insn (gen_cmpgtdi_media (tmp, sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); break; } case SFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpgesf_media (operands[0], + emit_insn (gen_cmpgesf_media (reg, sh_compare_op1, sh_compare_op0)); break; case DFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpgedf_media (operands[0], + emit_insn (gen_cmpgedf_media (reg, sh_compare_op1, sh_compare_op0)); break; default: FAIL; } + + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); + DONE; } @@ -9323,8 +9296,12 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + rtx reg; + + reg = operands[0]; + if (GET_MODE (operands[0]) != SImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode @@ -9335,32 +9312,36 @@ switch (GET_MODE (sh_compare_op0)) { case SImode: - emit_insn (gen_cmpgtsi_media (operands[0], + emit_insn (gen_cmpgtsi_media (reg, sh_compare_op0, sh_compare_op1)); break; case DImode: - emit_insn (gen_cmpgtdi_media (operands[0], + emit_insn (gen_cmpgtdi_media (reg, sh_compare_op0, sh_compare_op1)); break; case SFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpgtsf_media (operands[0], + emit_insn (gen_cmpgtsf_media (reg, sh_compare_op0, sh_compare_op1)); break; case DFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpgtdf_media (operands[0], + emit_insn (gen_cmpgtdf_media (reg, sh_compare_op0, sh_compare_op1)); break; default: FAIL; } + + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); + DONE; } if (! currently_expanding_to_rtl) @@ -9376,12 +9357,15 @@ { if (TARGET_SHMEDIA) { + rtx reg; enum machine_mode mode = GET_MODE (sh_compare_op0); if ((mode) == VOIDmode) mode = GET_MODE (sh_compare_op1); - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + reg = operands[0]; + if (GET_MODE (operands[0]) != SImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (mode, sh_compare_op1); @@ -9390,41 +9374,45 @@ { case SImode: { - rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode); emit_insn (gen_cmpgtsi_media (tmp, sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); break; } case DImode: { - rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode); emit_insn (gen_cmpgtdi_media (tmp, sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); break; } case SFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpgesf_media (operands[0], + emit_insn (gen_cmpgesf_media (reg, sh_compare_op0, sh_compare_op1)); break; case DFmode: if (! TARGET_SHMEDIA_FPU) FAIL; - emit_insn (gen_cmpgedf_media (operands[0], + emit_insn (gen_cmpgedf_media (reg, sh_compare_op0, sh_compare_op1)); break; default: FAIL; } + + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); + DONE; } @@ -9456,8 +9444,12 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + rtx reg; + + reg = operands[0]; + if (GET_MODE (operands[0]) == DImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode @@ -9465,8 +9457,11 @@ : GET_MODE (sh_compare_op1), sh_compare_op1); - emit_insn (gen_cmpgtudi_media (operands[0], + emit_insn (gen_cmpgtudi_media (reg, sh_compare_op0, sh_compare_op1)); + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); + DONE; } if (! currently_expanding_to_rtl) @@ -9482,8 +9477,12 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + rtx reg; + + reg = operands[0]; + if (GET_MODE (operands[0]) == DImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode @@ -9491,8 +9490,11 @@ : GET_MODE (sh_compare_op1), sh_compare_op1); - emit_insn (gen_cmpgtudi_media (operands[0], + emit_insn (gen_cmpgtudi_media (reg, sh_compare_op1, sh_compare_op0)); + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); + DONE; } if (! currently_expanding_to_rtl) @@ -9508,10 +9510,12 @@ { if (TARGET_SHMEDIA) { - rtx tmp; + rtx tmp, reg; - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + reg = operands[0]; + if (GET_MODE (operands[0]) != SImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode @@ -9519,10 +9523,12 @@ : GET_MODE (sh_compare_op1), sh_compare_op1); - tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode); emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); DONE; } @@ -9539,10 +9545,12 @@ { if (TARGET_SHMEDIA) { - rtx tmp; + rtx tmp, reg; - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + reg = operands[0]; + if (GET_MODE (operands[0]) != SImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode @@ -9550,10 +9558,12 @@ : GET_MODE (sh_compare_op1), sh_compare_op1); - tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode); emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); DONE; } @@ -9584,11 +9594,12 @@ { if (TARGET_SHMEDIA) { - rtx tmp; + rtx tmp, reg; - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); - + reg = operands[0]; + if (GET_MODE (operands[0]) != SImode) + reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0) + : gen_reg_rtx (SImode); if (! TARGET_SHMEDIA_FPU && GET_MODE (sh_compare_op0) != DImode && GET_MODE (sh_compare_op0) != SImode) @@ -9601,10 +9612,12 @@ : GET_MODE (sh_compare_op1), sh_compare_op1); - tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode); emit_insn (gen_seq (tmp)); - emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); + if (GET_MODE (operands[0]) == DImode) + emit_insn (gen_extendsidi2 (operands[0], reg)); DONE; } @@ -9618,8 +9631,8 @@ }") (define_expand "sunordered" - [(set (match_operand:DI 0 "arith_reg_operand" "") - (unordered:DI (match_dup 1) (match_dup 2)))] + [(set (match_operand:SI 0 "arith_reg_operand" "") + (unordered:SI (match_dup 1) (match_dup 2)))] "TARGET_SHMEDIA_FPU" " { @@ -10378,14 +10391,6 @@ (set_attr "fp_mode" "single")]) (define_insn "cmpeqsf_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f") - (match_operand:SF 2 "fp_arith_reg_operand" "f")))] - "TARGET_SHMEDIA_FPU" - "fcmpeq.s %1, %2, %0" - [(set_attr "type" "fcmp_media")]) - -(define_insn "cmpsieqsf_media" [(set (match_operand:SI 0 "register_operand" "=r") (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") (match_operand:SF 2 "fp_arith_reg_operand" "f")))] @@ -10394,24 +10399,24 @@ [(set_attr "type" "fcmp_media")]) (define_insn "cmpgtsf_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f") + [(set (match_operand:SI 0 "register_operand" "=r") + (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") (match_operand:SF 2 "fp_arith_reg_operand" "f")))] "TARGET_SHMEDIA_FPU" "fcmpgt.s %1, %2, %0" [(set_attr "type" "fcmp_media")]) (define_insn "cmpgesf_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f") + [(set (match_operand:SI 0 "register_operand" "=r") + (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") (match_operand:SF 2 "fp_arith_reg_operand" "f")))] "TARGET_SHMEDIA_FPU" "fcmpge.s %1, %2, %0" [(set_attr "type" "fcmp_media")]) (define_insn "cmpunsf_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f") + [(set (match_operand:SI 0 "register_operand" "=r") + (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") (match_operand:SF 2 "fp_arith_reg_operand" "f")))] "TARGET_SHMEDIA_FPU" "fcmpun.s %1, %2, %0" @@ -10884,14 +10889,6 @@ (set_attr "fp_mode" "double")]) (define_insn "cmpeqdf_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f") - (match_operand:DF 2 "fp_arith_reg_operand" "f")))] - "TARGET_SHMEDIA_FPU" - "fcmpeq.d %1,%2,%0" - [(set_attr "type" "fcmp_media")]) - -(define_insn "cmpsieqdf_media" [(set (match_operand:SI 0 "register_operand" "=r") (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") (match_operand:DF 2 "fp_arith_reg_operand" "f")))] @@ -10900,24 +10897,24 @@ [(set_attr "type" "fcmp_media")]) (define_insn "cmpgtdf_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f") + [(set (match_operand:SI 0 "register_operand" "=r") + (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") (match_operand:DF 2 "fp_arith_reg_operand" "f")))] "TARGET_SHMEDIA_FPU" "fcmpgt.d %1,%2,%0" [(set_attr "type" "fcmp_media")]) (define_insn "cmpgedf_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f") + [(set (match_operand:SI 0 "register_operand" "=r") + (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") (match_operand:DF 2 "fp_arith_reg_operand" "f")))] "TARGET_SHMEDIA_FPU" "fcmpge.d %1,%2,%0" [(set_attr "type" "fcmp_media")]) (define_insn "cmpundf_media" - [(set (match_operand:DI 0 "register_operand" "=r") - (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f") + [(set (match_operand:SI 0 "register_operand" "=r") + (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") (match_operand:DF 2 "fp_arith_reg_operand" "f")))] "TARGET_SHMEDIA_FPU" "fcmpun.d %1,%2,%0" Index: gcc/config/score/predicates.md =================================================================== --- gcc/config/score/predicates.md (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/score/predicates.md (.../branches/gcc-4_2-branch) (revision 125292) @@ -75,14 +75,3 @@ return IMM_IN_RANGE (INTVAL (op), 15, 1); }) -(define_predicate "const_pow2" - (match_code "const_int") -{ - return IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) INTVAL (op), 0, 31); -}) - -(define_predicate "const_npow2" - (match_code "const_int") -{ - return IMM_IS_POW_OF_2 (~(unsigned HOST_WIDE_INT) INTVAL (op), 0, 31); -}) Index: gcc/config/score/misc.md =================================================================== --- gcc/config/score/misc.md (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/score/misc.md (.../branches/gcc-4_2-branch) (revision 125292) @@ -380,38 +380,3 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_insn "bitclr_c" - [(set (match_operand:SI 0 "register_operand" "=e,d") - (and:SI (match_operand:SI 1 "register_operand" "0,d") - (match_operand:SI 2 "const_npow2"))) - (clobber (reg:CC CC_REGNUM))] - "" - "@ - bitclr! %0, %F2 - bitclr.c %0, %1, %F2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_insn "bitset_c" - [(set (match_operand:SI 0 "register_operand" "=e,d") - (ior:SI (match_operand:SI 1 "register_operand" "0,d") - (match_operand:SI 2 "const_pow2"))) - (clobber (reg:CC CC_REGNUM))] - "" - "@ - bitset! %0, %E2 - bitset.c %0, %1, %E2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_insn "bittgl_c" - [(set (match_operand:SI 0 "register_operand" "=e,d") - (xor:SI (match_operand:SI 1 "register_operand" "0,d") - (match_operand:SI 2 "const_pow2"))) - (clobber (reg:CC CC_REGNUM))] - "" - "@ - bittgl! %0, %E2 - bittgl.c %0, %1, %E2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) Index: gcc/config/score/score.c =================================================================== --- gcc/config/score/score.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/score/score.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -1168,7 +1168,7 @@ { gcc_assert (code == CONST_INT); fprintf (file, HOST_WIDE_INT_PRINT_HEX, - (unsigned HOST_WIDE_INT) INTVAL (op) >> 16); + (INTVAL (op) >> 16) & 0xffff); } else if (c == 'D') { @@ -1176,7 +1176,7 @@ { rtx temp = gen_lowpart (SImode, op); gcc_assert (GET_MODE (op) == SFmode); - fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (temp)); + fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (temp) & 0xffffffff); } else output_addr_const (file, op); Index: gcc/config/score/score.h =================================================================== --- gcc/config/score/score.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/score/score.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -785,6 +785,7 @@ output anything and let undefined symbol become external. However the assembler uses length information on externals to allocate in data/sdata bss/sbss, thereby saving exec time. */ +#undef ASM_OUTPUT_EXTERNAL #define ASM_OUTPUT_EXTERNAL(STREAM, DECL, NAME) \ score_output_external (STREAM, DECL, NAME) Index: gcc/config/pa/pa.md =================================================================== --- gcc/config/pa/pa.md (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/pa/pa.md (.../branches/gcc-4_2-branch) (revision 125292) @@ -39,6 +39,9 @@ (UNSPEC_TLSLDBASE 7) (UNSPEC_TLSIE 8) (UNSPEC_TLSLE 9) + (UNSPEC_TLSGD_PIC 10) + (UNSPEC_TLSLDM_PIC 11) + (UNSPEC_TLSIE_PIC 12) ]) ;; UNSPEC_VOLATILE: @@ -9890,33 +9893,55 @@ (define_insn "tgd_load" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")] UNSPEC_TLSGD)) - (clobber (reg:SI 1))] + (clobber (reg:SI 1)) + (use (reg:SI 27))] "" "* { - if (flag_pic) - return \"addil LT'%1-$tls_gdidx$,%%r19\;ldo RT'%1-$tls_gdidx$(%%r1),%0\"; - else - return \"addil LR'%1-$tls_gdidx$,%%r27\;ldo RR'%1-$tls_gdidx$(%%r1),%0\"; + return \"addil LR'%1-$tls_gdidx$,%%r27\;ldo RR'%1-$tls_gdidx$(%%r1),%0\"; }" [(set_attr "type" "multi") (set_attr "length" "8")]) +(define_insn "tgd_load_pic" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")] UNSPEC_TLSGD_PIC)) + (clobber (reg:SI 1)) + (use (reg:SI 19))] + "" + "* +{ + return \"addil LT'%1-$tls_gdidx$,%%r19\;ldo RT'%1-$tls_gdidx$(%%r1),%0\"; +}" + [(set_attr "type" "multi") + (set_attr "length" "8")]) + (define_insn "tld_load" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")] UNSPEC_TLSLDM)) - (clobber (reg:SI 1))] + (clobber (reg:SI 1)) + (use (reg:SI 27))] "" "* { - if (flag_pic) - return \"addil LT'%1-$tls_ldidx$,%%r19\;ldo RT'%1-$tls_ldidx$(%%r1),%0\"; - else - return \"addil LR'%1-$tls_ldidx$,%%r27\;ldo RR'%1-$tls_ldidx$(%%r1),%0\"; + return \"addil LR'%1-$tls_ldidx$,%%r27\;ldo RR'%1-$tls_ldidx$(%%r1),%0\"; }" [(set_attr "type" "multi") (set_attr "length" "8")]) +(define_insn "tld_load_pic" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")] UNSPEC_TLSLDM_PIC)) + (clobber (reg:SI 1)) + (use (reg:SI 19))] + "" + "* +{ + return \"addil LT'%1-$tls_ldidx$,%%r19\;ldo RT'%1-$tls_ldidx$(%%r1),%0\"; +}" + [(set_attr "type" "multi") + (set_attr "length" "8")]) + (define_insn "tld_offset_load" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")] @@ -9942,18 +9967,29 @@ (define_insn "tie_load" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand 1 "tie_symbolic_operand" "")] UNSPEC_TLSIE)) - (clobber (reg:SI 1))] + (clobber (reg:SI 1)) + (use (reg:SI 27))] "" "* { - if (flag_pic) - return \"addil LT'%1-$tls_ieoff$,%%r19\;ldw RT'%1-$tls_ieoff$(%%r1),%0\"; - else - return \"addil LR'%1-$tls_ieoff$,%%r27\;ldw RR'%1-$tls_ieoff$(%%r1),%0\"; + return \"addil LR'%1-$tls_ieoff$,%%r27\;ldw RR'%1-$tls_ieoff$(%%r1),%0\"; }" [(set_attr "type" "multi") (set_attr "length" "8")]) +(define_insn "tie_load_pic" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "tie_symbolic_operand" "")] UNSPEC_TLSIE_PIC)) + (clobber (reg:SI 1)) + (use (reg:SI 19))] + "" + "* +{ + return \"addil LT'%1-$tls_ieoff$,%%r19\;ldw RT'%1-$tls_ieoff$(%%r1),%0\"; +}" + [(set_attr "type" "multi") + (set_attr "length" "8")]) + (define_insn "tle_load" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (unspec:SI [(match_operand 1 "tle_symbolic_operand" "")] Index: gcc/config/pa/pa.c =================================================================== --- gcc/config/pa/pa.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/pa/pa.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -726,7 +726,10 @@ { case TLS_MODEL_GLOBAL_DYNAMIC: tmp = gen_reg_rtx (Pmode); - emit_insn (gen_tgd_load (tmp, addr)); + if (flag_pic) + emit_insn (gen_tgd_load_pic (tmp, addr)); + else + emit_insn (gen_tgd_load (tmp, addr)); ret = hppa_tls_call (tmp); break; @@ -734,7 +737,10 @@ ret = gen_reg_rtx (Pmode); tmp = gen_reg_rtx (Pmode); start_sequence (); - emit_insn (gen_tld_load (tmp, addr)); + if (flag_pic) + emit_insn (gen_tld_load_pic (tmp, addr)); + else + emit_insn (gen_tld_load (tmp, addr)); t1 = hppa_tls_call (tmp); insn = get_insns (); end_sequence (); @@ -750,7 +756,10 @@ tmp = gen_reg_rtx (Pmode); ret = gen_reg_rtx (Pmode); emit_insn (gen_tp_load (tp)); - emit_insn (gen_tie_load (tmp, addr)); + if (flag_pic) + emit_insn (gen_tie_load_pic (tmp, addr)); + else + emit_insn (gen_tie_load (tmp, addr)); emit_move_insn (ret, gen_rtx_PLUS (Pmode, tp, tmp)); break; Index: gcc/config/soft-fp/quad.h =================================================================== --- gcc/config/soft-fp/quad.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/quad.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Definitions for IEEE Quad Precision. - Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com), Jakub Jelinek (jj@ultra.linux.cz), @@ -176,15 +176,15 @@ } longs; struct { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned sign : 1; - unsigned exp : _FP_EXPBITS_Q; - unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE; - unsigned long frac0 : _FP_W_TYPE_SIZE; + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_Q; + _FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE; + _FP_W_TYPE frac0 : _FP_W_TYPE_SIZE; #else - unsigned long frac0 : _FP_W_TYPE_SIZE; - unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE; - unsigned exp : _FP_EXPBITS_Q; - unsigned sign : 1; + _FP_W_TYPE frac0 : _FP_W_TYPE_SIZE; + _FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_Q; + unsigned sign : 1; #endif } bits; }; Index: gcc/config/soft-fp/floatunsidf.c =================================================================== --- gcc/config/soft-fp/floatunsidf.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/floatunsidf.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Convert a 32bit unsigned integer to IEEE double - Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com) and Jakub Jelinek (jj@ultra.linux.cz). @@ -32,8 +32,7 @@ #include "soft-fp.h" #include "double.h" -double -__floatunsidf(USItype i) +DFtype __floatunsidf(USItype i) { FP_DECL_EX; FP_DECL_D(A); Index: gcc/config/soft-fp/floatundidf.c =================================================================== --- gcc/config/soft-fp/floatundidf.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/floatundidf.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Convert a 64bit unsigned integer to IEEE double - Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com) and Jakub Jelinek (jj@ultra.linux.cz). @@ -32,8 +32,7 @@ #include "soft-fp.h" #include "double.h" -double -__floatundidf(UDItype i) +DFtype __floatundidf(UDItype i) { FP_DECL_EX; FP_DECL_D(A); Index: gcc/config/soft-fp/extended.h =================================================================== --- gcc/config/soft-fp/extended.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/extended.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Definitions for IEEE Extended Precision. - Copyright (C) 1999,2006 Free Software Foundation, Inc. + Copyright (C) 1999,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek (jj@ultra.linux.cz). @@ -94,12 +94,6 @@ X##_f[1] = _flo.bits.frac1; \ X##_e = _flo.bits.exp; \ X##_s = _flo.bits.sign; \ - if (!X##_e && (X##_f[1] || X##_f[0]) \ - && !(X##_f[1] & _FP_IMPLBIT_E)) \ - { \ - X##_e++; \ - FP_SET_EXCEPTION(FP_EX_DENORM); \ - } \ } while (0) #define FP_UNPACK_RAW_EP(X, val) \ @@ -112,12 +106,6 @@ X##_f[1] = _flo->bits.frac1; \ X##_e = _flo->bits.exp; \ X##_s = _flo->bits.sign; \ - if (!X##_e && (X##_f[1] || X##_f[0]) \ - && !(X##_f[1] & _FP_IMPLBIT_E)) \ - { \ - X##_e++; \ - FP_SET_EXCEPTION(FP_EX_DENORM); \ - } \ } while (0) #define FP_PACK_RAW_E(val, X) \ @@ -164,13 +152,13 @@ #define FP_UNPACK_SEMIRAW_E(X,val) \ do { \ - _FP_UNPACK_RAW_E(X,val); \ + FP_UNPACK_RAW_E(X,val); \ _FP_UNPACK_SEMIRAW(E,4,X); \ } while (0) #define FP_UNPACK_SEMIRAW_EP(X,val) \ do { \ - _FP_UNPACK_RAW_EP(X,val); \ + FP_UNPACK_RAW_EP(X,val); \ _FP_UNPACK_SEMIRAW(E,4,X); \ } while (0) @@ -189,13 +177,13 @@ #define FP_PACK_SEMIRAW_E(val,X) \ do { \ _FP_PACK_SEMIRAW(E,4,X); \ - _FP_PACK_RAW_E(val,X); \ + FP_PACK_RAW_E(val,X); \ } while (0) #define FP_PACK_SEMIRAW_EP(val,X) \ do { \ _FP_PACK_SEMIRAW(E,4,X); \ - _FP_PACK_RAW_EP(val,X); \ + FP_PACK_RAW_EP(val,X); \ } while (0) #define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,4,X) @@ -277,14 +265,14 @@ XFtype flt; struct { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned long pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E); - unsigned sign : 1; - unsigned exp : _FP_EXPBITS_E; - unsigned long frac : _FP_W_TYPE_SIZE; + _FP_W_TYPE pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E); + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_E; + _FP_W_TYPE frac : _FP_W_TYPE_SIZE; #else - unsigned long frac : _FP_W_TYPE_SIZE; - unsigned exp : _FP_EXPBITS_E; - unsigned sign : 1; + _FP_W_TYPE frac : _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_E; + unsigned sign : 1; #endif } bits; }; @@ -299,11 +287,6 @@ X##_f1 = 0; \ X##_e = _flo.bits.exp; \ X##_s = _flo.bits.sign; \ - if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \ - { \ - X##_e++; \ - FP_SET_EXCEPTION(FP_EX_DENORM); \ - } \ } while (0) #define FP_UNPACK_RAW_EP(X, val) \ @@ -315,11 +298,6 @@ X##_f1 = 0; \ X##_e = _flo->bits.exp; \ X##_s = _flo->bits.sign; \ - if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \ - { \ - X##_e++; \ - FP_SET_EXCEPTION(FP_EX_DENORM); \ - } \ } while (0) #define FP_PACK_RAW_E(val, X) \ @@ -365,13 +343,13 @@ #define FP_UNPACK_SEMIRAW_E(X,val) \ do { \ - _FP_UNPACK_RAW_E(X,val); \ + FP_UNPACK_RAW_E(X,val); \ _FP_UNPACK_SEMIRAW(E,2,X); \ } while (0) #define FP_UNPACK_SEMIRAW_EP(X,val) \ do { \ - _FP_UNPACK_RAW_EP(X,val); \ + FP_UNPACK_RAW_EP(X,val); \ _FP_UNPACK_SEMIRAW(E,2,X); \ } while (0) @@ -390,13 +368,13 @@ #define FP_PACK_SEMIRAW_E(val,X) \ do { \ _FP_PACK_SEMIRAW(E,2,X); \ - _FP_PACK_RAW_E(val,X); \ + FP_PACK_RAW_E(val,X); \ } while (0) #define FP_PACK_SEMIRAW_EP(val,X) \ do { \ _FP_PACK_SEMIRAW(E,2,X); \ - _FP_PACK_RAW_EP(val,X); \ + FP_PACK_RAW_EP(val,X); \ } while (0) #define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,2,X) Index: gcc/config/soft-fp/floatunsisf.c =================================================================== --- gcc/config/soft-fp/floatunsisf.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/floatunsisf.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Convert a 32bit unsigned integer to IEEE single - Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com) and Jakub Jelinek (jj@ultra.linux.cz). @@ -32,8 +32,7 @@ #include "soft-fp.h" #include "single.h" -float -__floatunsisf(USItype i) +SFtype __floatunsisf(USItype i) { FP_DECL_EX; FP_DECL_S(A); Index: gcc/config/soft-fp/op-common.h =================================================================== --- gcc/config/soft-fp/op-common.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/op-common.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -1153,7 +1153,8 @@ if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \ || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \ < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \ - || _FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \ + || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \ + && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \ abort(); \ D##_s = S##_s; \ _FP_FRAC_COPY_##dwc##_##swc(D, S); \ @@ -1168,6 +1169,14 @@ { \ if (_FP_FRAC_ZEROP_##swc(S)) \ D##_e = 0; \ + else if (_FP_EXPBIAS_##dfs \ + < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \ + - _FP_FRACBITS_##sfs)); \ + D##_e = 0; \ + } \ else \ { \ int _lz; \ @@ -1199,7 +1208,8 @@ #define FP_TRUNC(dfs,sfs,dwc,swc,D,S) \ do { \ if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \ - || _FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \ + || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \ + && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \ abort(); \ D##_s = S##_s; \ if (_FP_EXP_NORMAL(sfs, swc, S)) \ @@ -1211,8 +1221,11 @@ { \ if (D##_e <= 0) \ { \ - if (D##_e <= 1 - _FP_FRACBITS_##dfs) \ - _FP_FRAC_SET_##swc(S, _FP_ZEROFRAC_##swc); \ + if (D##_e < 1 - _FP_FRACBITS_##dfs) \ + { \ + _FP_FRAC_SET_##swc(S, _FP_ZEROFRAC_##swc); \ + _FP_FRAC_LOW_##swc(S) |= 1; \ + } \ else \ { \ _FP_FRAC_HIGH_##sfs(S) |= _FP_IMPLBIT_SH_##sfs; \ @@ -1234,11 +1247,24 @@ if (S##_e == 0) \ { \ D##_e = 0; \ - _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ - if (!_FP_FRAC_ZEROP_##swc(S)) \ + if (_FP_FRAC_ZEROP_##swc(S)) \ + _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ + else \ { \ FP_SET_EXCEPTION(FP_EX_DENORM); \ - FP_SET_EXCEPTION(FP_EX_INEXACT); \ + if (_FP_EXPBIAS_##sfs \ + < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \ + { \ + _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + _FP_FRAC_COPY_##dwc##_##swc(D, S); \ + } \ + else \ + { \ + _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ + _FP_FRAC_LOW_##dwc(D) |= 1; \ + } \ } \ } \ else \ Index: gcc/config/soft-fp/floatundisf.c =================================================================== --- gcc/config/soft-fp/floatundisf.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/floatundisf.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Convert a 64bit unsigned integer to IEEE single - Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com) and Jakub Jelinek (jj@ultra.linux.cz). @@ -32,8 +32,7 @@ #include "soft-fp.h" #include "single.h" -float -__floatundisf(UDItype i) +SFtype __floatundisf(UDItype i) { FP_DECL_EX; FP_DECL_S(A); Index: gcc/config/soft-fp/op-2.h =================================================================== --- gcc/config/soft-fp/op-2.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/op-2.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Basic two-word fraction declaration and manipulation. - Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com), Jakub Jelinek (jj@ultra.linux.cz), @@ -613,3 +613,5 @@ #define _FP_FRAC_COPY_1_2(D, S) (D##_f = S##_f0) #define _FP_FRAC_COPY_2_1(D, S) ((D##_f0 = S##_f), (D##_f1 = 0)) + +#define _FP_FRAC_COPY_2_2(D,S) _FP_FRAC_COPY_2(D,S) Index: gcc/config/soft-fp/op-4.h =================================================================== --- gcc/config/soft-fp/op-4.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/op-4.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Basic four-word fraction declaration and manipulation. - Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com), Jakub Jelinek (jj@ultra.linux.cz), @@ -684,3 +684,5 @@ D##_f[1] = S##_f1; \ D##_f[2] = D##_f[3] = 0; \ } while (0) + +#define _FP_FRAC_COPY_4_4(D,S) _FP_FRAC_COPY_4(D,S) Index: gcc/config/soft-fp/double.h =================================================================== --- gcc/config/soft-fp/double.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ gcc/config/soft-fp/double.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,6 +1,6 @@ /* Software floating-point emulation. Definitions for IEEE Double Precision - Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com), Jakub Jelinek (jj@ultra.linux.cz), @@ -168,13 +168,13 @@ DFtype flt; struct { #if __BYTE_ORDER == __BIG_ENDIAN - unsigned sign : 1; - unsigned exp : _FP_EXPBITS_D; - unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); #else - unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); - unsigned exp : _FP_EXPBITS_D; - unsigned sign : 1; + _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; #endif } bits __attribute__((packed)); }; Index: libstdc++-v3/configure =================================================================== --- libstdc++-v3/configure (.../tags/gcc_4_2_0_release) (revision 125292) +++ libstdc++-v3/configure (.../branches/gcc-4_2-branch) (revision 125292) @@ -5764,8 +5764,6 @@ - echo "$as_me:$LINENO: checking for C locale to use" >&5 -echo $ECHO_N "checking for C locale to use... $ECHO_C" >&6 # Check whether --enable-clocale or --disable-clocale was given. if test "${enable_clocale+set}" = set; then enableval="$enable_clocale" @@ -5782,32 +5780,53 @@ fi; - # If they didn't use this option switch, or if they specified --enable - # with no specific model, we'll have to look for one. If they - # specified --disable (???), do likewise. + # Deal with gettext issues. Default to not using it (=no) until we detect + # support for it later. Let the user turn it off via --e/d, but let that + # default to on for easier handling. + USE_NLS=no + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + +else + enable_nls=yes +fi; + + # Either a known packaage, or "auto" if test $enable_clocale = no || test $enable_clocale = yes; then enable_clocale=auto fi - - # Either a known package, or "auto" enable_clocale_flag=$enable_clocale - # Probe for locale support if no specific model is specified. + # Probe for locale model to use if none specified. # Default to "generic". if test $enable_clocale_flag = auto; then case ${target_os} in linux* | gnu* | kfreebsd*-gnu | knetbsd*-gnu) - cat >conftest.$ac_ext <<_ACEOF + enable_clocale_flag=gnu + ;; + darwin* | freebsd*) + enable_clocale_flag=darwin + ;; + *) + enable_clocale_flag=generic + ;; + esac + fi + + # Sanity check model, and test for special functionality. + if test $enable_clocale_flag = gnu; then + cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - #include - #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) - _GLIBCXX_ok - #endif + #include + #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) + _GLIBCXX_ok + #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | @@ -5819,9 +5838,8 @@ rm -f conftest* - # Test for bugs early in glibc-2.2.x series - if test $enable_clocale_flag = gnu; then - if test "$cross_compiling" = yes; then + # Test for bugs early in glibc-2.2.x series + if test "$cross_compiling" = yes; then enable_clocale_flag=generic else cat >conftest.$ac_ext <<_ACEOF @@ -5831,28 +5849,28 @@ cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - #define _GNU_SOURCE 1 - #include - #include - #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) - extern __typeof(newlocale) __newlocale; - extern __typeof(duplocale) __duplocale; - extern __typeof(strcoll_l) __strcoll_l; - #endif - int main() - { - const char __one[] = "Äuglein Augmen"; - const char __two[] = "Äuglein"; - int i; - int j; - __locale_t loc; - __locale_t loc_dup; - loc = __newlocale(1 << LC_ALL, "de_DE", 0); - loc_dup = __duplocale(loc); - i = __strcoll_l(__one, __two, loc); - j = __strcoll_l(__one, __two, loc_dup); - return 0; - } + #define _GNU_SOURCE 1 + #include + #include + #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) + extern __typeof(newlocale) __newlocale; + extern __typeof(duplocale) __duplocale; + extern __typeof(strcoll_l) __strcoll_l; + #endif + int main() + { + const char __one[] = "Äuglein Augmen"; + const char __two[] = "Äuglein"; + int i; + int j; + __locale_t loc; + __locale_t loc_dup; + loc = __newlocale(1 << LC_ALL, "de_DE", 0); + loc_dup = __duplocale(loc); + i = __strcoll_l(__one, __two, loc); + j = __strcoll_l(__one, __two, loc_dup); + return 0; + } _ACEOF rm -f conftest$ac_exeext @@ -5877,32 +5895,176 @@ fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi - fi - # ... at some point put __strxfrm_l tests in as well. - ;; - darwin* | freebsd*) - enable_clocale_flag=darwin - ;; - *) - enable_clocale_flag=generic - ;; - esac + # Set it to scream when it hurts. + ac_save_CFLAGS="$CFLAGS" + CFLAGS="-Wimplicit-function-declaration -Werror" + + # Use strxfrm_l if available. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _GNU_SOURCE 1 + #include + #include +int +main () +{ +char s[128]; __locale_t loc; strxfrm_l(s, "C", 5, loc); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRXFRM_L 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + + # Use strerror_l if available. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _GNU_SOURCE 1 + #include + #include +int +main () +{ +__locale_t loc; strerror_l(5, loc); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRERROR_L 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + + CFLAGS="$ac_save_CFLAGS" fi - # Deal with gettext issues. Default to not using it (=no) until we detect - # support for it later. Let the user turn it off via --e/d, but let that - # default to on for easier handling. - USE_NLS=no - # Check whether --enable-nls or --disable-nls was given. -if test "${enable_nls+set}" = set; then - enableval="$enable_nls" + # Perhaps use strerror_r if available, and strerror_l isn't. + ac_save_CFLAGS="$CFLAGS" + CFLAGS="-Wimplicit-function-declaration -Werror" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _GNU_SOURCE 1 + #include + #include +int +main () +{ +char s[128]; strerror_r(5, s, 128); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRERROR_R 1 +_ACEOF + else - enable_nls=yes -fi; + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + # Set configure bits for specified locale package + echo "$as_me:$LINENO: checking for C locale to use" >&5 +echo $ECHO_N "checking for C locale to use... $ECHO_C" >&6 case ${enable_clocale_flag} in generic) echo "$as_me:$LINENO: result: generic" >&5 @@ -8015,7 +8177,7 @@ # Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style. cat > conftest.$ac_ext << EOF -#line 8018 "configure" +#line 8180 "configure" int main() { // NB: _Atomic_word not necessarily int. @@ -8395,11 +8557,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -54307,11 +54467,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -75669,11 +75827,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -77194,11 +77350,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -78687,11 +78841,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -100579,11 +100731,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -101426,11 +101576,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -102829,11 +102977,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -104624,11 +104770,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -105869,11 +106013,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 @@ -106898,11 +107040,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections echo "$as_me:$LINENO: checking for ld that supports -Wl,--gc-sections" >&5 Index: libstdc++-v3/include/bits/ostream.tcc =================================================================== --- libstdc++-v3/include/bits/ostream.tcc (.../tags/gcc_4_2_0_release) (revision 125292) +++ libstdc++-v3/include/bits/ostream.tcc (.../branches/gcc-4_2-branch) (revision 125292) @@ -334,7 +334,6 @@ extern template ostream& operator<<(ostream&, const char*); extern template ostream& operator<<(ostream&, const unsigned char*); extern template ostream& operator<<(ostream&, const signed char*); - extern template ostream& __ostream_insert(ostream&, const char*, streamsize); extern template ostream& ostream::_M_insert(long); extern template ostream& ostream::_M_insert(unsigned long); @@ -356,8 +355,6 @@ extern template wostream& operator<<(wostream&, char); extern template wostream& operator<<(wostream&, const wchar_t*); extern template wostream& operator<<(wostream&, const char*); - extern template wostream& __ostream_insert(wostream&, const wchar_t*, - streamsize); extern template wostream& wostream::_M_insert(long); extern template wostream& wostream::_M_insert(unsigned long); Index: libstdc++-v3/include/bits/ostream_insert.h =================================================================== --- libstdc++-v3/include/bits/ostream_insert.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ libstdc++-v3/include/bits/ostream_insert.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -109,6 +109,18 @@ return __out; } + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. +#if _GLIBCXX_EXTERN_TEMPLATE + extern template ostream& __ostream_insert(ostream&, const char*, streamsize); + +#ifdef _GLIBCXX_USE_WCHAR_T + extern template wostream& __ostream_insert(wostream&, const wchar_t*, + streamsize); +#endif +#endif + _GLIBCXX_END_NAMESPACE #endif /* _OSTREAM_INSERT_H */ Index: libstdc++-v3/ChangeLog =================================================================== --- libstdc++-v3/ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ libstdc++-v3/ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,26 @@ +2007-05-28 Benjamin Kosnik + + PR libstdc++/31717 + * acinclude.m4 (GLIBCXX_ENABLE_CLOCALE): Re-organize. Sanity check + gnu locale model requests to make sure it will work for the requested + target. Add checks for strxfrm_l, strerror_l when in gnu locale, + and strerror_r everywhere. + * aclocal.m4: Regenerated. + * configure: Regenerated. + * config.h.in: Regenerated. + +2007-05-24 Paolo Carlini + + * include/bits/ostream.tcc: Do not inhibit implicit instantiation + of __ostream_insert here... + * include/bits/ostream_insert.h: ... do it here. + +2007-05-21 Paolo Carlini + + PR libstdc++/31621 + * acinclude.m4 ([GLIBCXX_CHECK_LINKER_FEATURES]): Use the C compiler. + * configure: Regenerate. + 2007-05-13 Release Manager * GCC 4.2.0 released. Index: libstdc++-v3/config.h.in =================================================================== --- libstdc++-v3/config.h.in (.../tags/gcc_4_2_0_release) (revision 125292) +++ libstdc++-v3/config.h.in (.../branches/gcc-4_2-branch) (revision 125292) @@ -298,6 +298,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H +/* Define if strerror_l is available in . */ +#undef HAVE_STRERROR_L + +/* Define if strerror_r is available in . */ +#undef HAVE_STRERROR_R + /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H @@ -310,6 +316,9 @@ /* Define to 1 if you have the `strtold' function. */ #undef HAVE_STRTOLD +/* Define if strxfrm_l is available in . */ +#undef HAVE_STRXFRM_L + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILIO_H Index: libstdc++-v3/acinclude.m4 =================================================================== --- libstdc++-v3/acinclude.m4 (.../tags/gcc_4_2_0_release) (revision 125292) +++ libstdc++-v3/acinclude.m4 (.../branches/gcc-4_2-branch) (revision 125292) @@ -251,11 +251,9 @@ # NB: This flag only works reliably after 2.16.1. Configure tests # for this are difficult, so hard wire a value that should work. - # All these tests are for C++, but run with the "C" compiler driver. - # Need to do this so that g++ won't try to link in libstdc++/libsupc++. ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" - CFLAGS='-x c++ -Wl,--gc-sections' + CFLAGS='-Wl,--gc-sections' # Check for -Wl,--gc-sections AC_MSG_CHECKING([for ld that supports -Wl,--gc-sections]) @@ -1334,64 +1332,31 @@ dnl Default is generic. dnl AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ - AC_MSG_CHECKING([for C locale to use]) GLIBCXX_ENABLE(clocale,auto,[@<:@=MODEL@:>@], [use MODEL for target locale package], [permit generic|gnu|ieee_1003.1-2001|yes|no|auto]) + + # Deal with gettext issues. Default to not using it (=no) until we detect + # support for it later. Let the user turn it off via --e/d, but let that + # default to on for easier handling. + USE_NLS=no + AC_ARG_ENABLE(nls, + AC_HELP_STRING([--enable-nls],[use Native Language Support (default)]), + [], + [enable_nls=yes]) - # If they didn't use this option switch, or if they specified --enable - # with no specific model, we'll have to look for one. If they - # specified --disable (???), do likewise. + # Either a known packaage, or "auto" if test $enable_clocale = no || test $enable_clocale = yes; then enable_clocale=auto fi - - # Either a known package, or "auto" enable_clocale_flag=$enable_clocale - # Probe for locale support if no specific model is specified. + # Probe for locale model to use if none specified. # Default to "generic". if test $enable_clocale_flag = auto; then case ${target_os} in linux* | gnu* | kfreebsd*-gnu | knetbsd*-gnu) - AC_EGREP_CPP([_GLIBCXX_ok], [ - #include - #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) - _GLIBCXX_ok - #endif - ], enable_clocale_flag=gnu, enable_clocale_flag=generic) - - # Test for bugs early in glibc-2.2.x series - if test $enable_clocale_flag = gnu; then - AC_TRY_RUN([ - #define _GNU_SOURCE 1 - #include - #include - #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) - extern __typeof(newlocale) __newlocale; - extern __typeof(duplocale) __duplocale; - extern __typeof(strcoll_l) __strcoll_l; - #endif - int main() - { - const char __one[] = "Äuglein Augmen"; - const char __two[] = "Äuglein"; - int i; - int j; - __locale_t loc; - __locale_t loc_dup; - loc = __newlocale(1 << LC_ALL, "de_DE", 0); - loc_dup = __duplocale(loc); - i = __strcoll_l(__one, __two, loc); - j = __strcoll_l(__one, __two, loc_dup); - return 0; - } - ], - [enable_clocale_flag=gnu],[enable_clocale_flag=generic], - [enable_clocale_flag=generic]) - fi - - # ... at some point put __strxfrm_l tests in as well. + enable_clocale_flag=gnu ;; darwin* | freebsd*) enable_clocale_flag=darwin @@ -1402,16 +1367,79 @@ esac fi - # Deal with gettext issues. Default to not using it (=no) until we detect - # support for it later. Let the user turn it off via --e/d, but let that - # default to on for easier handling. - USE_NLS=no - AC_ARG_ENABLE(nls, - AC_HELP_STRING([--enable-nls],[use Native Language Support (default)]), - [], - [enable_nls=yes]) + # Sanity check model, and test for special functionality. + if test $enable_clocale_flag = gnu; then + AC_EGREP_CPP([_GLIBCXX_ok], [ + #include + #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) + _GLIBCXX_ok + #endif + ], enable_clocale_flag=gnu, enable_clocale_flag=generic) + # Test for bugs early in glibc-2.2.x series + AC_TRY_RUN([ + #define _GNU_SOURCE 1 + #include + #include + #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) + extern __typeof(newlocale) __newlocale; + extern __typeof(duplocale) __duplocale; + extern __typeof(strcoll_l) __strcoll_l; + #endif + int main() + { + const char __one[] = "Äuglein Augmen"; + const char __two[] = "Äuglein"; + int i; + int j; + __locale_t loc; + __locale_t loc_dup; + loc = __newlocale(1 << LC_ALL, "de_DE", 0); + loc_dup = __duplocale(loc); + i = __strcoll_l(__one, __two, loc); + j = __strcoll_l(__one, __two, loc_dup); + return 0; + } + ], + [enable_clocale_flag=gnu],[enable_clocale_flag=generic], + [enable_clocale_flag=generic]) + + # Set it to scream when it hurts. + ac_save_CFLAGS="$CFLAGS" + CFLAGS="-Wimplicit-function-declaration -Werror" + + # Use strxfrm_l if available. + AC_TRY_COMPILE([#define _GNU_SOURCE 1 + #include + #include ], + [char s[128]; __locale_t loc; strxfrm_l(s, "C", 5, loc);], + AC_DEFINE(HAVE_STRXFRM_L, 1, + [Define if strxfrm_l is available in .]),) + + # Use strerror_l if available. + AC_TRY_COMPILE([#define _GNU_SOURCE 1 + #include + #include ], + [__locale_t loc; strerror_l(5, loc);], + AC_DEFINE(HAVE_STRERROR_L, 1, + [Define if strerror_l is available in .]),) + + CFLAGS="$ac_save_CFLAGS" + fi + + # Perhaps use strerror_r if available, and strerror_l isn't. + ac_save_CFLAGS="$CFLAGS" + CFLAGS="-Wimplicit-function-declaration -Werror" + AC_TRY_COMPILE([#define _GNU_SOURCE 1 + #include + #include ], + [char s[128]; strerror_r(5, s, 128);], + AC_DEFINE(HAVE_STRERROR_R, 1, + [Define if strerror_r is available in .]),) + CFLAGS="$ac_save_CFLAGS" + # Set configure bits for specified locale package + AC_MSG_CHECKING([for C locale to use]) case ${enable_clocale_flag} in generic) AC_MSG_RESULT(generic) Index: libgfortran/runtime/environ.c =================================================================== --- libgfortran/runtime/environ.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ libgfortran/runtime/environ.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -861,14 +861,13 @@ static int do_parse (void) { - int tok, def; + int tok; int unit1; int continue_ulist; char *start; unit_count = 0; - def = 0; start = p; /* Parse the string. First, let's look for a default. */ @@ -923,6 +922,7 @@ break; case END: + def = endian; goto end; break; @@ -939,6 +939,18 @@ tok = next_token (); switch (tok) { + case NATIVE: + if (next_token () != ':') + goto error; + endian = CONVERT_NATIVE; + break; + + case SWAP: + if (next_token () != ':') + goto error; + endian = CONVERT_SWAP; + break; + case LITTLE: if (next_token () != ':') goto error; Index: libgfortran/intrinsics/reshape_generic.c =================================================================== --- libgfortran/intrinsics/reshape_generic.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ libgfortran/intrinsics/reshape_generic.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -266,7 +266,7 @@ else { scount[n]++; - sptr += sstride[n] * size; + src += sstride[n] * size; } } } Index: libgfortran/intrinsics/ishftc.c =================================================================== --- libgfortran/intrinsics/ishftc.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ libgfortran/intrinsics/ishftc.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -36,8 +36,7 @@ GFC_INTEGER_4 ishftc4 (GFC_INTEGER_4 i, GFC_INTEGER_4 shift, GFC_INTEGER_4 size) { - GFC_INTEGER_4 mask; - GFC_UINTEGER_4 bits; + GFC_UINTEGER_4 mask, bits; if (shift < 0) shift = shift + size; @@ -45,9 +44,14 @@ if (shift == 0 || shift == size) return i; - mask = (~(GFC_INTEGER_4)0) << size; - bits = i & ~mask; - return (i & mask) | (bits >> (size - shift)) | ((i << shift) & ~mask); + /* In C, the result of the shift operator is undefined if the right operand + is greater than or equal to the number of bits in the left operand. So we + have to special case it for fortran. */ + mask = ~((size == 32) ? 0 : (~0 << size)); + + bits = i & mask; + + return (i & ~mask) | ((bits << shift) & mask) | (bits >> (size - shift)); } extern GFC_INTEGER_8 ishftc8 (GFC_INTEGER_8, GFC_INTEGER_4, GFC_INTEGER_4); @@ -56,8 +60,7 @@ GFC_INTEGER_8 ishftc8 (GFC_INTEGER_8 i, GFC_INTEGER_4 shift, GFC_INTEGER_4 size) { - GFC_INTEGER_8 mask; - GFC_UINTEGER_8 bits; + GFC_UINTEGER_8 mask, bits; if (shift < 0) shift = shift + size; @@ -65,9 +68,14 @@ if (shift == 0 || shift == size) return i; - mask = (~(GFC_INTEGER_8)0) << size; - bits = i & ~mask; - return (i & mask) | (bits >> (size - shift)) | ((i << shift) & ~mask); + /* In C, the result of the shift operator is undefined if the right operand + is greater than or equal to the number of bits in the left operand. So we + have to special case it for fortran. */ + mask = ~((size == 64) ? 0 : (~0 << size)); + + bits = i & mask; + + return (i & ~mask) | ((bits << shift) & mask) | (bits >> (size - shift)); } #ifdef HAVE_GFC_INTEGER_16 @@ -77,8 +85,7 @@ GFC_INTEGER_16 ishftc16 (GFC_INTEGER_16 i, GFC_INTEGER_4 shift, GFC_INTEGER_4 size) { - GFC_INTEGER_16 mask; - GFC_UINTEGER_16 bits; + GFC_UINTEGER_16 mask, bits; if (shift < 0) shift = shift + size; @@ -86,8 +93,13 @@ if (shift == 0 || shift == size) return i; - mask = (~(GFC_INTEGER_16)0) << size; - bits = i & ~mask; - return (i & mask) | (bits >> (size - shift)) | ((i << shift) & ~mask); + /* In C, the result of the shift operator is undefined if the right operand + is greater than or equal to the number of bits in the left operand. So we + have to special case it for fortran. */ + mask = ~((size == 128) ? 0 : (~0 << size)); + + bits = i & mask; + + return (i & ~mask) | ((bits << shift) & mask) | (bits >> (size - shift)); } #endif Index: libgfortran/ChangeLog =================================================================== --- libgfortran/ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ libgfortran/ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,53 @@ +2007-05-23 Jerry DeLisle + + PR libfortran/31964 + Backport from trunk. + * intrinsics/ishftc.c (ishftc4, ishftc8, ishftc16): Fix mask to handle + shift of bit-size number of bits. + +2007-05-23 Tobias Burnus + + PR fortran/31917 + Backport from trunk. + * runtime/environ.c (mark_range): Fix setting default convert unit. + +2007-05-22 Jerry DeLisle + + PR libfortran/31051 + Backport from trunk. + * io/transfer.c (formatted_transfer_scalar): Adjust position for pending + spaces when in writing mode. Clean up some formatting. + +2007-05-22 Tobias Burnus + + PR libfortran/31915 + Backport from trunk. + * io/transfer.c (unformatted_read): Use proper size for real(10). + (unformatted_write): Ditto. + +2007-05-20 Jerry DeLisle + + PR libfortran/31395 + Backport from 4.3. + * io/format.c (parse_format_list): Fix parsing. Regression against g77. + +2007-05-20 Thomas Koenig + + PR fortran/31618 + Backport from trunk. + * io/transfer.c (read_block_direct): Instead of calling us_read, + set dtp->u.p.current_unit->current_record = 0 so that pre_position + will read the record marker. + (data_transfer_init): For different error conditions, call + generate_error, then return. + +2007-05-20 Thomas Koenig + + PR libfortran/31196 + Backport from trunk. + * intrinsics/reshape_generic.c (reshape_internal): Increment + correct variable. + 2007-05-13 Release Manager * GCC 4.2.0 released. Index: libgfortran/io/transfer.c =================================================================== --- libgfortran/io/transfer.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ libgfortran/io/transfer.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -493,11 +493,11 @@ } else { - /* Let's make sure the file position is correctly set for the - next read statement. */ + /* Let's make sure the file position is correctly pre-positioned + for the next read statement. */ + dtp->u.p.current_unit->current_record = 0; next_record_r_unf (dtp, 0); - us_read (dtp, 0); generate_error (&dtp->common, ERROR_SHORT_RECORD, NULL); return; } @@ -722,7 +722,11 @@ of the padding. If we hit a short record, then sz is adjusted accordingly, making later reads no-ops. */ - sz = kind; + if (type == BT_REAL || type == BT_COMPLEX) + sz = size_from_real_kind (kind); + else + sz = kind; + for (i=0; iu.n + dtp->u.p.skips; dtp->u.p.skips = f->u.n + dtp->u.p.skips; @@ -1160,6 +1168,7 @@ write_x (dtp, dtp->u.p.skips, dtp->u.p.pending_spaces); dtp->u.p.skips = dtp->u.p.pending_spaces = 0; } + if (dtp->u.p.mode == READING) read_x (dtp, f->u.n); @@ -1167,6 +1176,8 @@ case FMT_TL: case FMT_T: + consume_data_flag = 0; + if (f->format == FMT_TL) { @@ -1185,8 +1196,10 @@ } else /* FMT_T */ { - consume_data_flag = 0; - pos = f->u.n - 1; + if (dtp->u.p.mode == READING) + pos = f->u.n - 1; + else + pos = f->u.n - dtp->u.p.pending_spaces - 1; } /* Standard 10.6.1.1: excessive left tabbing is reset to the @@ -1753,16 +1766,19 @@ /* Check the action. */ if (read_flag && dtp->u.p.current_unit->flags.action == ACTION_WRITE) - generate_error (&dtp->common, ERROR_BAD_ACTION, - "Cannot read from file opened for WRITE"); + { + generate_error (&dtp->common, ERROR_BAD_ACTION, + "Cannot read from file opened for WRITE"); + return; + } if (!read_flag && dtp->u.p.current_unit->flags.action == ACTION_READ) - generate_error (&dtp->common, ERROR_BAD_ACTION, - "Cannot write to file opened for READ"); + { + generate_error (&dtp->common, ERROR_BAD_ACTION, + "Cannot write to file opened for READ"); + return; + } - if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK) - return; - dtp->u.p.first_item = 1; /* Check the format. */ @@ -1770,14 +1786,14 @@ if ((cf & IOPARM_DT_HAS_FORMAT) != 0) parse_format (dtp); - if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK) - return; - if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED && (cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT)) != 0) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "Format present for UNFORMATTED data transfer"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "Format present for UNFORMATTED data transfer"); + return; + } if ((cf & IOPARM_DT_HAS_NAMELIST_NAME) != 0 && dtp->u.p.ionml != NULL) { @@ -1787,13 +1803,19 @@ } else if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED && !(cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT))) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "Missing format for FORMATTED data transfer"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "Missing format for FORMATTED data transfer"); + } if (is_internal_unit (dtp) && dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "Internal file cannot be accessed by UNFORMATTED data transfer"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "Internal file cannot be accessed by UNFORMATTED " + "data transfer"); + return; + } /* Check the record or position number. */ @@ -1823,49 +1845,71 @@ if (dtp->u.p.advance_status != ADVANCE_UNSPECIFIED) { if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "ADVANCE specification conflicts with sequential access"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "ADVANCE specification conflicts with sequential access"); + return; + } if (is_internal_unit (dtp)) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "ADVANCE specification conflicts with internal file"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "ADVANCE specification conflicts with internal file"); + return; + } if ((cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT)) != IOPARM_DT_HAS_FORMAT) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "ADVANCE specification requires an explicit format"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "ADVANCE specification requires an explicit format"); + return; + } } if (read_flag) { if ((cf & IOPARM_EOR) != 0 && dtp->u.p.advance_status != ADVANCE_NO) - generate_error (&dtp->common, ERROR_MISSING_OPTION, - "EOR specification requires an ADVANCE specification of NO"); + { + generate_error (&dtp->common, ERROR_MISSING_OPTION, + "EOR specification requires an ADVANCE specification " + "of NO"); + return; + } if ((cf & IOPARM_DT_HAS_SIZE) != 0 && dtp->u.p.advance_status != ADVANCE_NO) - generate_error (&dtp->common, ERROR_MISSING_OPTION, - "SIZE specification requires an ADVANCE specification of NO"); - + { + generate_error (&dtp->common, ERROR_MISSING_OPTION, + "SIZE specification requires an ADVANCE specification of NO"); + return; + } } else { /* Write constraints. */ if ((cf & IOPARM_END) != 0) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "END specification cannot appear in a write statement"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "END specification cannot appear in a write statement"); + return; + } if ((cf & IOPARM_EOR) != 0) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "EOR specification cannot appear in a write statement"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "EOR specification cannot appear in a write statement"); + return; + } if ((cf & IOPARM_DT_HAS_SIZE) != 0) - generate_error (&dtp->common, ERROR_OPTION_CONFLICT, - "SIZE specification cannot appear in a write statement"); + { + generate_error (&dtp->common, ERROR_OPTION_CONFLICT, + "SIZE specification cannot appear in a write statement"); + return; + } } if (dtp->u.p.advance_status == ADVANCE_UNSPECIFIED) dtp->u.p.advance_status = ADVANCE_YES; - if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK) - return; /* Sanity checks on the record number. */ if ((cf & IOPARM_DT_HAS_REC) != 0) Index: libgfortran/io/format.c =================================================================== --- libgfortran/io/format.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ libgfortran/io/format.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -860,10 +860,11 @@ case FMT_SLASH: get_fnode (fmt, &head, &tail, FMT_SLASH); tail->repeat = 1; + goto optional_comma; - /* Fall Through */ - case FMT_COLON: + get_fnode (fmt, &head, &tail, FMT_COLON); + tail->repeat = 1; goto optional_comma; case FMT_END: Index: boehm-gc/darwin_stop_world.c =================================================================== --- boehm-gc/darwin_stop_world.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/darwin_stop_world.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -10,7 +10,7 @@ be allocated, is called the red zone. This area as shown in Figure 3-2 may be used for any purpose as long as a new stack frame does not need to be added to the stack." - + Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then it must set up a stack frame just like routines that call other routines." */ @@ -20,48 +20,6 @@ # define PPC_RED_ZONE_SIZE 320 #endif -/* Try to work out the right way to access thread state structure members. - The structure has changed its definition in different Darwin versions. */ -#if defined(__ppc__) -# define THREAD_STATE ppc_thread_state_t -# if defined (HAS_PPC_THREAD_STATE_R0) -# define THREAD_FLD(x) x -# elif defined (HAS_PPC_THREAD_STATE___R0) -# define THREAD_FLD(x) __ ## x -# else -# error can not work out how to access fields of ppc_thread_state_t -# endif -#elif defined(__ppc64__) -# define THREAD_STATE ppc_thread_state64_t -# if defined (HAS_PPC_THREAD_STATE64_R0) -# define THREAD_FLD(x) x -# elif defined (HAS_PPC_THREAD_STATE64___R0) -# define THREAD_FLD(x) __ ## x -# else -# error can not work out how to access fields of ppc_thread_state64_t -# endif -#elif defined(__i386__) -# define THREAD_STATE i386_thread_state_t -# if defined (HAS_I386_THREAD_STATE_EAX) -# define THREAD_FLD(x) x -# elif defined (HAS_I386_THREAD_STATE___EAX) -# define THREAD_FLD(x) __ ## x -# else -# error can not work out how to access fields of i386_thread_state_t -# endif -#elif defined(__x86_64__) -# define THREAD_STATE i386_thread_state_t -# if defined (HAS_I386_THREAD_STATE_EAX) -# define THREAD_FLD(x) x -# elif defined (HAS_I386_THREAD_STATE___EAX) -# define THREAD_FLD(x) __ ## x -# else -# error can not work out how to access fields of i386_thread_state_t -# endif -#else -# error unknown architecture -#endif - typedef struct StackFrame { unsigned long savedSP; unsigned long savedCR; @@ -115,8 +73,8 @@ GC_thread p; pthread_t me; ptr_t lo, hi; - THREAD_STATE state; - mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT; + GC_THREAD_STATE_T state; + mach_msg_type_number_t thread_state_count = GC_MACH_THREAD_STATE_COUNT; me = pthread_self(); if (!GC_thr_initialized) GC_thr_init(); @@ -128,11 +86,8 @@ lo = GC_approx_sp(); } else { /* Get the thread state (registers, etc) */ - r = thread_get_state( - p->stop_info.mach_thread, - MACHINE_THREAD_STATE, - (natural_t*)&state, - &thread_state_count); + r = thread_get_state(p->stop_info.mach_thread, GC_MACH_THREAD_STATE, + (natural_t*)&state, &thread_state_count); if(r != KERN_SUCCESS) ABORT("thread_get_state failed"); #if defined(I386) @@ -144,7 +99,33 @@ GC_push_one(state . THREAD_FLD (edx)); GC_push_one(state . THREAD_FLD (edi)); GC_push_one(state . THREAD_FLD (esi)); - GC_push_one(state . THREAD_FLD (ebp)); + GC_push_one(state . THREAD_FLD (ebp)); + +#elif defined(X86_64) + lo = (void*)state . THREAD_FLD (rsp); + + GC_push_one(state . THREAD_FLD (rax)); + GC_push_one(state . THREAD_FLD (rbx)); + GC_push_one(state . THREAD_FLD (rcx)); + GC_push_one(state . THREAD_FLD (rdx)); + GC_push_one(state . THREAD_FLD (rdi)); + GC_push_one(state . THREAD_FLD (rsi)); + GC_push_one(state . THREAD_FLD (rbp)); + GC_push_one(state . THREAD_FLD (rsp)); + GC_push_one(state . THREAD_FLD (r8)); + GC_push_one(state . THREAD_FLD (r9)); + GC_push_one(state . THREAD_FLD (r10)); + GC_push_one(state . THREAD_FLD (r11)); + GC_push_one(state . THREAD_FLD (r12)); + GC_push_one(state . THREAD_FLD (r13)); + GC_push_one(state . THREAD_FLD (r14)); + GC_push_one(state . THREAD_FLD (r15)); + GC_push_one(state . THREAD_FLD (rip)); + GC_push_one(state . THREAD_FLD (rflags)); + GC_push_one(state . THREAD_FLD (cs)); + GC_push_one(state . THREAD_FLD (fs)); + GC_push_one(state . THREAD_FLD (gs)); + #elif defined(POWERPC) lo = (void*)(state . THREAD_FLD (r1) - PPC_RED_ZONE_SIZE); @@ -221,9 +202,9 @@ hi = (ptr_t)FindTopOfStack(0); } else { # if defined(__ppc__) || defined(__ppc64__) - THREAD_STATE info; + GC_THREAD_STATE_T info; mach_msg_type_number_t outCount = THREAD_STATE_MAX; - r = thread_get_state(thread, MACHINE_THREAD_STATE, + r = thread_get_state(thread, GC_MACH_THREAD_STATE, (natural_t *)&info, &outCount); if(r != KERN_SUCCESS) ABORT("task_get_state failed"); @@ -264,10 +245,10 @@ # else /* FIXME: Remove after testing: */ WARN("This is completely untested and likely will not work\n", 0); - THREAD_STATE info; + GC_THREAD_STATE_T info; mach_msg_type_number_t outCount = THREAD_STATE_MAX; - r = thread_get_state(thread, MACHINE_THREAD_STATE, - (natural_t *)&info, &outCount); + r = thread_get_state(thread, GC_MACH_THREAD_STATE, (natural_t *)&info, + &outCount); if(r != KERN_SUCCESS) ABORT("task_get_state failed"); lo = (void*)info . THREAD_FLD (esp); Index: boehm-gc/Makefile.in =================================================================== --- boehm-gc/Makefile.in (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/Makefile.in (.../branches/gcc-4_2-branch) (revision 125292) @@ -224,6 +224,7 @@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ +extra_ldflags_libgc = @extra_ldflags_libgc@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -280,7 +281,7 @@ # linuxthread semaphore functions get linked: libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS) $(UNWINDLIBS) libgcjgc_la_DEPENDENCIES = @addobjs@ -libgcjgc_la_LDFLAGS = -version-info 1:2:0 -rpath $(toolexeclibdir) +libgcjgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info 1:2:0 -rpath $(toolexeclibdir) libgcjgc_convenience_la_LIBADD = @addobjs@ libgcjgc_convenience_la_DEPENDENCIES = @addobjs@ AM_CXXFLAGS = @GC_CFLAGS@ Index: boehm-gc/configure.ac =================================================================== --- boehm-gc/configure.ac (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/configure.ac (.../branches/gcc-4_2-branch) (revision 125292) @@ -248,33 +248,46 @@ case "$host" in powerpc*-*-darwin*) AC_CHECK_MEMBER(ppc_thread_state_t.r0, - AC_DEFINE(HAS_PPC_THREAD_STATE_R0,,[ppc_thread_state_t has field r0]),, + AC_DEFINE(HAS_PPC_THREAD_STATE_R0,1, + [ppc_thread_state_t has field r0]),, [#include ]) AC_CHECK_MEMBER(ppc_thread_state_t.__r0, - AC_DEFINE(HAS_PPC_THREAD_STATE___R0,,dnl - [ppc_thread_state_t has field __r0]),, + AC_DEFINE(HAS_PPC_THREAD_STATE___R0,1,dnl + [ppc_thread_state_t has field __r0]),, [#include ]) AC_CHECK_MEMBER(ppc_thread_state64_t.r0, - AC_DEFINE(HAS_PPC_THREAD_STATE64_R0,,dnl - [ppc_thread_state64_t has field r0]),, + AC_DEFINE(HAS_PPC_THREAD_STATE64_R0,1,dnl + [ppc_thread_state64_t has field r0]),, [#include ]) AC_CHECK_MEMBER(ppc_thread_state64_t.__r0, - AC_DEFINE(HAS_PPC_THREAD_STATE64___R0,,dnl - [ppc_thread_state64_t has field __r0]),, + AC_DEFINE(HAS_PPC_THREAD_STATE64___R0,1,dnl + [ppc_thread_state64_t has field __r0]),, [#include ]) ;; i?86*-*-darwin*) - AC_CHECK_MEMBER(i386_thread_state_t.eax, - AC_DEFINE(HAS_I386_THREAD_STATE_EAX,,dnl - [i386_thread_state_t has field eax]),, + AC_CHECK_MEMBER(x86_thread_state32_t.eax, + AC_DEFINE(HAS_X86_THREAD_STATE32_EAX,1,dnl + [x86_thread_state32_t has field eax]),, [#include -#include ]) - AC_CHECK_MEMBER(i386_thread_state_t.__eax, - AC_DEFINE(HAS_I386_THREAD_STATE___EAX,,dnl - [i386_thread_state_t has field __eax]),, + #include ]) + AC_CHECK_MEMBER(x86_thread_state32_t.__eax, + AC_DEFINE(HAS_X86_THREAD_STATE32___EAX,1,dnl + [x86_thread_state32_t has field __eax]),, [#include -#include ]) + #include ]) ;; + x86_64-*-darwin*) + AC_CHECK_MEMBER(x86_thread_state64_t.rax, + AC_DEFINE(HAS_X86_THREAD_STATE64_RAX,1,dnl + [x86_thread_state64_t has field rax]),, + [#include + #include ]) + AC_CHECK_MEMBER(x86_thread_state64_t.__rax, + AC_DEFINE(HAS_X86_THREAD_STATE64___RAX,1,dnl + [x86_thread_state64_t has field __rax]),, + [#include + #include ]) + ;; *) ;; esac @@ -287,6 +300,14 @@ ;; esac +# extra LD Flags which are required for targets +case "${host}" in + *-*-darwin*) + extra_ldflags_libgc=-Wl,-single_module + ;; +esac +AC_SUBST(extra_ldflags_libgc) + AC_SUBST(EXTRA_TEST_LIBS) target_all=libgcjgc.la Index: boehm-gc/include/Makefile.in =================================================================== --- boehm-gc/include/Makefile.in (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/include/Makefile.in (.../branches/gcc-4_2-branch) (revision 125292) @@ -149,6 +149,7 @@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ +extra_ldflags_libgc = @extra_ldflags_libgc@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ Index: boehm-gc/include/gc_config.h.in =================================================================== --- boehm-gc/include/gc_config.h.in (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/include/gc_config.h.in (.../branches/gcc-4_2-branch) (revision 125292) @@ -54,12 +54,6 @@ /* support for win32 threads */ #undef GC_WIN32_THREADS -/* i386_thread_state_t has field eax */ -#undef HAS_I386_THREAD_STATE_EAX - -/* i386_thread_state_t has field __eax */ -#undef HAS_I386_THREAD_STATE___EAX - /* ppc_thread_state64_t has field r0 */ #undef HAS_PPC_THREAD_STATE64_R0 @@ -72,6 +66,18 @@ /* ppc_thread_state_t has field __r0 */ #undef HAS_PPC_THREAD_STATE___R0 +/* x86_thread_state32_t has field eax */ +#undef HAS_X86_THREAD_STATE32_EAX + +/* x86_thread_state32_t has field __eax */ +#undef HAS_X86_THREAD_STATE32___EAX + +/* x86_thread_state64_t has field rax */ +#undef HAS_X86_THREAD_STATE64_RAX + +/* x86_thread_state64_t has field __rax */ +#undef HAS_X86_THREAD_STATE64___RAX + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H Index: boehm-gc/include/private/gc_priv.h =================================================================== --- boehm-gc/include/private/gc_priv.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/include/private/gc_priv.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -286,6 +286,53 @@ #endif +#if defined(DARWIN) +# if defined(POWERPC) +# if CPP_WORDSZ == 32 +# define GC_THREAD_STATE_T ppc_thread_state_t +# define GC_MACH_THREAD_STATE PPC_THREAD_STATE +# define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT +# define GC_MACH_HEADER mach_header +# define GC_MACH_SECTION section +# else +# define GC_THREAD_STATE_T ppc_thread_state64_t +# define GC_MACH_THREAD_STATE PPC_THREAD_STATE64 +# define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT +# define GC_MACH_HEADER mach_header_64 +# define GC_MACH_SECTION section_64 +# endif +# elif defined(I386) || defined(X86_64) +# if CPP_WORDSZ == 32 +# define GC_THREAD_STATE_T x86_thread_state32_t +# define GC_MACH_THREAD_STATE x86_THREAD_STATE32 +# define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT +# define GC_MACH_HEADER mach_header +# define GC_MACH_SECTION section +# else +# define GC_THREAD_STATE_T x86_thread_state64_t +# define GC_MACH_THREAD_STATE x86_THREAD_STATE64 +# define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT +# define GC_MACH_HEADER mach_header_64 +# define GC_MACH_SECTION section_64 +# endif +# else +# error define GC_THREAD_STATE_T +# define GC_MACH_THREAD_STATE MACHINE_THREAD_STATE +# define GC_MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT +# endif +/* Try to work out the right way to access thread state structure members. + The structure has changed its definition in different Darwin versions. + This now defaults to the (older) names without __, thus hopefully, + not breaking any existing Makefile.direct builds. */ +# if defined (HAS_PPC_THREAD_STATE___R0) \ + || defined (HAS_PPC_THREAD_STATE64___R0) \ + || defined (HAS_X86_THREAD_STATE32___EAX) \ + || defined (HAS_X86_THREAD_STATE64___RAX) +# define THREAD_FLD(x) __ ## x +# else +# define THREAD_FLD(x) x +# endif +#endif /*********************************/ /* */ /* OS interface routines */ @@ -468,6 +515,53 @@ # define GETENV(name) 0 #endif +#if defined(DARWIN) +# if defined(POWERPC) +# if CPP_WORDSZ == 32 +# define GC_THREAD_STATE_T ppc_thread_state_t +# define GC_MACH_THREAD_STATE PPC_THREAD_STATE +# define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT +# define GC_MACH_HEADER mach_header +# define GC_MACH_SECTION section +# else +# define GC_THREAD_STATE_T ppc_thread_state64_t +# define GC_MACH_THREAD_STATE PPC_THREAD_STATE64 +# define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT +# define GC_MACH_HEADER mach_header_64 +# define GC_MACH_SECTION section_64 +# endif +# elif defined(I386) || defined(X86_64) +# if CPP_WORDSZ == 32 +# define GC_THREAD_STATE_T x86_thread_state32_t +# define GC_MACH_THREAD_STATE x86_THREAD_STATE32 +# define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT +# define GC_MACH_HEADER mach_header +# define GC_MACH_SECTION section +# else +# define GC_THREAD_STATE_T x86_thread_state64_t +# define GC_MACH_THREAD_STATE x86_THREAD_STATE64 +# define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT +# define GC_MACH_HEADER mach_header_64 +# define GC_MACH_SECTION section_64 +# endif +# else +# error define GC_THREAD_STATE_T +# define GC_MACH_THREAD_STATE MACHINE_THREAD_STATE +# define GC_MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT +# endif +/* Try to work out the right way to access thread state structure members. + The structure has changed its definition in different Darwin versions. + This now defaults to the (older) names without __, thus hopefully, + not breaking any existing Makefile.direct builds. */ +# if defined (HAS_PPC_THREAD_STATE___R0) \ + || defined (HAS_PPC_THREAD_STATE64___R0) \ + || defined (HAS_X86_THREAD_STATE32___EAX) \ + || defined (HAS_X86_THREAD_STATE64___RAX) +# define THREAD_FLD(x) __ ## x +# else +# define THREAD_FLD(x) x +# endif +#endif /*********************************/ /* */ /* Word-size-dependent defines */ Index: boehm-gc/include/private/gcconfig.h =================================================================== --- boehm-gc/include/private/gcconfig.h (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/include/private/gcconfig.h (.../branches/gcc-4_2-branch) (revision 125292) @@ -302,7 +302,10 @@ # if defined(__ppc__) || defined(__ppc64__) # define POWERPC # define mach_type_known -# elif defined(__i386__) || defined(__x86_64) +# elif defined(__x86_64__) +# define X86_64 +# define mach_type_known +# elif defined(__i386__) # define I386 # define mach_type_known # endif @@ -791,26 +794,29 @@ # define DATAEND (_end) # endif # ifdef DARWIN -# if defined(__ppc64__) || defined(__x86_64) +# define OS_TYPE "DARWIN" +# define DYNAMIC_LOADING +# if defined(__ppc64__) # define ALIGNMENT 8 # define CPP_WORDSZ 64 +# define STACKBOTTOM ((ptr_t) 0x7fff5fc00000) +# define CACHE_LINE_SIZE 64 +# ifndef HBLKSIZE +# define HBLKSIZE 4096 +# endif # else # define ALIGNMENT 4 +# define STACKBOTTOM ((ptr_t) 0xc0000000) # endif -# define OS_TYPE "DARWIN" -# define DYNAMIC_LOADING /* XXX: see get_end(3), get_etext() and get_end() should not be used. - These aren't used when dyld support is enabled (it is by default) */ + These aren't used when dyld support is enabled (it is by default) */ # define DATASTART ((ptr_t) get_etext()) # define DATAEND ((ptr_t) get_end()) -# define STACKBOTTOM ((ptr_t) 0xc0000000) # define USE_MMAP # define USE_MMAP_ANON # define USE_ASM_PUSH_REGS - /* This is potentially buggy. It needs more testing. See the comments in - os_dep.c. It relies on threads to track writes. */ # ifdef GC_DARWIN_THREADS -/* # define MPROTECT_VDB -- diabled for now. May work for some apps. */ +# define MPROTECT_VDB # endif # include # define GETPAGESIZE() getpagesize() @@ -822,7 +828,7 @@ __asm__ __volatile__ ("dcbtst 0,%0" : : "r" ((const void *) (x))) # endif /* There seems to be some issues with trylock hanging on darwin. This - should be looked into some more */ + should be looked into some more */ # define NO_PTHREAD_TRYLOCK # endif # ifdef FREEBSD @@ -1317,23 +1323,21 @@ # define DARWIN_DONT_PARSE_STACK # define DYNAMIC_LOADING /* XXX: see get_end(3), get_etext() and get_end() should not be used. - These aren't used when dyld support is enabled (it is by default) */ + These aren't used when dyld support is enabled (it is by default) */ # define DATASTART ((ptr_t) get_etext()) # define DATAEND ((ptr_t) get_end()) # define STACKBOTTOM ((ptr_t) 0xc0000000) # define USE_MMAP # define USE_MMAP_ANON # define USE_ASM_PUSH_REGS - /* This is potentially buggy. It needs more testing. See the comments in - os_dep.c. It relies on threads to track writes. */ # ifdef GC_DARWIN_THREADS -/* # define MPROTECT_VDB -- disabled for now. May work for some apps. */ +# define MPROTECT_VDB # endif # include # define GETPAGESIZE() getpagesize() /* There seems to be some issues with trylock hanging on darwin. This - should be looked into some more */ -# define NO_PTHREAD_TRYLOCK + should be looked into some more */ +# define NO_PTHREAD_TRYLOCK # endif /* DARWIN */ # endif @@ -1986,6 +1990,26 @@ # define PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1) # endif # endif +# ifdef DARWIN +# define OS_TYPE "DARWIN" +# define DARWIN_DONT_PARSE_STACK +# define DYNAMIC_LOADING + /* XXX: see get_end(3), get_etext() and get_end() should not be used. + These aren't used when dyld support is enabled (it is by default) */ +# define DATASTART ((ptr_t) get_etext()) +# define DATAEND ((ptr_t) get_end()) +# define STACKBOTTOM ((ptr_t) 0x7fff5fc00000) +# define USE_MMAP +# define USE_MMAP_ANON +# ifdef GC_DARWIN_THREADS +# define MPROTECT_VDB +# endif +# include +# define GETPAGESIZE() getpagesize() + /* There seems to be some issues with trylock hanging on darwin. This + should be looked into some more */ +# define NO_PTHREAD_TRYLOCK +# endif # ifdef FREEBSD # define OS_TYPE "FREEBSD" # ifndef GC_FREEBSD_THREADS Index: boehm-gc/ChangeLog =================================================================== --- boehm-gc/ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,67 @@ +2007-05-22 Andreas Tobler + + * Backport r124870 from main. + + 2007-05-20 Andreas Tobler + + * configure.ac: Introduce extra_ldflags_libgc. Use it for Darwin. + * configure: Regenerate. + * Makefile.am (libgc_la_LDFLAGS): Use extra_ldflags_libgc. + * Makefile.in: Regenerate. + * include/Makefile.in: Regenerate. + * include/private/gcconfig.h: Enable MPROTECT_VDB for all Darwin + targets. Remove comments. Prepare ppc64 support for Darwin. + +2007-05-19 Andreas Tobler + + * Backport r120684, 120801, 120853, 120874 and 120977 from main. + + 2007-01-19 Andreas Tobler + + * os_dep.c (defined(MPROTECT_VDB) && defined(DARWIN)): Moved recently + added defines to include/private/gc_priv.h + * darwin_stop_world.c: Removed the above defines. + (catch_exception_raise): Added THREAD_FLD in exc_state for POWERPC too. + * include/private/gc_priv.h: Moved definitions from darwin_stop_world.c + and os_dep.c to here. Fixed THREAD definition fixes for ppc64. + + 2007-01-17 Mike Stump + + * os_dep.c: Fix i686-apple-darwin9 builds. + + 2007-01-17 Andreas Tobler + + * include/gc_config.h.in: Regenerate. + + 2007-01-15 Andreas Tobler + + * os_dep.c (defined(MPROTECT_VDB) && defined(DARWIN)): Adjust mail + reference. + (catch_exception_raise): Fix typo in the I386 exc_state. + + 2007-01-11 Andreas Tobler + + * configure.ac: Replaced HAS_I386_THREAD_STATE_* with + HAS_X86_THREAD_STATE32_* and HAS_X86_THREAD_STATE64_* respectively. + * configure: Regenerated. + * include/private/gcconfig.h (DARWIN): Added X86_64 define for Darwin. + Added base definitions for the X86_64 Darwin port. + * include/private/gc_priv.h: Added definitions for Darwin MACH thread + operations. Moved existing THREAD_STATE info from darwin_stop_world.c. + * darwin_stop_world.c: Removed THREAD_STATE info. Added + HAS_X86_THREAD_STATE64___RAX. And replaced HAS_I386_THREAD_STATE___EAX + with HAS_X86_THREAD_STATE32___EAX. + (GC_push_all_stacks): Use GC_MACH_THREAD_STATE_COUNT. Add code for + X86_64 Darwin. + * dyn_load.c (GC_dyld_name_for_hdr): Use GC_MACH_HEADER. + (GC_dyld_image_add): Use GC_MACH_HEADER and GC_MACH_SECTION. + Distinguish between getsectbynamefromheader_64 and + getsectbynamefromheader. + (GC_dyld_image_remove): Likewise. + * os_dep.c (GC_dirty_init): Use GC_MACH_THREAD_STATE. + (catch_exception_raise): Introduce exception information for I386 and + X86_64 Darwin. Add X86_64 for exc_state.faultvaddr. + 2007-05-13 Release Manager * GCC 4.2.0 released. Index: boehm-gc/configure =================================================================== --- boehm-gc/configure (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/configure (.../branches/gcc-4_2-branch) (revision 125292) @@ -309,7 +309,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS multi_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical mkinstalldirs INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CFLAGS CXXFLAGS CCAS CCASFLAGS AS ac_ct_AS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GC_CFLAGS LN_S LIBTOOL CXXCPP CPPFLAGS THREADLIBS POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE EXTRA_TEST_LIBS target_all CPLUSPLUS_TRUE CPLUSPLUS_FALSE AM_CPPFLAGS addobjs addincludes addlibs addtests CPP EGREP MY_CFLAGS toolexecdir toolexeclibdir LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS multi_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical mkinstalldirs INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CFLAGS CXXFLAGS CCAS CCASFLAGS AS ac_ct_AS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GC_CFLAGS LN_S LIBTOOL CXXCPP CPPFLAGS THREADLIBS POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE extra_ldflags_libgc EXTRA_TEST_LIBS target_all CPLUSPLUS_TRUE CPLUSPLUS_FALSE AM_CPPFLAGS addobjs addincludes addlibs addtests CPP EGREP MY_CFLAGS toolexecdir toolexeclibdir LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -5741,7 +5741,7 @@ if test $ac_cv_member_ppc_thread_state_t_r0 = yes; then cat >>confdefs.h <<\_ACEOF -#define HAS_PPC_THREAD_STATE_R0 +#define HAS_PPC_THREAD_STATE_R0 1 _ACEOF fi @@ -5852,7 +5852,7 @@ if test $ac_cv_member_ppc_thread_state_t___r0 = yes; then cat >>confdefs.h <<\_ACEOF -#define HAS_PPC_THREAD_STATE___R0 +#define HAS_PPC_THREAD_STATE___R0 1 _ACEOF fi @@ -5963,7 +5963,7 @@ if test $ac_cv_member_ppc_thread_state64_t_r0 = yes; then cat >>confdefs.h <<\_ACEOF -#define HAS_PPC_THREAD_STATE64_R0 +#define HAS_PPC_THREAD_STATE64_R0 1 _ACEOF fi @@ -6074,16 +6074,16 @@ if test $ac_cv_member_ppc_thread_state64_t___r0 = yes; then cat >>confdefs.h <<\_ACEOF -#define HAS_PPC_THREAD_STATE64___R0 +#define HAS_PPC_THREAD_STATE64___R0 1 _ACEOF fi ;; i?86*-*-darwin*) - echo "$as_me:$LINENO: checking for i386_thread_state_t.eax" >&5 -echo $ECHO_N "checking for i386_thread_state_t.eax... $ECHO_C" >&6 -if test "${ac_cv_member_i386_thread_state_t_eax+set}" = set; then + echo "$as_me:$LINENO: checking for x86_thread_state32_t.eax" >&5 +echo $ECHO_N "checking for x86_thread_state32_t.eax... $ECHO_C" >&6 +if test "${ac_cv_member_x86_thread_state32_t_eax+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -6093,12 +6093,12 @@ cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include -#include + #include int main () { -static i386_thread_state_t ac_aggr; +static x86_thread_state32_t ac_aggr; if (ac_aggr.eax) return 0; ; @@ -6127,7 +6127,7 @@ ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_member_i386_thread_state_t_eax=yes + ac_cv_member_x86_thread_state32_t_eax=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -6139,12 +6139,12 @@ cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include -#include + #include int main () { -static i386_thread_state_t ac_aggr; +static x86_thread_state32_t ac_aggr; if (sizeof ac_aggr.eax) return 0; ; @@ -6173,30 +6173,30 @@ ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_member_i386_thread_state_t_eax=yes + ac_cv_member_x86_thread_state32_t_eax=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -ac_cv_member_i386_thread_state_t_eax=no +ac_cv_member_x86_thread_state32_t_eax=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_member_i386_thread_state_t_eax" >&5 -echo "${ECHO_T}$ac_cv_member_i386_thread_state_t_eax" >&6 -if test $ac_cv_member_i386_thread_state_t_eax = yes; then +echo "$as_me:$LINENO: result: $ac_cv_member_x86_thread_state32_t_eax" >&5 +echo "${ECHO_T}$ac_cv_member_x86_thread_state32_t_eax" >&6 +if test $ac_cv_member_x86_thread_state32_t_eax = yes; then cat >>confdefs.h <<\_ACEOF -#define HAS_I386_THREAD_STATE_EAX +#define HAS_X86_THREAD_STATE32_EAX 1 _ACEOF fi - echo "$as_me:$LINENO: checking for i386_thread_state_t.__eax" >&5 -echo $ECHO_N "checking for i386_thread_state_t.__eax... $ECHO_C" >&6 -if test "${ac_cv_member_i386_thread_state_t___eax+set}" = set; then + echo "$as_me:$LINENO: checking for x86_thread_state32_t.__eax" >&5 +echo $ECHO_N "checking for x86_thread_state32_t.__eax... $ECHO_C" >&6 +if test "${ac_cv_member_x86_thread_state32_t___eax+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -6206,12 +6206,12 @@ cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include -#include + #include int main () { -static i386_thread_state_t ac_aggr; +static x86_thread_state32_t ac_aggr; if (ac_aggr.__eax) return 0; ; @@ -6240,7 +6240,7 @@ ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_member_i386_thread_state_t___eax=yes + ac_cv_member_x86_thread_state32_t___eax=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -6252,12 +6252,12 @@ cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include -#include + #include int main () { -static i386_thread_state_t ac_aggr; +static x86_thread_state32_t ac_aggr; if (sizeof ac_aggr.__eax) return 0; ; @@ -6286,28 +6286,256 @@ ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_member_i386_thread_state_t___eax=yes + ac_cv_member_x86_thread_state32_t___eax=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -ac_cv_member_i386_thread_state_t___eax=no +ac_cv_member_x86_thread_state32_t___eax=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_member_i386_thread_state_t___eax" >&5 -echo "${ECHO_T}$ac_cv_member_i386_thread_state_t___eax" >&6 -if test $ac_cv_member_i386_thread_state_t___eax = yes; then +echo "$as_me:$LINENO: result: $ac_cv_member_x86_thread_state32_t___eax" >&5 +echo "${ECHO_T}$ac_cv_member_x86_thread_state32_t___eax" >&6 +if test $ac_cv_member_x86_thread_state32_t___eax = yes; then cat >>confdefs.h <<\_ACEOF -#define HAS_I386_THREAD_STATE___EAX +#define HAS_X86_THREAD_STATE32___EAX 1 _ACEOF fi ;; + x86_64-*-darwin*) + echo "$as_me:$LINENO: checking for x86_thread_state64_t.rax" >&5 +echo $ECHO_N "checking for x86_thread_state64_t.rax... $ECHO_C" >&6 +if test "${ac_cv_member_x86_thread_state64_t_rax+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + +int +main () +{ +static x86_thread_state64_t ac_aggr; +if (ac_aggr.rax) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_x86_thread_state64_t_rax=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + +int +main () +{ +static x86_thread_state64_t ac_aggr; +if (sizeof ac_aggr.rax) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_x86_thread_state64_t_rax=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_x86_thread_state64_t_rax=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_x86_thread_state64_t_rax" >&5 +echo "${ECHO_T}$ac_cv_member_x86_thread_state64_t_rax" >&6 +if test $ac_cv_member_x86_thread_state64_t_rax = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAS_X86_THREAD_STATE64_RAX 1 +_ACEOF + +fi + + echo "$as_me:$LINENO: checking for x86_thread_state64_t.__rax" >&5 +echo $ECHO_N "checking for x86_thread_state64_t.__rax... $ECHO_C" >&6 +if test "${ac_cv_member_x86_thread_state64_t___rax+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + +int +main () +{ +static x86_thread_state64_t ac_aggr; +if (ac_aggr.__rax) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_x86_thread_state64_t___rax=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include + +int +main () +{ +static x86_thread_state64_t ac_aggr; +if (sizeof ac_aggr.__rax) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_x86_thread_state64_t___rax=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_x86_thread_state64_t___rax=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_x86_thread_state64_t___rax" >&5 +echo "${ECHO_T}$ac_cv_member_x86_thread_state64_t___rax" >&6 +if test $ac_cv_member_x86_thread_state64_t___rax = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAS_X86_THREAD_STATE64___RAX 1 +_ACEOF + +fi + + ;; *) ;; esac @@ -6392,8 +6620,16 @@ ;; esac +# extra LD Flags which are required for targets +case "${host}" in + *-*-darwin*) + extra_ldflags_libgc=-Wl,-single_module + ;; +esac + + target_all=libgcjgc.la @@ -8246,6 +8482,7 @@ s,@THREADLIBS@,$THREADLIBS,;t t s,@POWERPC_DARWIN_TRUE@,$POWERPC_DARWIN_TRUE,;t t s,@POWERPC_DARWIN_FALSE@,$POWERPC_DARWIN_FALSE,;t t +s,@extra_ldflags_libgc@,$extra_ldflags_libgc,;t t s,@EXTRA_TEST_LIBS@,$EXTRA_TEST_LIBS,;t t s,@target_all@,$target_all,;t t s,@CPLUSPLUS_TRUE@,$CPLUSPLUS_TRUE,;t t Index: boehm-gc/os_dep.c =================================================================== --- boehm-gc/os_dep.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/os_dep.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -3371,7 +3371,7 @@ 1. Apple's mach/xnu documentation 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the omnigroup's macosx-dev list. - www.omnigroup.com/mailman/archive/macosx-dev/2000-June/002030.html + www.omnigroup.com/mailman/archive/macosx-dev/2000-June/014178.html 3. macosx-nat.c from Apple's GDB source code. */ @@ -3683,7 +3683,7 @@ mask, GC_ports.exception, EXCEPTION_DEFAULT, - MACHINE_THREAD_STATE + GC_MACH_THREAD_STATE ); if(r != KERN_SUCCESS) ABORT("task_set_exception_ports failed"); @@ -3802,10 +3802,16 @@ mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT; ppc_exception_state64_t exc_state; # endif -# elif defined(I386) - thread_state_flavor_t flavor = i386_EXCEPTION_STATE; - mach_msg_type_number_t exc_state_count = i386_EXCEPTION_STATE_COUNT; - i386_exception_state_t exc_state; +# elif defined(I386) || defined(X86_64) +# if CPP_WORDSZ == 32 + thread_state_flavor_t flavor = x86_EXCEPTION_STATE32; + mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE32_COUNT; + x86_exception_state32_t exc_state; +# else + thread_state_flavor_t flavor = x86_EXCEPTION_STATE64; + mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE64_COUNT; + x86_exception_state64_t exc_state; +# endif # else # error FIXME for non-ppc darwin # endif @@ -3838,9 +3844,9 @@ /* This is the address that caused the fault */ #if defined(POWERPC) - addr = (char*) exc_state.dar; -#elif defined (I386) - addr = (char*) exc_state.faultvaddr; + addr = (char*) exc_state. THREAD_FLD(dar); +#elif defined (I386) || defined (X86_64) + addr = (char*) exc_state. THREAD_FLD(faultvaddr); #else # error FIXME for non POWERPC/I386 #endif Index: boehm-gc/Makefile.am =================================================================== --- boehm-gc/Makefile.am (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/Makefile.am (.../branches/gcc-4_2-branch) (revision 125292) @@ -33,11 +33,13 @@ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \ sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s +extra_ldflags_libgc = @extra_ldflags_libgc@ + # Include THREADLIBS here to ensure that the correct versions of # linuxthread semaphore functions get linked: libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS) $(UNWINDLIBS) libgcjgc_la_DEPENDENCIES = @addobjs@ -libgcjgc_la_LDFLAGS = -version-info 1:2:0 -rpath $(toolexeclibdir) +libgcjgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info 1:2:0 -rpath $(toolexeclibdir) libgcjgc_convenience_la_LIBADD = @addobjs@ libgcjgc_convenience_la_DEPENDENCIES = @addobjs@ Index: boehm-gc/dyn_load.c =================================================================== --- boehm-gc/dyn_load.c (.../tags/gcc_4_2_0_release) (revision 125292) +++ boehm-gc/dyn_load.c (.../branches/gcc-4_2-branch) (revision 125292) @@ -1152,7 +1152,7 @@ }; #ifdef DARWIN_DEBUG -static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) { +static const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr) { unsigned long i,c; c = _dyld_image_count(); for(i=0;isize == 0) continue; start = slide + sec->addr; @@ -1184,11 +1189,16 @@ } /* This should never be called by a thread holding the lock */ -static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) { +static void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr, + intptr_t slide) { unsigned long start,end,i; - const struct section *sec; + const struct GC_MACH_SECTION *sec; for(i=0;isize == 0) continue; start = slide + sec->addr; Index: configure.in =================================================================== --- configure.in (.../tags/gcc_4_2_0_release) (revision 125292) +++ configure.in (.../branches/gcc-4_2-branch) (revision 125292) @@ -2419,7 +2419,13 @@ # Pass -fkeep-inline-functions for stage 1 if the GCC version supports it. CFLAGS="$CFLAGS -fkeep-inline-functions" AC_MSG_CHECKING([whether -fkeep-inline-functions is supported]) - AC_TRY_COMPILE(,, + AC_TRY_COMPILE([ +#if (__GNUC__ < 3) \ + || (__GNUC__ == 3 && (__GNUC_MINOR__ < 3 \ + || (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ < 1))) +#error http://gcc.gnu.org/PR29382 +#endif + ],, [AC_MSG_RESULT([yes]); stage1_cflags="$stage1_cflags -fkeep-inline-functions"], [AC_MSG_RESULT([no])]) Index: ChangeLog =================================================================== --- ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,9 @@ +2007-05-30 Jakub Jelinek + + PR bootstrap/29382 + * configure.in: Don't use -fkeep-inline-functions for GCC < 3.3.1. + * configure: Rebuilt. + 2007-05-13 Release Manager * GCC 4.2.0 released. Index: libjava/java/lang/natClassLoader.cc =================================================================== --- libjava/java/lang/natClassLoader.cc (.../tags/gcc_4_2_0_release) (revision 125292) +++ libjava/java/lang/natClassLoader.cc (.../branches/gcc-4_2-branch) (revision 125292) @@ -235,6 +235,15 @@ new_class->engine = &_Jv_soleIndirectCompiledEngine; + /* FIXME: Way back before the dawn of time, we overloaded the + SYNTHETIC class access modifier to mean INTERPRETED. This was a + Bad Thing, but it didn't matter then because classes were never + marked synthetic. However, it is possible to redeem the + situation: _Jv_NewClassFromInitializer is only called from + compiled classes, so we clear the INTERPRETED flag. This is a + kludge! */ + new_class->accflags &= ~java::lang::reflect::Modifier::INTERPRETED; + if (_Jv_CheckABIVersion ((unsigned long) new_class->next_or_version)) (*_Jv_RegisterClassHook) (new_class); Index: libjava/ChangeLog =================================================================== --- libjava/ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ libjava/ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,8 @@ +2007-05-31 Andrew Haley + + * java/lang/natClassLoader.cc (_Jv_NewClassFromInitializer): Clear + INTERPRETED access modifier. + 2007-05-13 Release Manager * GCC 4.2.0 released. Index: maintainer-scripts/ChangeLog =================================================================== --- maintainer-scripts/ChangeLog (.../tags/gcc_4_2_0_release) (revision 125292) +++ maintainer-scripts/ChangeLog (.../branches/gcc-4_2-branch) (revision 125292) @@ -1,3 +1,7 @@ +2007-05-28 Mark Mitchell + + * gcc_release: Adjust placement of release candidates. + 2007-05-13 Release Manager * GCC 4.2.0 released. Index: maintainer-scripts/gcc_release =================================================================== --- maintainer-scripts/gcc_release (.../tags/gcc_4_2_0_release) (revision 125292) +++ maintainer-scripts/gcc_release (.../branches/gcc-4_2-branch) (revision 125292) @@ -699,10 +699,10 @@ # and minor release numbers. SVNBRANCH="branches/gcc-${RELEASE_MAJOR}_${RELEASE_MINOR}-branch" - # If this is not a final release, set various parameters acordingly. + # If this is not a final release, set various parameters accordingly. if [ ${FINAL} -ne 1 ]; then - RELEASE="${RELEASE}-${DATE}" - FTP_PATH="${FTP_PATH}/prerelease-${RELEASE}/" + RELEASE="${RELEASE}-RC-${DATE}" + FTP_PATH="${SNAPSHOTS_DIR}/${RELEASE}" else FTP_PATH="${FTP_PATH}/releases/gcc-${RELEASE}/" fi