diff options
Diffstat (limited to 'contrib/gcc/explow.c')
-rw-r--r-- | contrib/gcc/explow.c | 132 |
1 files changed, 79 insertions, 53 deletions
diff --git a/contrib/gcc/explow.c b/contrib/gcc/explow.c index 97435a7..0d9139a 100644 --- a/contrib/gcc/explow.c +++ b/contrib/gcc/explow.c @@ -49,6 +49,10 @@ trunc_int_for_mode (c, mode) { int width = GET_MODE_BITSIZE (mode); + /* You want to truncate to a _what_? */ + if (! SCALAR_INT_MODE_P (mode)) + abort (); + /* Canonicalize BImode to 0 and STORE_FLAG_VALUE. */ if (mode == BImode) return c & 1 ? STORE_FLAG_VALUE : 0; @@ -367,6 +371,7 @@ convert_memory_address (to_mode, x) { enum machine_mode from_mode = to_mode == ptr_mode ? Pmode : ptr_mode; rtx temp; + enum rtx_code code; /* Here we handle some special cases. If none of them apply, fall through to the default case. */ @@ -374,55 +379,55 @@ convert_memory_address (to_mode, x) { case CONST_INT: case CONST_DOUBLE: - return x; + if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)) + code = TRUNCATE; + else if (POINTERS_EXTEND_UNSIGNED < 0) + break; + else if (POINTERS_EXTEND_UNSIGNED > 0) + code = ZERO_EXTEND; + else + code = SIGN_EXTEND; + temp = simplify_unary_operation (code, to_mode, x, from_mode); + if (temp) + return temp; + break; case SUBREG: - if (POINTERS_EXTEND_UNSIGNED >= 0 - && (SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x))) + if ((SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x))) && GET_MODE (SUBREG_REG (x)) == to_mode) return SUBREG_REG (x); break; case LABEL_REF: - if (POINTERS_EXTEND_UNSIGNED >= 0) - { - temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0)); - LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x); - return temp; - } + temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0)); + LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x); + return temp; break; case SYMBOL_REF: - if (POINTERS_EXTEND_UNSIGNED >= 0) - { - temp = gen_rtx_SYMBOL_REF (to_mode, XSTR (x, 0)); - SYMBOL_REF_FLAG (temp) = SYMBOL_REF_FLAG (x); - CONSTANT_POOL_ADDRESS_P (temp) = CONSTANT_POOL_ADDRESS_P (x); - STRING_POOL_ADDRESS_P (temp) = STRING_POOL_ADDRESS_P (x); - return temp; - } + temp = shallow_copy_rtx (x); + PUT_MODE (temp, to_mode); + return temp; break; case CONST: - if (POINTERS_EXTEND_UNSIGNED >= 0) - return gen_rtx_CONST (to_mode, - convert_memory_address (to_mode, XEXP (x, 0))); + return gen_rtx_CONST (to_mode, + convert_memory_address (to_mode, XEXP (x, 0))); break; case PLUS: case MULT: - /* For addition the second operand is a small constant, we can safely - permute the conversion and addition operation. We can always safely - permute them if we are making the address narrower. In addition, - always permute the operations if this is a constant. */ - if (POINTERS_EXTEND_UNSIGNED >= 0 - && (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode) - || (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT - && (INTVAL (XEXP (x, 1)) + 20000 < 40000 - || CONSTANT_P (XEXP (x, 0)))))) + /* For addition we can safely permute the conversion and addition + operation if one operand is a constant and converting the constant + does not change it. We can always safely permute them if we are + making the address narrower. */ + if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode) + || (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 1)) == CONST_INT + && XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1)))) return gen_rtx_fmt_ee (GET_CODE (x), to_mode, convert_memory_address (to_mode, XEXP (x, 0)), - convert_memory_address (to_mode, XEXP (x, 1))); + XEXP (x, 1)); break; default: @@ -650,8 +655,18 @@ maybe_set_unchanging (ref, t) /* We can set RTX_UNCHANGING_P from TREE_READONLY for decls whose initialization is only executed once, or whose initializer always has the same value. Currently we simplify this to PARM_DECLs in the - first case, and decls with TREE_CONSTANT initializers in the second. */ + first case, and decls with TREE_CONSTANT initializers in the second. + + We cannot do this for non-static aggregates, because of the double + writes that can be generated by store_constructor, depending on the + contents of the initializer. Yes, this does eliminate a good fraction + of the number of uses of RTX_UNCHANGING_P for a language like Ada. + It also eliminates a good quantity of bugs. Let this be incentive to + eliminate RTX_UNCHANGING_P entirely in favour of a more reliable + solution, perhaps based on alias sets. */ + if ((TREE_READONLY (t) && DECL_P (t) + && (TREE_STATIC (t) || ! AGGREGATE_TYPE_P (TREE_TYPE (t))) && (TREE_CODE (t) == PARM_DECL || DECL_INITIAL (t) == NULL_TREE || TREE_CONSTANT (DECL_INITIAL (t)))) @@ -816,7 +831,7 @@ copy_to_suggested_reg (x, target, mode) PUNSIGNEDP points to the signedness of the type and may be adjusted to show what signedness to use on extension operations. - FOR_CALL is non-zero if this call is promoting args for a call. */ + FOR_CALL is nonzero if this call is promoting args for a call. */ enum machine_mode promote_mode (type, mode, punsignedp, for_call) @@ -1023,7 +1038,7 @@ emit_stack_save (save_level, psave, after) if (sa != 0) sa = validize_mem (sa); emit_insn (fcn (sa, stack_pointer_rtx)); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); emit_insn_after (seq, after); } @@ -1076,7 +1091,17 @@ emit_stack_restore (save_level, sa, after) } if (sa != 0) - sa = validize_mem (sa); + { + sa = validize_mem (sa); + /* These clobbers prevent the scheduler from moving + references to variable arrays below the code + that deletes (pops) the arrays. */ + emit_insn (gen_rtx_CLOBBER (VOIDmode, + gen_rtx_MEM (BLKmode, + gen_rtx_SCRATCH (VOIDmode)))); + emit_insn (gen_rtx_CLOBBER (VOIDmode, + gen_rtx_MEM (BLKmode, stack_pointer_rtx))); + } if (after) { @@ -1084,7 +1109,7 @@ emit_stack_restore (save_level, sa, after) start_sequence (); emit_insn (fcn (stack_pointer_rtx, sa)); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); emit_insn_after (seq, after); } @@ -1216,7 +1241,7 @@ allocate_dynamic_stack_space (size, target, known_align) always know its final value at this point in the compilation (it might depend on the size of the outgoing parameter lists, for example), so we must align the value to be returned in that case. - (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if + (Note that STACK_DYNAMIC_OFFSET will have a default nonzero value if STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined). We must also do an alignment operation on the returned value if the stack pointer alignment is less strict that BIGGEST_ALIGNMENT. @@ -1389,7 +1414,7 @@ allocate_dynamic_stack_space (size, target, known_align) #ifdef SETJMP_VIA_SAVE_AREA if (setjmpless_size != NULL_RTX) { - rtx note_target = get_last_insn (); + rtx note_target = get_last_insn (); REG_NOTES (note_target) = gen_rtx_EXPR_LIST (REG_SAVE_AREA, setjmpless_size, @@ -1436,14 +1461,13 @@ allocate_dynamic_stack_space (size, target, known_align) run-time routine to call to check the stack, so provide a mechanism for calling that routine. */ -static rtx stack_check_libfunc; +static GTY(()) rtx stack_check_libfunc; void set_stack_check_libfunc (libfunc) rtx libfunc; { stack_check_libfunc = libfunc; - ggc_add_rtx_root (&stack_check_libfunc, 1); } /* Emit one stack probe at ADDRESS, an address within the stack. */ @@ -1488,9 +1512,9 @@ probe_stack_range (first, size) if (stack_check_libfunc != 0) { rtx addr = memory_address (QImode, - gen_rtx (STACK_GROW_OP, Pmode, - stack_pointer_rtx, - plus_constant (size, first))); + gen_rtx_fmt_ee (STACK_GROW_OP, Pmode, + stack_pointer_rtx, + plus_constant (size, first))); #ifdef POINTERS_EXTEND_UNSIGNED if (GET_MODE (addr) != ptr_mode) @@ -1507,9 +1531,9 @@ probe_stack_range (first, size) { insn_operand_predicate_fn pred; rtx last_addr - = force_operand (gen_rtx_STACK_GROW_OP (Pmode, - stack_pointer_rtx, - plus_constant (size, first)), + = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode, + stack_pointer_rtx, + plus_constant (size, first)), NULL_RTX); pred = insn_data[(int) CODE_FOR_check_stack].operand[0].predicate; @@ -1634,17 +1658,17 @@ hard_function_value (valtype, func, outgoing) will match and we will abort later in this function. */ for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT); - tmpmode != VOIDmode; - tmpmode = GET_MODE_WIDER_MODE (tmpmode)) - { - /* Have we found a large enough mode? */ - if (GET_MODE_SIZE (tmpmode) >= bytes) - break; - } + tmpmode != VOIDmode; + tmpmode = GET_MODE_WIDER_MODE (tmpmode)) + { + /* Have we found a large enough mode? */ + if (GET_MODE_SIZE (tmpmode) >= bytes) + break; + } /* No suitable mode found. */ if (tmpmode == VOIDmode) - abort (); + abort (); PUT_MODE (val, tmpmode); } @@ -1698,3 +1722,5 @@ rtx_to_tree_code (code) } return ((int) tcode); } + +#include "gt-explow.h" |