diff options
author | Jan Hubicka <jh@suse.cz> | 2003-02-09 13:35:28 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2003-02-09 12:35:28 +0000 |
commit | d9deed68d467546014f23e54e630cf596c42ff5d (patch) | |
tree | 703dc561ba11a34e2a0c453032326a663273f8bc /gcc/simplify-rtx.c | |
parent | 83fd323c4c5fd8f067803028a71870b0dfd8ae30 (diff) | |
download | gcc-d9deed68d467546014f23e54e630cf596c42ff5d.zip gcc-d9deed68d467546014f23e54e630cf596c42ff5d.tar.gz gcc-d9deed68d467546014f23e54e630cf596c42ff5d.tar.bz2 |
i386.md (ahi?v*3): Set third operand type to TImode.
* i386.md (ahi?v*3): Set third operand type to TImode.
* i386.c (ix86_expand_binop_builtin): Extend operand when needed.
* simplify-rtx.c (simplify_subreg): Fix conversion from vector into
integer mode.
* rtl.def (VEC_MERGE, VEC_SELECT, VEC_CONCAT, VEC_DUPLICATE):
Change code so they are arithmetic expressions now.
* simplify-rtx.c (simplify_unary_operation, simplify_binary_operation,
simplify_ternary_operation): Deal with VEC_* expressions.
* i386.md (vmaskcmp, pinsrw, movd patterns): Fix RTL representation.
From-SVN: r62600
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 0298b79e..9685de0 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -372,6 +372,44 @@ simplify_unary_operation (code, mode, op, op_mode) unsigned int width = GET_MODE_BITSIZE (mode); rtx trueop = avoid_constant_pool_reference (op); + if (code == VEC_DUPLICATE) + { + if (!VECTOR_MODE_P (mode)) + abort (); + if (GET_MODE (trueop) != VOIDmode + && !VECTOR_MODE_P (GET_MODE (trueop)) + && GET_MODE_INNER (mode) != GET_MODE (trueop)) + abort (); + if (GET_MODE (trueop) != VOIDmode + && VECTOR_MODE_P (GET_MODE (trueop)) + && GET_MODE_INNER (mode) != GET_MODE_INNER (GET_MODE (trueop))) + abort (); + if (GET_CODE (trueop) == CONST_INT || GET_CODE (trueop) == CONST_DOUBLE + || GET_CODE (trueop) == CONST_VECTOR) + { + int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); + unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); + rtvec v = rtvec_alloc (n_elts); + unsigned int i; + + if (GET_CODE (trueop) != CONST_VECTOR) + for (i = 0; i < n_elts; i++) + RTVEC_ELT (v, i) = trueop; + else + { + enum machine_mode inmode = GET_MODE (trueop); + int in_elt_size = GET_MODE_SIZE (GET_MODE_INNER (inmode)); + unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size); + + if (in_n_elts >= n_elts || n_elts % in_n_elts) + abort (); + for (i = 0; i < n_elts; i++) + RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop, i % in_n_elts); + } + return gen_rtx_CONST_VECTOR (mode, v); + } + } + /* The order of these tests is critical so that, for example, we don't check the wrong mode (input vs. output) for a conversion operation, such as FIX. At some point, this should be simplified. */ @@ -1476,6 +1514,10 @@ simplify_binary_operation (code, mode, op0, op1) /* ??? There are simplifications that can be done. */ return 0; + case VEC_SELECT: + case VEC_CONCAT: + return 0; + default: abort (); } @@ -2332,6 +2374,30 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2) } } break; + case VEC_MERGE: + if (GET_MODE (op0) != mode + || GET_MODE (op1) != mode + || !VECTOR_MODE_P (mode)) + abort (); + op0 = avoid_constant_pool_reference (op0); + op1 = avoid_constant_pool_reference (op1); + op2 = avoid_constant_pool_reference (op2); + if (GET_CODE (op0) == CONST_VECTOR + && GET_CODE (op1) == CONST_VECTOR + && GET_CODE (op2) == CONST_INT) + { + int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); + unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); + rtvec v = rtvec_alloc (n_elts); + unsigned int i; + + for (i = 0; i < n_elts; i++) + RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i) + ? CONST_VECTOR_ELT (op0, i) + : CONST_VECTOR_ELT (op1, i)); + return gen_rtx_CONST_VECTOR (mode, v); + } + break; default: abort (); @@ -2413,13 +2479,16 @@ simplify_subreg (outermode, op, innermode, byte) } if (GET_CODE (elt) != CONST_INT) return NULL_RTX; + /* Avoid overflow. */ + if (high >> (HOST_BITS_PER_WIDE_INT - shift)) + return NULL_RTX; high = high << shift | sum >> (HOST_BITS_PER_WIDE_INT - shift); sum = (sum << shift) + INTVAL (elt); } if (GET_MODE_BITSIZE (outermode) <= HOST_BITS_PER_WIDE_INT) return GEN_INT (trunc_int_for_mode (sum, outermode)); else if (GET_MODE_BITSIZE (outermode) == 2* HOST_BITS_PER_WIDE_INT) - return immed_double_const (high, sum, outermode); + return immed_double_const (sum, high, outermode); else return NULL_RTX; } |