diff options
author | Michael Hayes <m.hayes@elec.canterbury.ac.nz> | 2004-01-26 00:20:07 +0000 |
---|---|---|
committer | Michael Hayes <m.hayes@gcc.gnu.org> | 2004-01-26 00:20:07 +0000 |
commit | b7bbb57472941fa0fd404dde046a1ed9f5c497f0 (patch) | |
tree | 0c8b7c14d872d59837183e2439eead3e1f7a972f /gcc/config/c4x | |
parent | 3a03ba747366916b1401a8b26a8fa28a4a97f56f (diff) | |
download | gcc-b7bbb57472941fa0fd404dde046a1ed9f5c497f0.zip gcc-b7bbb57472941fa0fd404dde046a1ed9f5c497f0.tar.gz gcc-b7bbb57472941fa0fd404dde046a1ed9f5c497f0.tar.bz2 |
c4x.c (c4x_valid_operands): More aggressively reject invalid operand combinations.
* config/c4x/c4x.c (c4x_valid_operands): More aggressively reject
invalid operand combinations.
From-SVN: r76607
Diffstat (limited to 'gcc/config/c4x')
-rw-r--r-- | gcc/config/c4x/c4x.c | 113 |
1 files changed, 79 insertions, 34 deletions
diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index 2c46ec1..4537711 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -3735,11 +3735,17 @@ c4x_valid_operands (enum rtx_code code, rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED, int force) { + rtx op0; rtx op1; rtx op2; enum rtx_code code1; enum rtx_code code2; + + /* FIXME, why can't we tighten the operands for IF_THEN_ELSE? */ + if (code == IF_THEN_ELSE) + return 1 || (operands[0] == operands[2] || operands[0] == operands[3]); + if (code == COMPARE) { op1 = operands[0]; @@ -3751,6 +3757,10 @@ c4x_valid_operands (enum rtx_code code, rtx *operands, op2 = operands[2]; } + op0 = operands[0]; + + if (GET_CODE (op0) == SUBREG) + op0 = SUBREG_REG (op0); if (GET_CODE (op1) == SUBREG) op1 = SUBREG_REG (op1); if (GET_CODE (op2) == SUBREG) @@ -3759,6 +3769,7 @@ c4x_valid_operands (enum rtx_code code, rtx *operands, code1 = GET_CODE (op1); code2 = GET_CODE (op2); + if (code1 == REG && code2 == REG) return 1; @@ -3769,6 +3780,7 @@ c4x_valid_operands (enum rtx_code code, rtx *operands, return c4x_R_indirect (op1) && c4x_R_indirect (op2); } + /* We cannot handle two MEMs or two CONSTS, etc. */ if (code1 == code2) return 0; @@ -3788,6 +3800,7 @@ c4x_valid_operands (enum rtx_code code, rtx *operands, /* Any valid memory operand screened by src_operand is OK. */ case MEM: + break; /* After CSE, any remaining (ADDRESSOF:P reg) gets converted into a stack slot memory address comprising a PLUS and a @@ -3800,54 +3813,86 @@ c4x_valid_operands (enum rtx_code code, rtx *operands, break; } + if (GET_CODE (op0) == SCRATCH) + return 1; + + if (!REG_P (op0)) + return 0; + /* Check that we have a valid destination register for a two operand instruction. */ - return ! force || code == COMPARE || REGNO (op1) == REGNO (operands[0]); + return ! force || code == COMPARE || REGNO (op1) == REGNO (op0); } - /* We assume MINUS is commutative since the subtract patterns - also support the reverse subtract instructions. Since op1 - is not a register, and op2 is a register, op1 can only - be a restricted memory operand for a shift instruction. */ + + /* Check non-commutative operators. */ if (code == ASHIFTRT || code == LSHIFTRT || code == ASHIFT || code == COMPARE) return code2 == REG && (c4x_S_indirect (op1) || c4x_R_indirect (op1)); - - switch (code1) + + + /* Assume MINUS is commutative since the subtract patterns + also support the reverse subtract instructions. Since op1 + is not a register, and op2 is a register, op1 can only + be a restricted memory operand for a shift instruction. */ + if (code2 == REG) { - case CONST_INT: - if (c4x_J_constant (op1) && c4x_R_indirect (op2)) - return 1; - break; + switch (code1) + { + case CONST_INT: + break; - case CONST_DOUBLE: - if (! c4x_H_constant (op1)) - return 0; - break; + case CONST_DOUBLE: + if (! c4x_H_constant (op1)) + return 0; + break; - /* Any valid memory operand screened by src_operand is OK. */ - case MEM: -#if 0 - if (code2 != REG) - return 0; -#endif - break; + /* Any valid memory operand screened by src_operand is OK. */ + case MEM: + break; + + /* After CSE, any remaining (ADDRESSOF:P reg) gets converted + into a stack slot memory address comprising a PLUS and a + constant. */ + case ADDRESSOF: + break; + + default: + abort (); + break; + } - /* After CSE, any remaining (ADDRESSOF:P reg) gets converted - into a stack slot memory address comprising a PLUS and a - constant. */ - case ADDRESSOF: - break; - - default: - abort (); - break; + if (GET_CODE (op0) == SCRATCH) + return 1; + + if (!REG_P (op0)) + return 0; + + /* Check that we have a valid destination register for a two operand + instruction. */ + return ! force || REGNO (op1) == REGNO (op0); } - /* Check that we have a valid destination register for a two operand - instruction. */ - return ! force || REGNO (op1) == REGNO (operands[0]); + if (c4x_J_constant (op1) && c4x_R_indirect (op2)) + return 1; + + return 0; +} + + +int valid_operands (enum rtx_code code, rtx *operands, enum machine_mode mode) +{ + + /* If we are not optimizing then we have to let anything go and let + reload fix things up. instantiate_decl in function.c can produce + invalid insns by changing the offset of a memory operand from a + valid one into an invalid one, when the second operand is also a + memory operand. The alternative is not to allow two memory + operands for an insn when not optimizing. The problem only rarely + occurs, for example with the C-torture program DFcmp.c. */ + + return ! optimize || c4x_valid_operands (code, operands, mode, 0); } |