Submitted By: Jonathan Norman (jonathan at bluesquarelinux.co.uk) Date: 2011-07-12 Initial Package Version: 4.6.0 Origin: Upstream Upstream Status: Applied Description: Fixes a issue with Mips that causes GCC to setfault when using optimation greater than -O0. Taken from GCC Revision 174541 and applied to GCC 4.6.0 diff -Naur gcc-4.6.0.orig/gcc/expmed.c gcc-4.6.0/gcc/expmed.c --- gcc-4.6.0.orig/gcc/expmed.c 2011-07-12 16:18:33.939215981 +0000 +++ gcc-4.6.0/gcc/expmed.c 2011-07-12 16:33:51.121616152 +0000 @@ -1431,7 +1431,7 @@ unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD; unsigned int i; - if (target == 0 || !REG_P (target)) + if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target)) target = gen_reg_rtx (mode); /* Indicate for flow that the entire target reg is being set. */ diff -Naur gcc-4.6.0.orig/gcc/optabs.c gcc-4.6.0/gcc/optabs.c --- gcc-4.6.0.orig/gcc/optabs.c 2011-07-12 16:18:34.119217377 +0000 +++ gcc-4.6.0/gcc/optabs.c 2011-07-12 16:33:00.296108734 +0000 @@ -1694,7 +1694,10 @@ /* If TARGET is the same as one of the operands, the REG_EQUAL note won't be accurate, so use a new target. */ - if (target == 0 || target == op0 || target == op1) + if (target == 0 + || target == op0 + || target == op1 + || !valid_multiword_target_p (target)) target = gen_reg_rtx (mode); start_sequence (); @@ -1762,7 +1765,10 @@ /* If TARGET is the same as one of the operands, the REG_EQUAL note won't be accurate, so use a new target. */ - if (target == 0 || target == op0 || target == op1) + if (target == 0 + || target == op0 + || target == op1 + || !valid_multiword_target_p (target)) target = gen_reg_rtx (mode); start_sequence (); @@ -1816,7 +1822,11 @@ opportunities, and second because if target and op0 happen to be MEMs designating the same location, we would risk clobbering it too early in the code sequence we generate below. */ - if (target == 0 || target == op0 || target == op1 || ! REG_P (target)) + if (target == 0 + || target == op0 + || target == op1 + || !REG_P (target) + || !valid_multiword_target_p (target)) target = gen_reg_rtx (mode); start_sequence (); @@ -1936,7 +1946,7 @@ xtarget = gen_reg_rtx (mode); - if (target == 0 || !REG_P (target)) + if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target)) target = xtarget; /* Indicate for flow that the entire target reg is being set. */ @@ -2689,7 +2699,7 @@ t0 = expand_unop (word_mode, bswap_optab, operand_subword_force (op, 1, mode), NULL_RTX, true); - if (target == 0) + if (target == 0 || !valid_multiword_target_p (target)) target = gen_reg_rtx (mode); if (REG_P (target)) emit_clobber (target); @@ -2932,7 +2942,9 @@ if (code == ABS) mask = double_int_not (mask); - if (target == 0 || target == op0) + if (target == 0 + || target == op0 + || (nwords > 1 && !valid_multiword_target_p (target))) target = gen_reg_rtx (mode); if (nwords > 1) @@ -3140,7 +3152,7 @@ int i; rtx insns; - if (target == 0 || target == op0) + if (target == 0 || target == op0 || !valid_multiword_target_p (target)) target = gen_reg_rtx (mode); start_sequence (); @@ -3611,7 +3623,10 @@ mask = double_int_setbit (double_int_zero, bitpos); - if (target == 0 || target == op0 || target == op1) + if (target == 0 + || target == op0 + || target == op1 + || (nwords > 1 && !valid_multiword_target_p (target))) target = gen_reg_rtx (mode); if (nwords > 1) @@ -7330,4 +7345,21 @@ return NULL_RTX; } +/* TARGET is a target of a multiword operation that we are going to + implement as a series of word-mode operations. Return true if + TARGET is suitable for this purpose. */ + +bool +valid_multiword_target_p (rtx target) +{ + enum machine_mode mode; + int i; + + mode = GET_MODE (target); + for (i = 0; i < GET_MODE_SIZE (mode); i += UNITS_PER_WORD) + if (!validate_subreg (word_mode, mode, target, i)) + return false; + return true; +} + #include "gt-optabs.h" diff -Naur gcc-4.6.0.orig/gcc/optabs.h gcc-4.6.0/gcc/optabs.h --- gcc-4.6.0.orig/gcc/optabs.h 2011-07-12 16:18:34.119217377 +0000 +++ gcc-4.6.0/gcc/optabs.h 2011-07-12 16:24:10.888292947 +0000 @@ -923,4 +923,6 @@ extern rtx optab_libfunc (optab optab, enum machine_mode mode); extern rtx convert_optab_libfunc (convert_optab optab, enum machine_mode mode1, enum machine_mode mode2); + +extern bool valid_multiword_target_p (rtx); #endif /* GCC_OPTABS_H */ diff -Naur gcc-4.6.0.orig/gcc/testsuite/gcc.target/mips/pr45074.c gcc-4.6.0/gcc/testsuite/gcc.target/mips/pr45074.c --- gcc-4.6.0.orig/gcc/testsuite/gcc.target/mips/pr45074.c 1970-01-01 00:00:00.000000000 +0000 +++ gcc-4.6.0/gcc/testsuite/gcc.target/mips/pr45074.c 2011-07-12 16:19:49.925768556 +0000 @@ -0,0 +1,8 @@ +/* { dg-options "-mhard-float -mgp32 -O" } */ +register double g __asm__("$f20"); + +NOMIPS16 void +test (double a) +{ + g = -a; +}