diff options
Diffstat (limited to 'gcc')
42 files changed, 648 insertions, 133 deletions
diff --git a/gcc/alias.c b/gcc/alias.c index fb93d658faf..5d017eb73c9 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -2276,6 +2276,7 @@ nonlocal_mentioned_p (x) case CC0: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case LABEL_REF: return 0; diff --git a/gcc/c-common.c b/gcc/c-common.c index 3768db554ba..b2bdf50ef28 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -702,6 +702,7 @@ constant_expression_warning (value) tree value; { if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST + || TREE_CODE (value) == VECTOR_CST || TREE_CODE (value) == COMPLEX_CST) && TREE_CONSTANT_OVERFLOW (value) && pedantic) pedwarn ("overflow in constant expression"); @@ -736,6 +737,12 @@ overflow_warning (value) if (skip_evaluation == 0) warning ("floating point overflow in expression"); } + else if (TREE_CODE (value) == VECTOR_CST && TREE_OVERFLOW (value)) + { + TREE_OVERFLOW (value) = 0; + if (skip_evaluation == 0) + warning ("vector overflow in expression"); + } } /* Print a warning if a large constant is truncated to unsigned, diff --git a/gcc/combine.c b/gcc/combine.c index 5abda2e56fe..eb825311613 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -11603,6 +11603,7 @@ mark_used_regs_combine (x) case CONST_INT: case CONST: case CONST_DOUBLE: + case CONST_VECTOR: case PC: case ADDR_VEC: case ADDR_DIFF_VEC: diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b0ec9f21368..1d7091d2d9b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -18999,14 +18999,14 @@ (plus:V8QI (plus:V8QI (match_operand:V8QI 1 "register_operand" "0") (match_operand:V8QI 2 "nonimmediate_operand" "ym")) - (vec_const:V8QI (parallel [(const_int 1) - (const_int 1) - (const_int 1) - (const_int 1) - (const_int 1) - (const_int 1) - (const_int 1) - (const_int 1)]))) + (const_vector:V8QI [(const_int 1) + (const_int 1) + (const_int 1) + (const_int 1) + (const_int 1) + (const_int 1) + (const_int 1) + (const_int 1)])) (const_int 1)))] "TARGET_SSE || TARGET_3DNOW_A" "pavgb\t{%2, %0|%0, %2}" @@ -19018,10 +19018,10 @@ (plus:V4HI (plus:V4HI (match_operand:V4HI 1 "register_operand" "0") (match_operand:V4HI 2 "nonimmediate_operand" "ym")) - (vec_const:V4HI (parallel [(const_int 1) - (const_int 1) - (const_int 1) - (const_int 1)]))) + (const_vector:V4HI [(const_int 1) + (const_int 1) + (const_int 1) + (const_int 1)])) (const_int 1)))] "TARGET_SSE || TARGET_3DNOW_A" "pavgw\t{%2, %0|%0, %2}" @@ -19735,12 +19735,11 @@ (match_operand:V4HI 1 "register_operand" "0")) (sign_extend:V4SI (match_operand:V4HI 2 "nonimmediate_operand" "ym"))) - (vec_const:V4SI - (parallel [(const_int 32768) - (const_int 32768) - (const_int 32768) - (const_int 32768)]))) - (const_int 16))))] + (const_vector:V4SI [(const_int 32768) + (const_int 32768) + (const_int 32768) + (const_int 32768)])) + (const_int 16))))] "TARGET_3DNOW" "pmulhrw\\t{%2, %0|%0, %2}" [(set_attr "type" "mmx")]) diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index a588360c36b..19aeb07b9e0 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -52,6 +52,7 @@ extern int got_no_const_operand PARAMS ((rtx, enum machine_mode)); extern int num_insns_constant PARAMS ((rtx, enum machine_mode)); extern int easy_fp_constant PARAMS ((rtx, enum machine_mode)); extern int zero_fp_constant PARAMS ((rtx, enum machine_mode)); +extern int zero_constant PARAMS ((rtx, enum machine_mode)); extern int volatile_mem_operand PARAMS ((rtx, enum machine_mode)); extern int offsettable_mem_operand PARAMS ((rtx, enum machine_mode)); extern int mem_or_easy_const_operand PARAMS ((rtx, enum machine_mode)); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 8cd66463d5c..5e3a7353c33 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -174,6 +174,7 @@ static void is_altivec_return_reg PARAMS ((rtx, void *)); int vrsave_operation PARAMS ((rtx, enum machine_mode)); static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int)); static void altivec_frame_fixup PARAMS ((rtx, rtx, HOST_WIDE_INT)); +static int easy_vector_constant PARAMS ((rtx)); /* Default register names. */ char rs6000_reg_names[][8] = @@ -1194,6 +1195,54 @@ easy_fp_constant (op, mode) abort (); } +/* Return 1 if the operand is a CONST_INT and can be put into a + register with one instruction. */ + +static int +easy_vector_constant (op) + rtx op; +{ + rtx elt; + int units, i; + + if (GET_CODE (op) != CONST_VECTOR) + return 0; + + units = CONST_VECTOR_NUNITS (op); + + /* We can generate 0 easily. Look for that. */ + for (i = 0; i < units; ++i) + { + elt = CONST_VECTOR_ELT (op, i); + + /* We could probably simplify this by just checking for equality + with CONST0_RTX for the current mode, but let's be safe + instead. */ + + if (GET_CODE (elt) == CONST_INT && INTVAL (elt) != 0) + return 0; + + if (GET_CODE (elt) == CONST_DOUBLE + && (CONST_DOUBLE_LOW (elt) != 0 + || CONST_DOUBLE_HIGH (elt) != 0)) + return 0; + } + + /* We could probably generate a few other constants trivially, but + gcc doesn't generate them yet. FIXME later. */ + return 0; +} + +/* Return 1 if the operand is the constant 0. This works for scalars + as well as vectors. */ +int +zero_constant (op, mode) + rtx op; + enum machine_mode mode; +{ + return op == CONST0_RTX (mode); +} + /* Return 1 if the operand is 0.0. */ int zero_fp_constant (op, mode) @@ -1892,6 +1941,7 @@ rs6000_legitimize_reload_address (x, mode, opnum, type, ind_levels, win) #if TARGET_MACHO if (GET_CODE (x) == SYMBOL_REF && DEFAULT_ABI == ABI_DARWIN + && !ALTIVEC_VECTOR_MODE (mode) && flag_pic) { /* Darwin load of floating point constant. */ @@ -2186,9 +2236,10 @@ rs6000_emit_move (dest, source, mode) /* Handle the case where reload calls us with an invalid address; and the case of CONSTANT_P_RTX. */ - if (! general_operand (operands[1], mode) - || ! nonimmediate_operand (operands[0], mode) - || GET_CODE (operands[1]) == CONSTANT_P_RTX) + if (!VECTOR_MODE_P (mode) + && (! general_operand (operands[1], mode) + || ! nonimmediate_operand (operands[0], mode) + || GET_CODE (operands[1]) == CONSTANT_P_RTX)) { emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); return; @@ -2218,8 +2269,8 @@ rs6000_emit_move (dest, source, mode) case V8HImode: case V4SFmode: case V4SImode: - /* fixme: aldyh -- allow vector constants when they are implemented. */ - if (CONSTANT_P (operands[1])) + if (CONSTANT_P (operands[1]) + && !easy_vector_constant (operands[1])) operands[1] = force_const_mem (mode, operands[1]); break; diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index ebbede46205..cdbe3361a91 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -638,10 +638,13 @@ extern int rs6000_altivec_abi; /* A bitfield declared as `int' forces `int' alignment for the struct. */ #define PCC_BITFIELD_TYPE_MATTERS 1 -/* Make strings word-aligned so strcpy from constants will be faster. */ -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - (TREE_CODE (EXP) == STRING_CST \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) +/* Make strings word-aligned so strcpy from constants will be faster. + Make vector constants quadword aligned. */ +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + (TREE_CODE (EXP) == STRING_CST \ + && (ALIGN) < BITS_PER_WORD \ + ? BITS_PER_WORD \ + : (ALIGN)) /* Make arrays of chars word-aligned for the same reasons. Align vectors to 128 bits. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 7a5bce5b931..d83538ba625 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -14017,6 +14017,36 @@ "mtvrsave %1" [(set_attr "type" "altivec")]) +;; Vector clears +(define_insn "*movv4si_const0" + [(set (match_operand:V4SI 0 "altivec_register_operand" "=v") + (match_operand:V4SI 1 "zero_constant" ""))] + "TARGET_ALTIVEC" + "vxor %0,%0,%0" + [(set_attr "type" "vecsimple")]) + +(define_insn "*movv4sf_const0" + [(set (match_operand:V4SF 0 "altivec_register_operand" "=v") + (match_operand:V4SF 1 "zero_constant" ""))] + + "TARGET_ALTIVEC" + "vxor %0,%0,%0" + [(set_attr "type" "vecsimple")]) + +(define_insn "*movv8hi_const0" + [(set (match_operand:V8HI 0 "altivec_register_operand" "=v") + (match_operand:V8HI 1 "zero_constant" ""))] + "TARGET_ALTIVEC" + "vxor %0,%0,%0" + [(set_attr "type" "vecsimple")]) + +(define_insn "*movv16qi_const0" + [(set (match_operand:V16QI 0 "altivec_register_operand" "=v") + (match_operand:V16QI 1 "zero_constant" ""))] + "TARGET_ALTIVEC" + "vxor %0,%0,%0" + [(set_attr "type" "vecsimple")]) + ;; Simple binary operations. (define_insn "addv16qi3" @@ -15481,49 +15511,61 @@ "lvsr %0,%1,%2" [(set_attr "type" "vecload")]) +;; Parallel some of the LVE* and STV*'s with unspecs because some have +;; identical rtl but different instructions-- and gcc gets confused. + (define_insn "altivec_lvebx" - [(set (match_operand:V16QI 0 "register_operand" "=v") - (unspec:V16QI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "register_operand" "r")] 196))] + [(parallel + [(set (match_operand:V16QI 0 "register_operand" "=v") + (mem:V16QI (plus:SI (match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "register_operand" "r")))) + (unspec [(const_int 0)] 196)])] "TARGET_ALTIVEC" "lvebx %0,%1,%2" [(set_attr "type" "vecload")]) (define_insn "altivec_lvehx" - [(set (match_operand:V8HI 0 "register_operand" "=v") - (unspec:V8HI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "register_operand" "r")] 197))] + [(parallel + [(set (match_operand:V8HI 0 "register_operand" "=v") + (mem:V8HI + (and:SI (plus:SI (match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "register_operand" "r")) + (const_int -2)))) + (unspec [(const_int 0)] 197)])] "TARGET_ALTIVEC" "lvehx %0,%1,%2" [(set_attr "type" "vecload")]) (define_insn "altivec_lvewx" - [(set (match_operand:V4SI 0 "register_operand" "=v") - (unspec:V4SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "register_operand" "r")] 198))] + [(parallel + [(set (match_operand:V4SI 0 "register_operand" "=v") + (mem:V4SI + (and:SI (plus:SI (match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "register_operand" "r")) + (const_int -4)))) + (unspec [(const_int 0)] 198)])] "TARGET_ALTIVEC" "lvewx %0,%1,%2" [(set_attr "type" "vecload")]) (define_insn "altivec_lvxl" - [(set (match_operand:V4SI 0 "register_operand" "=v") - (unspec:V4SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "register_operand" "r")] 199))] + [(parallel + [(set (match_operand:V4SI 0 "register_operand" "=v") + (mem:V4SI (plus:SI (match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "register_operand" "r")))) + (unspec [(const_int 0)] 213)])] "TARGET_ALTIVEC" "lvxl %0,%1,%2" [(set_attr "type" "vecload")]) (define_insn "altivec_lvx" [(set (match_operand:V4SI 0 "register_operand" "=v") - (unspec:V4SI [(match_operand:SI 1 "register_operand" "b") - (match_operand:SI 2 "register_operand" "r")] 200))] + (mem:V4SI (plus:SI (match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "register_operand" "r"))))] "TARGET_ALTIVEC" "lvx %0,%1,%2" [(set_attr "type" "vecload")]) -;; Parallel the STV*'s with unspecs because some of them have -;; identical rtl but are different instructions-- and gcc gets confused. - (define_insn "altivec_stvx" [(parallel [(set (mem:V4SI diff --git a/gcc/cse.c b/gcc/cse.c index b88a84c2cea..a607b0c46f3 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -2323,6 +2323,22 @@ canon_hash (x, mode) + (unsigned) CONST_DOUBLE_HIGH (x)); return hash; + case CONST_VECTOR: + { + int units; + rtx elt; + + units = CONST_VECTOR_NUNITS (x); + + for (i = 0; i < units; ++i) + { + elt = CONST_VECTOR_ELT (x, i); + hash += canon_hash (elt, GET_MODE (elt)); + } + + return hash; + } + /* Assume there is only one rtx object for any given label. */ case LABEL_REF: hash += ((unsigned) LABEL_REF << 7) + (unsigned long) XEXP (x, 0); @@ -2776,6 +2792,7 @@ canon_reg (x, insn) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case ADDR_VEC: @@ -3317,6 +3334,7 @@ fold_rtx (x, insn) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case REG: @@ -3727,6 +3745,7 @@ fold_rtx (x, insn) case SYMBOL_REF: case LABEL_REF: case CONST_DOUBLE: + case CONST_VECTOR: const_arg = arg; break; @@ -6425,6 +6444,7 @@ cse_process_notes (x, object) case SYMBOL_REF: case LABEL_REF: case CONST_DOUBLE: + case CONST_VECTOR: case PC: case CC0: case LO_SUM: @@ -7416,6 +7436,7 @@ count_reg_usage (x, counts, dest, incr) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: return; diff --git a/gcc/cselib.c b/gcc/cselib.c index 64eb8a5752a..0eb17b8a836 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -593,6 +593,22 @@ hash_rtx (x, mode, create) + (unsigned) CONST_DOUBLE_HIGH (x)); return hash ? hash : (unsigned int) CONST_DOUBLE; + case CONST_VECTOR: + { + int units; + rtx elt; + + units = CONST_VECTOR_NUNITS (x); + + for (i = 0; i < units; ++i) + { + elt = CONST_VECTOR_ELT (x, i); + hash += hash_rtx (elt, GET_MODE (elt), 0); + } + + return hash; + } + /* Assume there is only one rtx object for any given label. */ case LABEL_REF: hash @@ -794,6 +810,7 @@ cselib_subst_to_values (x) return e->u.val_rtx; case CONST_DOUBLE: + case CONST_VECTOR: case CONST_INT: return x; @@ -1009,6 +1026,7 @@ cselib_mem_conflict_p (mem_base, val) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: return 0; @@ -1032,6 +1032,7 @@ df_uses_record (df, loc, ref_type, bb, insn, flags) case CONST_INT: case CONST: case CONST_DOUBLE: + case CONST_VECTOR: case PC: case ADDR_VEC: case ADDR_DIFF_VEC: diff --git a/gcc/doc/c-tree.texi b/gcc/doc/c-tree.texi index 65b39db0bb8..849d07948b6 100644 --- a/gcc/doc/c-tree.texi +++ b/gcc/doc/c-tree.texi @@ -1712,6 +1712,7 @@ This macro returns the attributes on the type @var{type}. @findex tree_int_cst_equal @tindex REAL_CST @tindex COMPLEX_CST +@tindex VECTOR_CST @tindex STRING_CST @findex TREE_STRING_LENGTH @findex TREE_STRING_POINTER @@ -1858,6 +1859,12 @@ These nodes are used to represent complex number constants, that is a @code{TREE_REALPART} and @code{TREE_IMAGPART} return the real and the imaginary parts respectively. +@item VECTOR_CST +These nodes are used to represent vector constants, whose parts are +constant nodes. Each individual constant node is either an integer or a +double constant node. The first operand is a @code{TREE_LIST} of the +constant nodes and is accessed through @code{TREE_VECTOR_CST_ELTS}. + @item STRING_CST These nodes represent string-constants. The @code{TREE_STRING_LENGTH} returns the length of the string, as an @code{int}. The diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 5b614090b28..6963950301f 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -1156,6 +1156,20 @@ bits but small enough to fit within twice that number of bits (GCC does not provide a mechanism to represent even larger constants). In the latter case, @var{m} will be @code{VOIDmode}. +@findex const_vector +@item (const_vector:@var{m} [@var{x0} @var{x1} @dots{}]) +Represents a vector constant. The square brackets stand for the vector +containing the constant elements. @var{x0}, @var{x1} and so on are +the @code{const_int} or @code{const_double} elements. + +The number of units in a @code{const_vector} is obtained with the macro +@code{CONST_VECTOR_NUNITS} as in @code{CONST_VECTOR_NUNITS (@var{v})}. + +Individual elements in a vector constant are accessed with the macro +@code{CONST_VECTOR_ELT} as in @code{CONST_VECTOR_ELT (@var{v}, @var{n}) +where @var{v} is the vector constant and @var{n} is the element +desired. + @findex CONST_DOUBLE_MEM @findex CONST_DOUBLE_CHAIN @var{addr} is used to contain the @code{mem} expression that corresponds @@ -1185,10 +1199,14 @@ the precise bit pattern used by the target machine, use the macro @findex CONST2_RTX The macro @code{CONST0_RTX (@var{mode})} refers to an expression with value 0 in mode @var{mode}. If mode @var{mode} is of mode class -@code{MODE_INT}, it returns @code{const0_rtx}. Otherwise, it returns a -@code{CONST_DOUBLE} expression in mode @var{mode}. Similarly, the macro +@code{MODE_INT}, it returns @code{const0_rtx}. If mode @var{mode} is of +mode class @code{MODE_FLOAT}, it returns a @code{CONST_DOUBLE} +expression in mode @var{mode}. Otherwise, it returns a +@code{CONST_VECTOR} expression in mode @var{mode}. Similarly, the macro @code{CONST1_RTX (@var{mode})} refers to an expression with value 1 in -mode @var{mode} and similarly for @code{CONST2_RTX}. +mode @var{mode} and similarly for @code{CONST2_RTX}. The +@code{CONST1_RTX} and @code{CONST2_RTX} macros are undefined +for vector modes. @findex const_string @item (const_string @var{str}) @@ -3331,6 +3349,11 @@ There is only one @code{cc0} expression. There is only one @code{const_double} expression with value 0 for each floating point mode. Likewise for values 1 and 2. +@cindex @code{const_vector}, RTL sharing +@item +There is only one @code{const_vector} expression with value 0 for +each vector mode, be it an integer or a double constant vector. + @cindex @code{label_ref}, RTL sharing @cindex @code{scratch}, RTL sharing @item diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 4ea852b6050..82dd61a5f64 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -196,6 +196,7 @@ static mem_attrs *get_mem_attrs PARAMS ((HOST_WIDE_INT, tree, rtx, rtx, unsigned int, enum machine_mode)); static tree component_ref_for_mem_expr PARAMS ((tree)); +static rtx gen_const_vector_0 PARAMS ((enum mode_class, enum machine_mode)); /* Probability of the conditional branch currently proceeded by try_split. Set to -1 otherwise. */ @@ -2390,6 +2391,7 @@ copy_rtx_if_shared (orig) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -2506,6 +2508,7 @@ reset_used_flags (x) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -4541,6 +4544,7 @@ copy_insn_1 (orig) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -4779,6 +4783,35 @@ mark_emit_status (es) ggc_mark_rtx (es->x_first_insn); } +/* Generate the constant 0. The first argument is MODE_VECTOR_INT for + integers or MODE_VECTOR_FLOAT for floats. */ + +static rtx +gen_const_vector_0 (type, mode) + enum mode_class type; + enum machine_mode mode; +{ + rtx tem; + rtvec v; + int units, i; + enum machine_mode inner; + + units = GET_MODE_NUNITS (mode); + inner = GET_MODE_INNER (mode); + + v = rtvec_alloc (units); + + /* We need to call this function after we to set CONST0_RTX first. */ + if (!CONST0_RTX (inner)) + abort (); + + for (i = 0; i < units; ++i) + RTVEC_ELT (v, i) = CONST0_RTX (inner); + + tem = gen_rtx_CONST_VECTOR (mode, v); + return tem; +} + /* Create some permanent unique rtl objects shared between all functions. LINE_NUMBERS is nonzero if line numbers are to be generated. */ @@ -4920,6 +4953,18 @@ init_emit_once (line_numbers) const_tiny_rtx[i][(int) mode] = GEN_INT (i); } + for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + const_tiny_rtx[0][(int) mode] + = gen_const_vector_0 (MODE_VECTOR_INT, mode); + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + const_tiny_rtx[0][(int) mode] + = gen_const_vector_0 (MODE_VECTOR_FLOAT, mode); + for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i) if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC) const_tiny_rtx[0][i] = const0_rtx; diff --git a/gcc/expmed.c b/gcc/expmed.c index a26ad0946a9..ad87865a063 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -4038,7 +4038,25 @@ make_tree (type, x) } return t; - + + case CONST_VECTOR: + { + int i, units; + rtx elt; + tree t = NULL_TREE; + + units = CONST_VECTOR_NUNITS (x); + + /* Build a tree with vector elements. */ + for (i = units - 1; i >= 0; --i) + { + elt = CONST_VECTOR_ELT (x, i); + t = tree_cons (NULL_TREE, make_tree (type, elt), t); + } + + return build_vector (type, t); + } + case PLUS: return fold (build (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)), make_tree (type, XEXP (x, 1)))); diff --git a/gcc/expr.c b/gcc/expr.c index 73690372e4e..f56f88640dc 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -2562,8 +2562,7 @@ clear_storage (object, size) /* If OBJECT is not BLKmode and SIZE is the same size as its mode, just move a zero. Otherwise, do this a piece at a time. */ - if ((GET_MODE (object) != BLKmode - && !VECTOR_MODE_P (GET_MODE (object))) + if (GET_MODE (object) != BLKmode && GET_CODE (size) == CONST_INT && GET_MODE_SIZE (GET_MODE (object)) == (unsigned int) INTVAL (size)) emit_move_insn (object, CONST0_RTX (GET_MODE (object))); @@ -4245,6 +4244,14 @@ is_zeros_p (exp) case REAL_CST: return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0); + case VECTOR_CST: + for (elt = TREE_VECTOR_CST_ELTS (exp); elt; + elt = TREE_CHAIN (elt)) + if (!is_zeros_p (TREE_VALUE (elt))) + return 0; + + return 1; + case CONSTRUCTOR: if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) return CONSTRUCTOR_ELTS (exp) == NULL_TREE; diff --git a/gcc/flow.c b/gcc/flow.c index 315cb2d7e85..6c3cd564d7d 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -3635,6 +3635,7 @@ mark_used_regs (pbi, x, cond, insn) case CONST_INT: case CONST: case CONST_DOUBLE: + case CONST_VECTOR: case PC: case ADDR_VEC: case ADDR_DIFF_VEC: diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 2f0d4ace1c1..7c9a5ec99ee 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -2427,6 +2427,27 @@ operand_equal_p (arg0, arg1, only_const) && REAL_VALUES_IDENTICAL (TREE_REAL_CST (arg0), TREE_REAL_CST (arg1))); + case VECTOR_CST: + { + tree v1, v2; + + if (TREE_CONSTANT_OVERFLOW (arg0) + || TREE_CONSTANT_OVERFLOW (arg1)) + return 0; + + v1 = TREE_VECTOR_CST_ELTS (arg0); + v2 = TREE_VECTOR_CST_ELTS (arg1); + while (v1 && v2) + { + if (!operand_equal_p (v1, v2, only_const)) + return 0; + v1 = TREE_CHAIN (v1); + v2 = TREE_CHAIN (v2); + } + + return 1; + } + case COMPLEX_CST: return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), only_const) @@ -5184,6 +5205,7 @@ fold (expr) { case INTEGER_CST: case REAL_CST: + case VECTOR_CST: case STRING_CST: case COMPLEX_CST: case CONSTRUCTOR: @@ -7586,6 +7608,23 @@ rtl_expr_nonnegative_p (r) return CONST_DOUBLE_HIGH (r) >= 0; return 0; + case CONST_VECTOR: + { + int units, i; + rtx elt; + + units = CONST_VECTOR_NUNITS (r); + + for (i = 0; i < units; ++i) + { + elt = CONST_VECTOR_ELT (r, i); + if (!rtl_expr_nonnegative_p (elt)) + return 0; + } + + return 1; + } + case SYMBOL_REF: case LABEL_REF: /* These are always nonnegative. */ diff --git a/gcc/function.c b/gcc/function.c index 634e74b4d62..0c2298c2474 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -1994,6 +1994,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements) case SYMBOL_REF: case LABEL_REF: case CONST_DOUBLE: + case CONST_VECTOR: return; case SIGN_EXTRACT: @@ -3722,6 +3723,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) { case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case SYMBOL_REF: case CODE_LABEL: diff --git a/gcc/gcse.c b/gcc/gcse.c index 928b6397624..b7b08f2840a 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -1315,6 +1315,7 @@ want_to_gcse_p (x) case SUBREG: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CALL: return 0; @@ -1400,6 +1401,7 @@ oprs_unchanged_p (x, insn, avail_p) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case ADDR_VEC: @@ -1635,6 +1637,22 @@ hash_expr_1 (x, mode, do_not_record_p) + (unsigned int) CONST_DOUBLE_HIGH (x)); return hash; + case CONST_VECTOR: + { + int units; + rtx elt; + + units = CONST_VECTOR_NUNITS (x); + + for (i = 0; i < units; ++i) + { + elt = CONST_VECTOR_ELT (x, i); + hash += hash_expr_1 (elt, GET_MODE (elt), do_not_record_p); + } + + return hash; + } + /* Assume there is only one rtx object for any given label. */ case LABEL_REF: /* We don't hash on the address of the CODE_LABEL to avoid bootstrap @@ -2756,6 +2774,7 @@ oprs_not_set_p (x, insn) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case ADDR_VEC: @@ -3089,6 +3108,7 @@ expr_killed_p (x, bb) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case ADDR_VEC: @@ -3789,6 +3809,7 @@ compute_transp (x, indx, bmap, set_p) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case ADDR_VEC: @@ -6289,6 +6310,7 @@ store_ops_ok (x, bb) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case ADDR_VEC: diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 1c916b34bf2..a485deef61c 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -839,6 +839,7 @@ attr_copy_rtx (orig) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -2278,6 +2279,7 @@ encode_units_mask (x) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -4112,6 +4114,7 @@ clear_struct_flag (x) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -4167,6 +4170,7 @@ count_sub_rtxs (x, max) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: diff --git a/gcc/integrate.c b/gcc/integrate.c index 10d98f2f8a8..ad6b2a1f52a 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -2120,6 +2120,7 @@ copy_rtx_and_substitute (orig, map, for_lhs) case PC: case CC0: case CONST_INT: + case CONST_VECTOR: return orig; case SYMBOL_REF: @@ -2479,6 +2480,7 @@ subst_constants (loc, insn, map, memonly) case PC: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CONST: case LABEL_REF: diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c index 1a6e3cf97fb..c44f3686bb8 100644 --- a/gcc/local-alloc.c +++ b/gcc/local-alloc.c @@ -539,6 +539,7 @@ equiv_init_varies_p (x) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: return 0; @@ -658,6 +659,7 @@ contains_replace_regs (x) case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE: + case CONST_VECTOR: case PC: case CC0: case HIGH: @@ -708,6 +710,7 @@ memref_referenced_p (memref, x) case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE: + case CONST_VECTOR: case PC: case CC0: case HIGH: diff --git a/gcc/machmode.def b/gcc/machmode.def index 5ec6a1ea182..16abebb8f31 100644 --- a/gcc/machmode.def +++ b/gcc/machmode.def @@ -63,50 +63,54 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA there is none. Vector modes use this field to point to the next vector size, so we can iterate through the different vectors modes. The ordering is by increasing byte size, with QI coming before HI, - HI before SI, etc. */ + HI before SI, etc. + + Eigth arg is the mode of the internal elements in a vector. + VOIDmode if not a vector. +*/ /* VOIDmode is used when no mode needs to be specified, as for example on CONST_INT RTL expressions. */ -DEF_MACHMODE (VOIDmode, "VOID", MODE_RANDOM, 0, 0, 0, VOIDmode) +DEF_MACHMODE (VOIDmode, "VOID", MODE_RANDOM, 0, 0, 0, VOIDmode, VOIDmode) -DEF_MACHMODE (BImode, "BI", MODE_INT, 1, 1, 1, QImode) -DEF_MACHMODE (QImode, "QI", MODE_INT, BITS_PER_UNIT, 1, 1, HImode) -DEF_MACHMODE (HImode, "HI", MODE_INT, BITS_PER_UNIT*2, 2, 2, SImode) -DEF_MACHMODE (SImode, "SI", MODE_INT, BITS_PER_UNIT*4, 4, 4, DImode) -DEF_MACHMODE (DImode, "DI", MODE_INT, BITS_PER_UNIT*8, 8, 8, TImode) -DEF_MACHMODE (TImode, "TI", MODE_INT, BITS_PER_UNIT*16, 16, 16, OImode) -DEF_MACHMODE (OImode, "OI", MODE_INT, BITS_PER_UNIT*32, 32, 32, VOIDmode) +DEF_MACHMODE (BImode, "BI", MODE_INT, 1, 1, 1, QImode, VOIDmode) +DEF_MACHMODE (QImode, "QI", MODE_INT, BITS_PER_UNIT, 1, 1, HImode, VOIDmode) +DEF_MACHMODE (HImode, "HI", MODE_INT, BITS_PER_UNIT*2, 2, 2, SImode, VOIDmode) +DEF_MACHMODE (SImode, "SI", MODE_INT, BITS_PER_UNIT*4, 4, 4, DImode, VOIDmode) +DEF_MACHMODE (DImode, "DI", MODE_INT, BITS_PER_UNIT*8, 8, 8, TImode, VOIDmode) +DEF_MACHMODE (TImode, "TI", MODE_INT, BITS_PER_UNIT*16, 16, 16, OImode, VOIDmode) +DEF_MACHMODE (OImode, "OI", MODE_INT, BITS_PER_UNIT*32, 32, 32, VOIDmode, VOIDmode) /* Pointers on some machines use these types to distinguish them from ints. Useful if a pointer is 4 bytes but has some bits that are not significant, so it is really not quite as wide as an integer. */ -DEF_MACHMODE (PQImode, "PQI", MODE_PARTIAL_INT, BITS_PER_UNIT, 1, 1, PHImode) -DEF_MACHMODE (PHImode, "PHI", MODE_PARTIAL_INT, BITS_PER_UNIT*2, 2, 2, PSImode) -DEF_MACHMODE (PSImode, "PSI", MODE_PARTIAL_INT, BITS_PER_UNIT*4, 4, 4, PDImode) -DEF_MACHMODE (PDImode, "PDI", MODE_PARTIAL_INT, BITS_PER_UNIT*8, 8, 8, VOIDmode) - -DEF_MACHMODE (QFmode, "QF", MODE_FLOAT, BITS_PER_UNIT, 1, 1, HFmode) -DEF_MACHMODE (HFmode, "HF", MODE_FLOAT, BITS_PER_UNIT*2, 2, 2, TQFmode) -DEF_MACHMODE (TQFmode, "TQF", MODE_FLOAT, BITS_PER_UNIT*3, 3, 3, SFmode) /* MIL-STD-1750A */ -DEF_MACHMODE (SFmode, "SF", MODE_FLOAT, BITS_PER_UNIT*4, 4, 4, DFmode) -DEF_MACHMODE (DFmode, "DF", MODE_FLOAT, BITS_PER_UNIT*8, 8, 8, XFmode) -DEF_MACHMODE (XFmode, "XF", MODE_FLOAT, BITS_PER_UNIT*12, 12, 12, TFmode) /* IEEE extended */ -DEF_MACHMODE (TFmode, "TF", MODE_FLOAT, BITS_PER_UNIT*16, 16, 16, VOIDmode) +DEF_MACHMODE (PQImode, "PQI", MODE_PARTIAL_INT, BITS_PER_UNIT, 1, 1, PHImode, VOIDmode) +DEF_MACHMODE (PHImode, "PHI", MODE_PARTIAL_INT, BITS_PER_UNIT*2, 2, 2, PSImode, VOIDmode) +DEF_MACHMODE (PSImode, "PSI", MODE_PARTIAL_INT, BITS_PER_UNIT*4, 4, 4, PDImode, VOIDmode) +DEF_MACHMODE (PDImode, "PDI", MODE_PARTIAL_INT, BITS_PER_UNIT*8, 8, 8, VOIDmode, VOIDmode) + +DEF_MACHMODE (QFmode, "QF", MODE_FLOAT, BITS_PER_UNIT, 1, 1, HFmode, VOIDmode) +DEF_MACHMODE (HFmode, "HF", MODE_FLOAT, BITS_PER_UNIT*2, 2, 2, TQFmode, VOIDmode) +DEF_MACHMODE (TQFmode, "TQF", MODE_FLOAT, BITS_PER_UNIT*3, 3, 3, SFmode, VOIDmode) /* MIL-STD-1750A */ +DEF_MACHMODE (SFmode, "SF", MODE_FLOAT, BITS_PER_UNIT*4, 4, 4, DFmode, VOIDmode) +DEF_MACHMODE (DFmode, "DF", MODE_FLOAT, BITS_PER_UNIT*8, 8, 8, XFmode, VOIDmode) +DEF_MACHMODE (XFmode, "XF", MODE_FLOAT, BITS_PER_UNIT*12, 12, 12, TFmode, VOIDmode) /* IEEE extended */ +DEF_MACHMODE (TFmode, "TF", MODE_FLOAT, BITS_PER_UNIT*16, 16, 16, VOIDmode, VOIDmode) /* Complex modes. */ -DEF_MACHMODE (QCmode, "QC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*2, 2, 1, HCmode) -DEF_MACHMODE (HCmode, "HC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*4, 4, 2, SCmode) -DEF_MACHMODE (SCmode, "SC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*8, 8, 4, DCmode) -DEF_MACHMODE (DCmode, "DC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*16, 16, 8, XCmode) -DEF_MACHMODE (XCmode, "XC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*24, 24, 12, TCmode) -DEF_MACHMODE (TCmode, "TC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*32, 32, 16, VOIDmode) - -DEF_MACHMODE (CQImode, "CQI", MODE_COMPLEX_INT, BITS_PER_UNIT*2, 2, 1, CHImode) -DEF_MACHMODE (CHImode, "CHI", MODE_COMPLEX_INT, BITS_PER_UNIT*4, 4, 2, CSImode) -DEF_MACHMODE (CSImode, "CSI", MODE_COMPLEX_INT, BITS_PER_UNIT*8, 8, 4, CDImode) -DEF_MACHMODE (CDImode, "CDI", MODE_COMPLEX_INT, BITS_PER_UNIT*16, 16, 8, CTImode) -DEF_MACHMODE (CTImode, "CTI", MODE_COMPLEX_INT, BITS_PER_UNIT*32, 32, 16, COImode) -DEF_MACHMODE (COImode, "COI", MODE_COMPLEX_INT, BITS_PER_UNIT*64, 64, 32, VOIDmode) +DEF_MACHMODE (QCmode, "QC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*2, 2, 1, HCmode, VOIDmode) +DEF_MACHMODE (HCmode, "HC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*4, 4, 2, SCmode, VOIDmode) +DEF_MACHMODE (SCmode, "SC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*8, 8, 4, DCmode, VOIDmode) +DEF_MACHMODE (DCmode, "DC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*16, 16, 8, XCmode, VOIDmode) +DEF_MACHMODE (XCmode, "XC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*24, 24, 12, TCmode, VOIDmode) +DEF_MACHMODE (TCmode, "TC", MODE_COMPLEX_FLOAT, BITS_PER_UNIT*32, 32, 16, VOIDmode, VOIDmode) + +DEF_MACHMODE (CQImode, "CQI", MODE_COMPLEX_INT, BITS_PER_UNIT*2, 2, 1, CHImode, VOIDmode) +DEF_MACHMODE (CHImode, "CHI", MODE_COMPLEX_INT, BITS_PER_UNIT*4, 4, 2, CSImode, VOIDmode) +DEF_MACHMODE (CSImode, "CSI", MODE_COMPLEX_INT, BITS_PER_UNIT*8, 8, 4, CDImode, VOIDmode) +DEF_MACHMODE (CDImode, "CDI", MODE_COMPLEX_INT, BITS_PER_UNIT*16, 16, 8, CTImode, VOIDmode) +DEF_MACHMODE (CTImode, "CTI", MODE_COMPLEX_INT, BITS_PER_UNIT*32, 32, 16, COImode, VOIDmode) +DEF_MACHMODE (COImode, "COI", MODE_COMPLEX_INT, BITS_PER_UNIT*64, 64, 32, VOIDmode, VOIDmode) /* Vector modes. */ /* There are no V1xx vector modes. These are equivalent to normal @@ -114,43 +118,43 @@ DEF_MACHMODE (COImode, "COI", MODE_COMPLEX_INT, BITS_PER_UNIT*64, 64, 32, VOIDmo /* The wider mode field for vectors follows in order of increasing bit size with QI coming before HI, HI before SI, and SI before DI within same bit sizes. */ -DEF_MACHMODE (V2QImode, "V2QI", MODE_VECTOR_INT, BITS_PER_UNIT*2, 2, 1, V4QImode) -DEF_MACHMODE (V2HImode, "V2HI", MODE_VECTOR_INT, BITS_PER_UNIT*4, 4, 2, V8QImode) -DEF_MACHMODE (V2SImode, "V2SI", MODE_VECTOR_INT, BITS_PER_UNIT*8, 8, 4, V16QImode) -DEF_MACHMODE (V2DImode, "V2DI", MODE_VECTOR_INT, BITS_PER_UNIT*16, 16, 8, V8SImode) +DEF_MACHMODE (V2QImode, "V2QI", MODE_VECTOR_INT, BITS_PER_UNIT*2, 2, 1, V4QImode, QImode) +DEF_MACHMODE (V2HImode, "V2HI", MODE_VECTOR_INT, BITS_PER_UNIT*4, 4, 2, V8QImode, HImode) +DEF_MACHMODE (V2SImode, "V2SI", MODE_VECTOR_INT, BITS_PER_UNIT*8, 8, 4, V16QImode, SImode) +DEF_MACHMODE (V2DImode, "V2DI", MODE_VECTOR_INT, BITS_PER_UNIT*16, 16, 8, V8SImode, DImode) -DEF_MACHMODE (V4QImode, "V4QI", MODE_VECTOR_INT, BITS_PER_UNIT*4, 4, 1, V2HImode) -DEF_MACHMODE (V4HImode, "V4HI", MODE_VECTOR_INT, BITS_PER_UNIT*8, 8, 2, V2SImode) -DEF_MACHMODE (V4SImode, "V4SI", MODE_VECTOR_INT, BITS_PER_UNIT*16, 16, 4, V2DImode) -DEF_MACHMODE (V4DImode, "V4DI", MODE_VECTOR_INT, BITS_PER_UNIT*32, 32, 8, V8DImode) +DEF_MACHMODE (V4QImode, "V4QI", MODE_VECTOR_INT, BITS_PER_UNIT*4, 4, 1, V2HImode, QImode) +DEF_MACHMODE (V4HImode, "V4HI", MODE_VECTOR_INT, BITS_PER_UNIT*8, 8, 2, V2SImode, HImode) +DEF_MACHMODE (V4SImode, "V4SI", MODE_VECTOR_INT, BITS_PER_UNIT*16, 16, 4, V2DImode, SImode) +DEF_MACHMODE (V4DImode, "V4DI", MODE_VECTOR_INT, BITS_PER_UNIT*32, 32, 8, V8DImode, DImode) -DEF_MACHMODE (V8QImode, "V8QI", MODE_VECTOR_INT, BITS_PER_UNIT*8, 8, 1, V4HImode) -DEF_MACHMODE (V8HImode, "V8HI", MODE_VECTOR_INT, BITS_PER_UNIT*16, 16, 2, V4SImode) -DEF_MACHMODE (V8SImode, "V8SI", MODE_VECTOR_INT, BITS_PER_UNIT*32, 32, 4, V4DImode) -DEF_MACHMODE (V8DImode, "V8DI", MODE_VECTOR_INT, BITS_PER_UNIT*64, 64, 8, VOIDmode) +DEF_MACHMODE (V8QImode, "V8QI", MODE_VECTOR_INT, BITS_PER_UNIT*8, 8, 1, V4HImode, QImode) +DEF_MACHMODE (V8HImode, "V8HI", MODE_VECTOR_INT, BITS_PER_UNIT*16, 16, 2, V4SImode, HImode) +DEF_MACHMODE (V8SImode, "V8SI", MODE_VECTOR_INT, BITS_PER_UNIT*32, 32, 4, V4DImode, SImode) +DEF_MACHMODE (V8DImode, "V8DI", MODE_VECTOR_INT, BITS_PER_UNIT*64, 64, 8, VOIDmode, DImode) -DEF_MACHMODE (V16QImode, "V16QI", MODE_VECTOR_INT, BITS_PER_UNIT*16, 16, 1, V8HImode) +DEF_MACHMODE (V16QImode, "V16QI", MODE_VECTOR_INT, BITS_PER_UNIT*16, 16, 1, V8HImode, QImode) -DEF_MACHMODE (V2SFmode, "V2SF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*8, 8, 4, V4SFmode) -DEF_MACHMODE (V2DFmode, "V2DF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*16, 16, 8, V8SFmode) +DEF_MACHMODE (V2SFmode, "V2SF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*8, 8, 4, V4SFmode, SFmode) +DEF_MACHMODE (V2DFmode, "V2DF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*16, 16, 8, V8SFmode, DFmode) -DEF_MACHMODE (V4SFmode, "V4SF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*16, 16, 4, V2DFmode) -DEF_MACHMODE (V4DFmode, "V4DF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*32, 32, 8, V8DFmode) +DEF_MACHMODE (V4SFmode, "V4SF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*16, 16, 4, V2DFmode, SFmode) +DEF_MACHMODE (V4DFmode, "V4DF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*32, 32, 8, V8DFmode, DFmode) -DEF_MACHMODE (V8SFmode, "V8SF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*32, 32, 4,V4DFmode) -DEF_MACHMODE (V8DFmode, "V8DF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*64, 64, 8, VOIDmode) -DEF_MACHMODE (V16SFmode, "V16SF", MODE_VECTOR_FLOAT, 512, 64, 4, VOIDmode) +DEF_MACHMODE (V8SFmode, "V8SF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*32, 32, 4,V4DFmode, SFmode) +DEF_MACHMODE (V8DFmode, "V8DF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*64, 64, 8, VOIDmode, DFmode) +DEF_MACHMODE (V16SFmode, "V16SF", MODE_VECTOR_FLOAT, 512, 64, 4, VOIDmode, SFmode) /* BLKmode is used for structures, arrays, etc. that fit no more specific mode. */ -DEF_MACHMODE (BLKmode, "BLK", MODE_RANDOM, 0, 0, 0, VOIDmode) +DEF_MACHMODE (BLKmode, "BLK", MODE_RANDOM, 0, 0, 0, VOIDmode, VOIDmode) /* The modes for representing the condition codes come last. CCmode is always defined. Additional modes for the condition code can be specified in the EXTRA_CC_MODES macro. All MODE_CC modes are the same width as SImode and have VOIDmode as their next wider mode. */ -#define CC(E, M) DEF_MACHMODE (E, M, MODE_CC, BITS_PER_UNIT*4, 4, 4, VOIDmode) +#define CC(E, M) DEF_MACHMODE (E, M, MODE_CC, BITS_PER_UNIT*4, 4, 4, VOIDmode, VOIDmode) CC (CCmode, "CC") @@ -167,7 +171,7 @@ EXTRA_CC_MODES lot of redundancy in ports that support both 32-bit and 64-bit targets. */ #ifdef GENERATOR_FILE #undef Pmode -DEF_MACHMODE (Pmode, "P", MODE_RANDOM, 0, 0, 0, VOIDmode) +DEF_MACHMODE (Pmode, "P", MODE_RANDOM, 0, 0, 0, VOIDmode, VOIDmode) #endif /* diff --git a/gcc/machmode.h b/gcc/machmode.h index 0f285e36524..f581cd041bd 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -24,7 +24,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA /* Make an enum class that gives all the machine modes. */ -#define DEF_MACHMODE(SYM, NAME, TYPE, BITSIZE, SIZE, UNIT, WIDER) SYM, +#define DEF_MACHMODE(SYM, NAME, TYPE, BITSIZE, SIZE, UNIT, WIDER, INNER) SYM, enum machine_mode { #include "machmode.def" @@ -107,6 +107,12 @@ extern const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES]; #define GET_MODE_MASK(MODE) mode_mask_array[(int) (MODE)] +extern const enum machine_mode inner_mode_array[NUM_MACHINE_MODES]; + +/* Return the mode of the inner elements in a vector. */ + +#define GET_MODE_INNER(MODE) inner_mode_array[(int) (MODE)] + #endif /* defined (HOST_WIDE_INT) && ! defined GET_MODE_MASK */ #if ! defined GET_MODE_WIDER_MODE || ! defined GET_MODE_ALIGNMENT \ diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 594cf0ba4c2..adb18817288 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -707,6 +707,22 @@ print_node (file, prefix, node, indent) } break; + case VECTOR_CST: + { + tree vals = TREE_VECTOR_CST_ELTS (node); + char buf[10]; + tree link; + int i; + + i = 0; + for (link = vals; link; link = TREE_CHAIN (link), ++i) + { + sprintf (buf, "elt%d: ", i); + print_node (file, buf, TREE_VALUE (link), indent + 4); + } + } + break; + case COMPLEX_CST: print_node (file, "real", TREE_REALPART (node), indent + 4); print_node (file, "imag", TREE_IMAGPART (node), indent + 4); diff --git a/gcc/recog.c b/gcc/recog.c index ec0ec882dc7..6039c4d607a 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -753,6 +753,7 @@ find_single_use_1 (dest, loc) case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE: + case CONST_VECTOR: case CLOBBER: return 0; diff --git a/gcc/regclass.c b/gcc/regclass.c index d064e240b62..93a5edbaf2a 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -2416,6 +2416,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CC0: case PC: case SYMBOL_REF: diff --git a/gcc/regrename.c b/gcc/regrename.c index 674062e37cd..6277398945d 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -678,6 +678,7 @@ scan_rtx (insn, loc, class, action, type, earlyclobber) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case CC0: diff --git a/gcc/reload.c b/gcc/reload.c index 97db874acb3..c4231a2ea12 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -4927,6 +4927,7 @@ subst_reg_equivs (ad, insn) case CONST_INT: case CONST: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case PC: diff --git a/gcc/reload1.c b/gcc/reload1.c index 5211b5fcb36..7b420a1ea3d 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -2282,6 +2282,7 @@ eliminate_regs (x, mem_mode, insn) { case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case SYMBOL_REF: case CODE_LABEL: @@ -2660,6 +2661,7 @@ elimination_effects (x, mem_mode) { case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case SYMBOL_REF: case CODE_LABEL: @@ -3749,6 +3751,7 @@ scan_paradoxical_subregs (x) case SYMBOL_REF: case LABEL_REF: case CONST_DOUBLE: + case CONST_VECTOR: /* shouldn't happen, but just in case. */ case CC0: case PC: case USE: diff --git a/gcc/resource.c b/gcc/resource.c index 5b19fe45450..f306abb304e 100644 --- a/gcc/resource.c +++ b/gcc/resource.c @@ -212,6 +212,7 @@ mark_referenced_resources (x, res, include_delayed_effects) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case PC: case SYMBOL_REF: case LABEL_REF: @@ -645,6 +646,7 @@ mark_set_resources (x, res, in_dest, mark_type) case USE: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case LABEL_REF: case SYMBOL_REF: case CONST: diff --git a/gcc/rtl.c b/gcc/rtl.c index 7f4a4d5dd7c..6077232d0e7 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -115,7 +115,7 @@ const char * const rtx_name[NUM_RTX_CODE] = { /* Indexed by machine mode, gives the name of that machine mode. This name does not include the letters "mode". */ -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) NAME, +#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER, INNER) NAME, const char * const mode_name[NUM_MACHINE_MODES] = { #include "machmode.def" @@ -125,7 +125,7 @@ const char * const mode_name[NUM_MACHINE_MODES] = { /* Indexed by machine mode, gives the class mode for GET_MODE_CLASS. */ -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) CLASS, +#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER, INNER) CLASS, const enum mode_class mode_class[NUM_MACHINE_MODES] = { #include "machmode.def" @@ -136,7 +136,7 @@ const enum mode_class mode_class[NUM_MACHINE_MODES] = { /* Indexed by machine mode, gives the length of the mode, in bits. GET_MODE_BITSIZE uses this. */ -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) BITSIZE, +#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER, INNER) BITSIZE, const unsigned short mode_bitsize[NUM_MACHINE_MODES] = { #include "machmode.def" @@ -147,7 +147,7 @@ const unsigned short mode_bitsize[NUM_MACHINE_MODES] = { /* Indexed by machine mode, gives the length of the mode, in bytes. GET_MODE_SIZE uses this. */ -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) SIZE, +#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER, INNER) SIZE, const unsigned char mode_size[NUM_MACHINE_MODES] = { #include "machmode.def" @@ -158,7 +158,7 @@ const unsigned char mode_size[NUM_MACHINE_MODES] = { /* Indexed by machine mode, gives the length of the mode's subunit. GET_MODE_UNIT_SIZE uses this. */ -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) UNIT, +#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER, INNER) UNIT, const unsigned char mode_unit_size[NUM_MACHINE_MODES] = { #include "machmode.def" /* machine modes are documented here */ @@ -170,7 +170,7 @@ const unsigned char mode_unit_size[NUM_MACHINE_MODES] = { (QI -> HI -> SI -> DI, etc.) Widening multiply instructions use this. */ -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) \ +#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER, INNER) \ (unsigned char) WIDER, const unsigned char mode_wider_mode[NUM_MACHINE_MODES] = { @@ -179,7 +179,7 @@ const unsigned char mode_wider_mode[NUM_MACHINE_MODES] = { #undef DEF_MACHMODE -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) \ +#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER, INNER) \ ((BITSIZE) >= HOST_BITS_PER_WIDE_INT) ? ~(unsigned HOST_WIDE_INT) 0 : ((unsigned HOST_WIDE_INT) 1 << (BITSIZE)) - 1, /* Indexed by machine mode, gives mask of significant bits in mode. */ @@ -188,6 +188,17 @@ const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES] = { #include "machmode.def" }; +#undef DEF_MACHMODE + +#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER, INNER) INNER, + +/* Indexed by machine mode, gives the mode of the inner elements in a + vector type. */ + +const enum machine_mode inner_mode_array[NUM_MACHINE_MODES] = { +#include "machmode.def" +}; + /* Indexed by mode class, gives the narrowest mode for each class. The Q modes are always of width 1 (2 for complex) - it is impossible for any mode to be narrower. @@ -346,6 +357,7 @@ copy_rtx (orig) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -455,6 +467,7 @@ copy_most_rtx (orig, may_share) case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -560,7 +573,13 @@ unsigned int get_mode_alignment (mode) enum machine_mode mode; { - unsigned int alignment = GET_MODE_UNIT_SIZE (mode); + unsigned int alignment; + + if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT + || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT) + alignment = GET_MODE_UNIT_SIZE (mode); + else + alignment = GET_MODE_SIZE (mode); /* Extract the LSB of the size. */ alignment = alignment & -alignment; @@ -626,6 +645,7 @@ rtx_equal_p (x, y) case SCRATCH: case CONST_DOUBLE: case CONST_INT: + case CONST_VECTOR: return 0; default: diff --git a/gcc/rtl.def b/gcc/rtl.def index fc12af2665f..8fad6501864 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -585,6 +585,9 @@ DEF_RTL_EXPR(CONST_INT, "const_int", "w", 'o') there may be from 1 to 4; see rtl.c. */ DEF_RTL_EXPR(CONST_DOUBLE, "const_double", CONST_DOUBLE_FORMAT, 'o') +/* Describes a vector constant. */ +DEF_RTL_EXPR(CONST_VECTOR, "const_vector", "E", 'x') + /* String constant. Used only for attributes right now. */ DEF_RTL_EXPR(CONST_STRING, "const_string", "s", 'o') @@ -972,10 +975,6 @@ DEF_RTL_EXPR(VEC_SELECT, "vec_select", "ee", 'x') combined and is the concatenation of the two source vectors. */ DEF_RTL_EXPR(VEC_CONCAT, "vec_concat", "ee", 'x') -/* Describes a vector constant. Each part of the PARALLEL that is operand 0 - describes a constant for one of the subparts. */ -DEF_RTL_EXPR(VEC_CONST, "vec_const", "e", 'x') - /* Describes an operation that converts a small vector into a larger one by duplicating the input values. The output vector mode must have the same submodes as the input vector mode, and the number of output parts must be diff --git a/gcc/rtl.h b/gcc/rtl.h index 99fabfcb3ff..714faac91c6 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -255,6 +255,7 @@ struct rtvec_def { (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE \ || GET_CODE (X) == CONST || GET_CODE (X) == HIGH \ + || GET_CODE (X) == CONST_VECTOR \ || GET_CODE (X) == CONSTANT_P_RTX) /* General accessor macros for accessing the fields of an rtx. */ @@ -823,6 +824,12 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS]; /* Link for chain of all CONST_DOUBLEs in use in current function. */ #define CONST_DOUBLE_CHAIN(r) XCEXP (r, 0, CONST_DOUBLE) +/* For a CONST_VECTOR, return element #n. */ +#define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR) + +/* For a CONST_VECTOR, return the number of elements in a vector. */ +#define CONST_VECTOR_NUNITS(RTX) XCVECLEN (RTX, 0, CONST_VECTOR) + /* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of. SUBREG_BYTE extracts the byte-number. */ diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index f185c616f5a..37f1e64910a 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -64,6 +64,7 @@ rtx_unstable_p (x) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: return 0; @@ -139,6 +140,7 @@ rtx_varies_p (x, for_alias) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: return 0; @@ -502,6 +504,7 @@ count_occurrences (x, find, count_dest) case REG: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: @@ -580,7 +583,8 @@ reg_mentioned_p (reg, in) case CONST_INT: return GET_CODE (reg) == CONST_INT && INTVAL (in) == INTVAL (reg); - + + case CONST_VECTOR: case CONST_DOUBLE: /* These are kept unique for a given value. */ return 0; @@ -829,6 +833,7 @@ regs_set_between_p (x, start, end) { case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case SYMBOL_REF: case LABEL_REF: @@ -875,6 +880,7 @@ modified_between_p (x, start, end) { case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case SYMBOL_REF: case LABEL_REF: @@ -930,6 +936,7 @@ modified_in_p (x, insn) { case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case SYMBOL_REF: case LABEL_REF: @@ -2021,6 +2028,7 @@ volatile_insn_p (x) case CONST_INT: case CONST: case CONST_DOUBLE: + case CONST_VECTOR: case CC0: case PC: case REG: @@ -2087,6 +2095,7 @@ volatile_refs_p (x) case CONST_INT: case CONST: case CONST_DOUBLE: + case CONST_VECTOR: case CC0: case PC: case REG: @@ -2153,6 +2162,7 @@ side_effects_p (x) case CONST_INT: case CONST: case CONST_DOUBLE: + case CONST_VECTOR: case CC0: case PC: case REG: @@ -2231,6 +2241,7 @@ may_trap_p (x) /* Handle these cases quickly. */ case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case LABEL_REF: case CONST: @@ -2339,6 +2350,7 @@ inequality_comparisons_p (x) case CC0: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case LABEL_REF: case SYMBOL_REF: @@ -2452,6 +2464,7 @@ replace_regs (x, reg_map, nregs, replace_dest) case CC0: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST: case SYMBOL_REF: case LABEL_REF: @@ -2542,6 +2555,7 @@ computed_jump_p_1 (x) case CONST: case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case REG: return 1; diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index 9f20aad331b..5fb23b76d9b 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -723,6 +723,7 @@ sched_analyze_2 (deps, x, insn) { case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case SYMBOL_REF: case CONST: case LABEL_REF: diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 02ba7161b46..f8ca55c780f 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1223,6 +1223,7 @@ walk_tree (tp, func, data, htab_) case IDENTIFIER_NODE: case INTEGER_CST: case REAL_CST: + case VECTOR_CST: case STRING_CST: case REAL_TYPE: case COMPLEX_TYPE: diff --git a/gcc/tree.c b/gcc/tree.c index e2829491ca4..764aa798ed8 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -558,6 +558,35 @@ build_int_2_wide (low, hi) return t; } +/* Return a new VECTOR_CST node whose type is TYPE and whose values + are in a list pointed by VALS. */ + +tree +build_vector (type, vals) + tree type, vals; +{ + tree v = make_node (VECTOR_CST); + int over1 = 0, over2 = 0; + tree link; + + TREE_VECTOR_CST_ELTS (v) = vals; + TREE_TYPE (v) = type; + + /* Iterate through elements and check for overflow. */ + for (link = vals; link; link = TREE_CHAIN (link)) + { + tree value = TREE_VALUE (link); + + over1 |= TREE_OVERFLOW (value); + over2 |= TREE_CONSTANT_OVERFLOW (value); + } + + TREE_OVERFLOW (v) = over1; + TREE_CONSTANT_OVERFLOW (v) = over2; + + return v; +} + /* Return a new REAL_CST node whose type is TYPE and value is D. */ tree diff --git a/gcc/tree.def b/gcc/tree.def index 39ea31c033b..9cfe139ac57 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -269,6 +269,9 @@ DEFTREECODE (REAL_CST, "real_cst", 'c', 3) Also there is TREE_CST_RTL. */ DEFTREECODE (COMPLEX_CST, "complex_cst", 'c', 3) +/* Contents are in TREE_VECTOR_CST_ELTS field. */ +DEFTREECODE (VECTOR_CST, "vector_cst", 'c', 3) + /* Contents are TREE_STRING_LENGTH and TREE_STRING_POINTER fields. Also there is TREE_CST_RTL. */ DEFTREECODE (STRING_CST, "string_cst", 'c', 3) diff --git a/gcc/tree.h b/gcc/tree.h index fe4e0335012..d4f4c50c636 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -175,14 +175,14 @@ struct tree_common TREE_VIA_VIRTUAL in TREE_LIST or TREE_VEC TREE_CONSTANT_OVERFLOW in - INTEGER_CST, REAL_CST, COMPLEX_CST + INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST TREE_SYMBOL_REFERENCED in IDENTIFIER_NODE public_flag: TREE_OVERFLOW in - INTEGER_CST, REAL_CST, COMPLEX_CST + INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST TREE_PUBLIC in VAR_DECL or FUNCTION_DECL or IDENTIFIER_NODE TREE_VIA_PUBLIC in @@ -512,9 +512,10 @@ extern void tree_class_check_failed PARAMS ((const tree, int, chain is via a `virtual' declaration. */ #define TREE_VIA_VIRTUAL(NODE) ((NODE)->common.static_flag) -/* In an INTEGER_CST, REAL_CST, or COMPLEX_CST, this means there was an - overflow in folding. This is distinct from TREE_OVERFLOW because ANSI C - requires a diagnostic when overflows occur in constant expressions. */ +/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, or VECTOR_CST this means + there was an overflow in folding. This is distinct from + TREE_OVERFLOW because ANSI C requires a diagnostic when overflows + occur in constant expressions. */ #define TREE_CONSTANT_OVERFLOW(NODE) ((NODE)->common.static_flag) /* In an IDENTIFIER_NODE, this means that assemble_name was called with @@ -522,9 +523,10 @@ extern void tree_class_check_failed PARAMS ((const tree, int, #define TREE_SYMBOL_REFERENCED(NODE) \ (IDENTIFIER_NODE_CHECK (NODE)->common.static_flag) -/* In an INTEGER_CST, REAL_CST, of COMPLEX_CST, this means there was an - overflow in folding, and no warning has been issued for this subexpression. - TREE_OVERFLOW implies TREE_CONSTANT_OVERFLOW, but not vice versa. */ +/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, or VECTOR_CST, this means + there was an overflow in folding, and no warning has been issued + for this subexpression. TREE_OVERFLOW implies + TREE_CONSTANT_OVERFLOW, but not vice versa. */ #define TREE_OVERFLOW(NODE) ((NODE)->common.public_flag) /* In a VAR_DECL or FUNCTION_DECL, @@ -707,9 +709,9 @@ struct tree_int_cst } int_cst; }; -/* In REAL_CST, STRING_CST, COMPLEX_CST nodes, and CONSTRUCTOR nodes, - and generally in all kinds of constants that could - be given labels (rather than being immediate). */ +/* In REAL_CST, STRING_CST, COMPLEX_CST, VECTOR_CST nodes, and + CONSTRUCTOR nodes, and generally in all kinds of constants that + could be given labels (rather than being immediate). */ #define TREE_CST_RTL(NODE) (CST_OR_CONSTRUCTOR_CHECK (NODE)->real_cst.rtl) @@ -752,6 +754,16 @@ struct tree_complex tree real; tree imag; }; + +/* In a VECTOR_CST node. */ +#define TREE_VECTOR_CST_ELTS(NODE) (VECTOR_CST_CHECK (NODE)->vector.elements) + +struct tree_vector +{ + struct tree_common common; + rtx rtl; + tree elements; +}; #include "hashtable.h" @@ -1843,6 +1855,7 @@ union tree_node struct tree_common common; struct tree_int_cst int_cst; struct tree_real_cst real_cst; + struct tree_vector vector; struct tree_string string; struct tree_complex complex; struct tree_identifier identifier; @@ -2093,6 +2106,7 @@ extern tree build PARAMS ((enum tree_code, tree, ...)); extern tree build_nt PARAMS ((enum tree_code, ...)); extern tree build_int_2_wide PARAMS ((unsigned HOST_WIDE_INT, HOST_WIDE_INT)); +extern tree build_vector PARAMS ((tree, tree)); extern tree build_real PARAMS ((tree, REAL_VALUE_TYPE)); extern tree build_real_from_int_cst PARAMS ((tree, tree)); extern tree build_complex PARAMS ((tree, tree, tree)); diff --git a/gcc/varasm.c b/gcc/varasm.c index 0ca2172c32c..67d64e6263b 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2382,7 +2382,8 @@ decode_addr_const (exp, value) value->offset = offset; } -enum kind { RTX_UNKNOWN, RTX_DOUBLE, RTX_INT, RTX_UNSPEC }; +/* We do RTX_UNSPEC + XINT (blah), so nothing can go after RTX_UNSPEC. */ +enum kind { RTX_UNKNOWN, RTX_DOUBLE, RTX_INT, RTX_VECTOR, RTX_UNSPEC }; struct rtx_const { ENUM_BITFIELD(kind) kind : 16; @@ -2391,6 +2392,10 @@ struct rtx_const union real_extract du; struct addr_const addr; struct {HOST_WIDE_INT high, low;} di; + + /* The max vector size we have is 8 wide. This should be enough. */ + HOST_WIDE_INT veclo[16]; + HOST_WIDE_INT vechi[16]; } un; }; @@ -3580,6 +3585,34 @@ decode_rtx_const (mode, x, value) } break; + case CONST_VECTOR: + { + int units, i; + rtx elt; + + units = CONST_VECTOR_NUNITS (x); + value->kind = RTX_VECTOR; + value->mode = mode; + + for (i = 0; i < units; ++i) + { + elt = CONST_VECTOR_ELT (x, i); + if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + { + value->un.veclo[i] = (HOST_WIDE_INT) INTVAL (elt); + value->un.vechi[i] = 0; + } + else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) + { + value->un.veclo[i] = (HOST_WIDE_INT) CONST_DOUBLE_LOW (elt); + value->un.vechi[i] = (HOST_WIDE_INT) CONST_DOUBLE_HIGH (elt); + } + else + abort (); + } + } + break; + case CONST_INT: value->un.addr.offset = INTVAL (x); break; @@ -4007,6 +4040,46 @@ output_constant_pool (fnname, fndecl) assemble_integer (x, GET_MODE_SIZE (pool->mode), pool->align, 1); break; + case MODE_VECTOR_FLOAT: + { + int i, units; + rtx elt; + + if (GET_CODE (x) != CONST_VECTOR) + abort (); + + units = CONST_VECTOR_NUNITS (x); + + for (i = 0; i < units; i++) + { + elt = CONST_VECTOR_ELT (x, i); + memcpy ((char *) &u, + (char *) &CONST_DOUBLE_LOW (elt), + sizeof u); + assemble_real (u.d, GET_MODE_INNER (pool->mode), pool->align); + } + } + break; + + case MODE_VECTOR_INT: + { + int i, units; + rtx elt; + + if (GET_CODE (x) != CONST_VECTOR) + abort (); + + units = CONST_VECTOR_NUNITS (x); + + for (i = 0; i < units; i++) + { + elt = CONST_VECTOR_ELT (x, i); + assemble_integer (elt, GET_MODE_UNIT_SIZE (pool->mode), + pool->align, 1); + } + } + break; + default: abort (); } @@ -4255,6 +4328,7 @@ initializer_constant_valid_p (value, endtype) return TREE_STATIC (value) ? null_pointer_node : 0; case INTEGER_CST: + case VECTOR_CST: case REAL_CST: case STRING_CST: case COMPLEX_CST: |