diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/rs6000/predicates.md | 10 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 3 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 7 | ||||
-rw-r--r-- | gcc/jump.c | 6 |
5 files changed, 27 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 081cc1503b6..9bef3c87451 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2006-11-29 Joseph Myers <joseph@codesourcery.com> + + * config/rs6000/predicates.md (gpc_reg_operand): Check + invalid_e500_subreg. + * config/rs6000/rs6000.c (invalid_e500_subreg): Don't allow any + SImode subregs of SPE vectors. + * config/rs6000/rs6000.md (insv): Fail for invalid E500 subregs. + * jump.c (true_regnum): Require subregs to satisfy + subreg_offset_representable_p. + 2006-11-29 Daniel Berlin <dberlin@dberlin.org> Steven Bosscher <stevenb.gcc@gmail.com> diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 2ff0ba77b85..6aefe2dd0c9 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -84,10 +84,12 @@ ;; Return 1 if op is a register that is not special. (define_predicate "gpc_reg_operand" (and (match_operand 0 "register_operand") - (match_test "GET_CODE (op) != REG - || (REGNO (op) >= ARG_POINTER_REGNUM - && !XER_REGNO_P (REGNO (op))) - || REGNO (op) < MQ_REGNO"))) + (match_test "(GET_CODE (op) != REG + || (REGNO (op) >= ARG_POINTER_REGNUM + && !XER_REGNO_P (REGNO (op))) + || REGNO (op) < MQ_REGNO) + && !((TARGET_E500_DOUBLE || TARGET_SPE) + && invalid_e500_subreg (op, mode))"))) ;; Return 1 if op is a register that is a condition register field. (define_predicate "cc_reg_operand" diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 675af68fe9a..d607de26f84 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -2737,8 +2737,7 @@ invalid_e500_subreg (rtx op, enum machine_mode mode) && GET_CODE (op) == SUBREG && mode == SImode && REG_P (SUBREG_REG (op)) - && SPE_VECTOR_MODE (GET_MODE (SUBREG_REG (op))) - && SUBREG_BYTE (op) != 4) + && SPE_VECTOR_MODE (GET_MODE (SUBREG_REG (op)))) return true; return false; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index f40e78dfafa..7e1d0a19326 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -3419,9 +3419,12 @@ { /* Do not handle 16/8 bit structures that fit in HI/QI modes directly, since the (SUBREG:SI (REG:HI xxx)) that is otherwise generated can confuse the - compiler if the address of the structure is taken later. */ + compiler if the address of the structure is taken later. Likewise, do + not handle invalid E500 subregs. */ if (GET_CODE (operands[0]) == SUBREG - && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD)) + && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD + || ((TARGET_E500_DOUBLE || TARGET_SPE) + && invalid_e500_subreg (operands[0], GET_MODE (operands[0]))))) FAIL; if (TARGET_POWERPC64 && GET_MODE (operands[0]) == DImode) diff --git a/gcc/jump.c b/gcc/jump.c index 807f2c6f7d6..567017004f5 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -1951,7 +1951,11 @@ true_regnum (rtx x) if (GET_CODE (x) == SUBREG) { int base = true_regnum (SUBREG_REG (x)); - if (base >= 0 && base < FIRST_PSEUDO_REGISTER) + if (base >= 0 + && base < FIRST_PSEUDO_REGISTER + && subreg_offset_representable_p (REGNO (SUBREG_REG (x)), + GET_MODE (SUBREG_REG (x)), + SUBREG_BYTE (x), GET_MODE (x))) return base + subreg_regno_offset (REGNO (SUBREG_REG (x)), GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x), GET_MODE (x)); |