aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Christopher <echristo@gcc.gnu.org>2006-06-29 20:42:54 +0000
committerEric Christopher <echristo@gcc.gnu.org>2006-06-29 20:42:54 +0000
commit5656a184e839836bcacf8f8ed4b94b565159c190 (patch)
treebdbc0fc4139526168815d26977ec3edc0a3f6db5
parentc8d560fa808c83063ffc3696ad829d1f30ff57f2 (diff)
downloadgcc-5656a184e839836bcacf8f8ed4b94b565159c190.zip
gcc-5656a184e839836bcacf8f8ed4b94b565159c190.tar.gz
gcc-5656a184e839836bcacf8f8ed4b94b565159c190.tar.bz2
predicates.md (vector_all_ones_operand): New.
2006-06-29 Eric Christopher <echristo@apple.com> Evan Cheng <evan.cheng@apple.com> * predicates.md (vector_all_ones_operand): New. (nonimmediate_or_sse_const_operand): Ditto. * config/i386/i386-protos.h (standard_sse_constant_opcode): Declare. * config/i386/i386.c (standard_sse_constant_opcode): Define. (standard_sse_mode_p): Ditto. (standard_sse_constant_p): Add case for -1 vector. (ix86_expand_vector_move): Try to use. * sse.md (*mov<mode>_internal): Use nonimmediate_or_sse_const_operand. Call standard_sse_constant_opcode. (*movv4sf_internal): Ditto. (*movv2df_internal): Ditto. From-SVN: r115077
-rw-r--r--gcc/ChangeLog35
-rw-r--r--gcc/config/i386/i386-protos.h3
-rw-r--r--gcc/config/i386/i386.c129
-rw-r--r--gcc/config/i386/predicates.md35
-rw-r--r--gcc/config/i386/sse.md32
5 files changed, 166 insertions, 68 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c27d6d2..fdcc4b8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2006-06-29 Eric Christopher <echristo@apple.com>
+ Evan Cheng <evan.cheng@apple.com>
+
+ * predicates.md (vector_all_ones_operand): New.
+ (nonimmediate_or_sse_const_operand): Ditto.
+ * config/i386/i386-protos.h (standard_sse_constant_opcode): Declare.
+ * config/i386/i386.c (standard_sse_constant_opcode): Define.
+ (standard_sse_mode_p): Ditto.
+ (standard_sse_constant_p): Add case for -1 vector.
+ (ix86_expand_vector_move): Try to use.
+ * sse.md (*mov<mode>_internal): Use nonimmediate_or_sse_const_operand.
+ Call standard_sse_constant_opcode.
+ (*movv4sf_internal): Ditto.
+ (*movv2df_internal): Ditto.
+
2006-06-29 Roger Sayle <roger@eyesopen.com>
* genpreds.c (write_match_code_switch): Correctly use XSTR instead
@@ -51,7 +66,7 @@
* config/m32c/mov.md (SI mov peephole): New.
* config/m32c/m32.c (m32c_immd_dbl_mov): New.
* config/m32c/m32c-protos.h (m32c_immd_dbl_mov): New.
-
+
2006-06-26 Olivier Hainque <hainque@adacore.com>
* function.c (aggregate_value_p): Honor DECL_BY_REFERENCE on
@@ -239,7 +254,7 @@
function.
* alloc-pool.c (free_alloc_pool_if_empty): New function.
* et-forest.h (et_free_pools): Prototype new function.
- * et-forest.c (et_free_tree_force): Free parent occurrence.
+ * et-forest.c (et_free_tree_force): Free parent occurrence.
(et_free_pools): New function.
* dominance.c (free_dominance_info): Free et-forest alloc
pools.
@@ -325,11 +340,11 @@
Fix PR tree-optimization/27341
* tree-cfg.c (gimplify_val): Call mark_new_vars_to_rename on the
statement we get.
- * tree-complex.c (pass_lower_complex): Update SMT usage.
+ * tree-complex.c (pass_lower_complex): Update SMT usage.
2006-06-19 Andreas Krebbel <krebbel1@de.ibm.com>
- * config/s390/s390.md ("doloop_si64", "doloop_si31", "doloop_di"):
+ * config/s390/s390.md ("doloop_si64", "doloop_si31", "doloop_di"):
Add a new alternative to the constraint strings. Add move of
operand 1 to 3 to the splitter definition.
("doloop_si_long"): Second contraint alternative removed.
@@ -337,7 +352,7 @@
2006-06-08 Anatoly Sokolov <aesok@post.ru>
* config/avr/avr.h (avr_have_movw_lpmx_p): Declare.
- (TARGET_CPU_CPP_BUILTINS): Add __AVR_HAVE_MOVW__ and
+ (TARGET_CPU_CPP_BUILTINS): Add __AVR_HAVE_MOVW__ and
__AVR_HAVE_LPMX__.
(AVR_HAVE_MOVW) Define.
(ASSEMBLER_DIALECT): Use AVR_HAVE_MOVW.
@@ -350,7 +365,7 @@
attiny44, attiny84, attiny25, attiny45, attiny85, attiny261,
attiny461, attiny861 and at86rf401 in 'avr25' arhitecture.
(avr_override_options): Init 'avr_have_movw_lpmx_p'.
- (output_movhi, output_movsisf, ashlsi3_out, avr_rtx_costs): Use
+ (output_movhi, output_movsisf, ashlsi3_out, avr_rtx_costs): Use
AVR_HAVE_MOVW.
(avr_file_start): Do not output '.arh' derective.
* config/avr/libgcc.S (mov_l): Use __AVR_HAVE_MOVW__.
@@ -361,7 +376,7 @@
(call_insn, call_value_insn): Use 'call_insn' and __AVR_HAVE_MOVW__.
* config/avr/t-avr(MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Add avr25.
(MULTILIB_MATCHES): Add attiny13, attiny2313, attiny24, attiny44,
- attiny84, attiny25, attiny45, attiny85, attiny261, attiny461,
+ attiny84, attiny25, attiny45, attiny85, attiny261, attiny461,
attiny861 and at86rf401 devices.
2006-06-18 Jie Zhang <jie.zhang@analog.com>
@@ -450,7 +465,7 @@
bind locally.
2006-06-15 Andrew MacLeod <amacleod@redhat.com>
-
+
PR middle-end/27793
* tree-dfa.c (referenced_vars_dup_list): Remove.
(find_referenced_vars): Remove assert.
@@ -502,12 +517,12 @@
* Makefile.in: Define HTMLS_BUILD, HTMLS_INSTALL,
html__strip_dir, html__mkdir_p. Enhance install-html target.
- * configure.ac: AC_SUBST datarootdir, docdir and htmldir.
+ * configure.ac: AC_SUBST datarootdir, docdir and htmldir.
* configure: Regenerate.
2006-06-13 Fariborz Jahanian <fjahanian@apple.com>
- * fold-const.c (fold_cond_expr_with_comparison): Check for
+ * fold-const.c (fold_cond_expr_with_comparison): Check for
Objective-C++ as language in deciding COND_EXPR transformation.
2006-06-06 J"orn Rennecke <joern.rennecke@st.com>
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 315487e..6b9ed89 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -43,6 +43,7 @@ extern int standard_80387_constant_p (rtx);
extern const char *standard_80387_constant_opcode (rtx);
extern rtx standard_80387_constant_rtx (int);
extern int standard_sse_constant_p (rtx);
+extern const char *standard_sse_constant_opcode (rtx, rtx);
extern int symbolic_reference_mentioned_p (rtx);
extern bool extended_reg_mentioned_p (rtx);
extern bool x86_extended_QIreg_mentioned_p (rtx);
@@ -173,7 +174,7 @@ extern int ix86_data_alignment (tree, int);
extern int ix86_local_alignment (tree, int);
extern int ix86_constant_alignment (tree, int);
extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
-extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
+extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 4bea5fe..bce7991 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -742,7 +742,7 @@ const int x86_movx = m_ATHLON_K8 | m_PPRO | m_PENT4 | m_NOCONA | m_GENERIC /* m_
const int x86_double_with_add = ~m_386;
const int x86_use_bit_test = m_386;
const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON_K8 | m_K6 | m_GENERIC;
-const int x86_cmove = m_PPRO | m_ATHLON_K8 | m_PENT4 | m_NOCONA;
+const int x86_cmove = m_PPRO | m_ATHLON_K8 | m_PENT4 | m_NOCONA;
const int x86_fisttp = m_NOCONA;
const int x86_3dnow_a = m_ATHLON_K8;
const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON_K8 | m_PENT4 | m_NOCONA | m_GENERIC;
@@ -2784,7 +2784,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
When we have only some of our vector isa extensions enabled, then there
are some modes for which vector_mode_supported_p is false. For these
modes, the generic vector support in gcc will choose some non-vector mode
- in order to implement the type. By computing the natural mode, we'll
+ in order to implement the type. By computing the natural mode, we'll
select the proper ABI location for the operand and not depend on whatever
the middle-end decides to do with these vector types. */
@@ -3026,10 +3026,10 @@ classify_argument (enum machine_mode mode, tree type,
subclasses[0] = X86_64_SSE_CLASS;
if (subclasses[0] == X86_64_INTEGERSI_CLASS && bytes != 4)
subclasses[0] = X86_64_INTEGER_CLASS;
-
+
for (i = 0; i < words; i++)
classes[i] = subclasses[i % num];
-
+
break;
}
case UNION_TYPE:
@@ -3187,12 +3187,12 @@ classify_argument (enum machine_mode mode, tree type,
return 0;
default:
gcc_assert (VECTOR_MODE_P (mode));
-
+
if (bytes > 16)
return 0;
-
+
gcc_assert (GET_MODE_CLASS (GET_MODE_INNER (mode)) == MODE_INT);
-
+
if (bit_offset + GET_MODE_BITSIZE (mode) <= 32)
classes[0] = X86_64_INTEGERSI_CLASS;
else
@@ -3726,12 +3726,12 @@ contains_128bit_aligned_vector_p (tree type)
case QUAL_UNION_TYPE:
{
tree field;
-
+
if (TYPE_BINFO (type))
{
tree binfo, base_binfo;
int i;
-
+
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
if (contains_128bit_aligned_vector_p
@@ -3753,7 +3753,7 @@ contains_128bit_aligned_vector_p (tree type)
if (contains_128bit_aligned_vector_p (TREE_TYPE (type)))
return true;
break;
-
+
default:
gcc_unreachable ();
}
@@ -4622,14 +4622,60 @@ standard_80387_constant_rtx (int idx)
XFmode);
}
+/* Return 1 if mode is a valid mode for sse. */
+static int
+standard_sse_mode_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case V16QImode:
+ case V8HImode:
+ case V4SImode:
+ case V2DImode:
+ case V4SFmode:
+ case V2DFmode:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
/* Return 1 if X is FP constant we can load to SSE register w/o using memory.
*/
int
standard_sse_constant_p (rtx x)
{
- if (x == const0_rtx)
+ enum machine_mode mode = GET_MODE (x);
+
+ if (x == const0_rtx || x == CONST0_RTX (GET_MODE (x)))
return 1;
- return (x == CONST0_RTX (GET_MODE (x)));
+ if (vector_all_ones_operand (x, mode)
+ && standard_sse_mode_p (mode))
+ return TARGET_SSE2 ? 2 : -1;
+
+ return 0;
+}
+
+/* Return the opcode of the special instruction to be used to load
+ the constant X. */
+
+const char *
+standard_sse_constant_opcode (rtx insn, rtx x)
+{
+ switch (standard_sse_constant_p (x))
+ {
+ case 1:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "xorps\t%0, %0";
+ else if (get_attr_mode (insn) == MODE_V2DF)
+ return "xorpd\t%0, %0";
+ else
+ return "pxor\t%0, %0";
+ case 2:
+ return "pcmpeqd\t%0, %0";
+ }
+ gcc_unreachable ();
}
/* Returns 1 if OP contains a symbol reference */
@@ -4978,7 +5024,7 @@ ix86_initial_elimination_offset (int from, int to)
if (from == ARG_POINTER_REGNUM)
return frame.stack_pointer_offset;
-
+
gcc_assert (from == FRAME_POINTER_REGNUM);
return frame.stack_pointer_offset - frame.frame_pointer_offset;
}
@@ -5318,7 +5364,7 @@ ix86_expand_prologue (void)
/* And here we cheat like madmen with the unwind info. We force the
cfa register back to sp+4, which is exactly what it was at the
start of the function. Re-pushing the return address results in
- the return at the same spot relative to the cfa, and thus is
+ the return at the same spot relative to the cfa, and thus is
correct wrt the unwind info. */
x = cfun->machine->force_align_arg_pointer;
x = gen_frame_mem (Pmode, plus_constant (x, -4));
@@ -6243,7 +6289,7 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
{
rtx reg;
reason_rtx = base;
-
+
if (REG_P (base))
reg = base;
else if (GET_CODE (base) == SUBREG
@@ -6343,7 +6389,7 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
goto is_legitimate_pic;
reason = "64bit address unspec";
goto report_error;
-
+
case UNSPEC_GOTPCREL:
gcc_assert (flag_pic);
goto is_legitimate_pic;
@@ -7103,7 +7149,7 @@ output_pic_addr_const (FILE *file, rtx x, int code)
putc ('+', file);
output_pic_addr_const (file, XEXP (x, 1), code);
}
- else
+ else
{
gcc_assert (GET_CODE (XEXP (x, 1)) == CONST_INT);
output_pic_addr_const (file, XEXP (x, 1), code);
@@ -7195,7 +7241,7 @@ i386_output_dwarf_dtprel (FILE *file, int size, rtx x)
/* In the name of slightly smaller debug output, and to cater to
general assembler lossage, recognize PIC+GOTOFF and turn it back
- into a direct symbol reference.
+ into a direct symbol reference.
On Darwin, this is necessary to avoid a crash, because Darwin
has a different PIC label for each routine but the DWARF debugging
@@ -7274,7 +7320,7 @@ ix86_delegitimize_address (rtx orig_x)
if (! result)
return orig_x;
-
+
if (const_addend)
result = gen_rtx_PLUS (Pmode, result, const_addend);
if (reg_addend)
@@ -8523,7 +8569,7 @@ emit_i387_cw_initialization (int mode)
emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0x8)));
slot = SLOT_CW_CEIL;
break;
-
+
case I387_CW_MASK_PM:
/* mask precision exception for nearbyint() */
emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0020)));
@@ -8833,7 +8879,7 @@ ix86_expand_move (enum machine_mode mode, rtx operands[])
#else
if (GET_CODE (op0) == MEM)
op1 = force_reg (Pmode, op1);
- else
+ else
op1 = legitimize_address (op1, op1, Pmode);
#endif /* TARGET_MACHO */
}
@@ -8894,7 +8940,8 @@ ix86_expand_vector_move (enum machine_mode mode, rtx operands[])
to handle some of them more efficiently. */
if ((reload_in_progress | reload_completed) == 0
&& register_operand (op0, mode)
- && CONSTANT_P (op1) && op1 != CONST0_RTX (mode))
+ && CONSTANT_P (op1)
+ && standard_sse_constant_p (op1) <= 0)
op1 = validize_mem (force_const_mem (mode, op1));
/* Make operand1 a register if it isn't already. */
@@ -8909,7 +8956,7 @@ ix86_expand_vector_move (enum machine_mode mode, rtx operands[])
emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
}
-/* Implement the movmisalign patterns for SSE. Non-SSE modes go
+/* Implement the movmisalign patterns for SSE. Non-SSE modes go
straight to ix86_expand_vector_move. */
void
@@ -11693,9 +11740,9 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode)
{
/* The only non-offsetable memories we handle are pushes. */
int ok = push_operand (operand, VOIDmode);
-
+
gcc_assert (ok);
-
+
operand = copy_rtx (operand);
PUT_MODE (operand, Pmode);
parts[0] = parts[1] = parts[2] = operand;
@@ -11953,7 +12000,7 @@ ix86_split_long_move (rtx operands[])
default:
gcc_unreachable ();
}
-
+
if (GET_MODE (part[1][0]) == SImode)
part[1][0] = part[1][1];
}
@@ -12118,7 +12165,7 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode)
ix86_expand_clear (low[0]);
ix86_expand_clear (high[0]);
emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (single_width)));
-
+
d = gen_lowpart (QImode, low[0]);
d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
s = gen_rtx_EQ (QImode, flags, const0_rtx);
@@ -13591,9 +13638,9 @@ ix86_agi_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type)
if (GET_CODE (addr) == PARALLEL)
addr = XVECEXP (addr, 0, 0);
-
+
gcc_assert (GET_CODE (addr) == SET);
-
+
addr = SET_SRC (addr);
}
else
@@ -15419,7 +15466,7 @@ ix86_init_mmx_sse_builtins (void)
integer_type_node, NULL_TREE);
def_builtin (MASK_SSE, "__builtin_ia32_vec_set_v8hi",
ftype, IX86_BUILTIN_VEC_SET_V8HI);
-
+
ftype = build_function_type_list (V4HI_type_node, V4HI_type_node,
intHI_type_node,
integer_type_node, NULL_TREE);
@@ -15732,7 +15779,7 @@ get_element_number (tree vec_type, tree arg)
instructions from inside the compiler, we can't allow the use of MMX
registers unless the user explicitly asks for it. So we do *not* define
vec_set/vec_extract/vec_init patterns for MMX modes in mmx.md. Instead
- we have builtins invoked by mmintrin.h that gives us license to emit
+ we have builtins invoked by mmintrin.h that gives us license to emit
these sorts of instructions. */
static rtx
@@ -16269,7 +16316,7 @@ rtx
ix86_force_to_memory (enum machine_mode mode, rtx operand)
{
rtx result;
-
+
gcc_assert (reload_completed);
if (TARGET_RED_ZONE)
{
@@ -16371,7 +16418,7 @@ ix86_preferred_reload_class (rtx x, enum reg_class class)
{
enum machine_mode mode = GET_MODE (x);
- /* We're only allowed to return a subclass of CLASS. Many of the
+ /* We're only allowed to return a subclass of CLASS. Many of the
following checks fail for NO_REGS, so eliminate that early. */
if (class == NO_REGS)
return NO_REGS;
@@ -16506,7 +16553,7 @@ ix86_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
if (!TARGET_SSE2)
return true;
- /* If the target says that inter-unit moves are more expensive
+ /* If the target says that inter-unit moves are more expensive
than moving through memory, then don't generate them. */
if (!TARGET_INTER_UNIT_MOVES && !optimize_size)
return true;
@@ -16516,7 +16563,7 @@ ix86_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
return true;
/* ??? For the cost of one register reformat penalty, we could use
- the same instructions to move SFmode and DFmode data, but the
+ the same instructions to move SFmode and DFmode data, but the
relevant move patterns don't support those alternatives. */
if (mode == SFmode || mode == DFmode)
return true;
@@ -16550,7 +16597,7 @@ ix86_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
return true;
/* Vector registers do not support subreg with nonzero offsets, which
- are otherwise valid for integer registers. Since we can't see
+ are otherwise valid for integer registers. Since we can't see
whether we have a nonzero offset from here, prohibit all
nonparadoxical subregs changing size. */
if (GET_MODE_SIZE (to) < GET_MODE_SIZE (from))
@@ -16661,7 +16708,7 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
else if (VALID_FP_MODE_P (mode))
return 1;
/* Lots of MMX code casts 8 byte vector modes to DImode. If we then go
- on to use that value in smaller contexts, this can easily force a
+ on to use that value in smaller contexts, this can easily force a
pseudo to be allocated to GENERAL_REGS. Since this is no worse than
supporting DImode, allow it. */
else if (VALID_MMX_REG_MODE_3DNOW (mode) || VALID_MMX_REG_MODE (mode))
@@ -16670,7 +16717,7 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
return 0;
}
-/* A subroutine of ix86_modes_tieable_p. Return true if MODE is a
+/* A subroutine of ix86_modes_tieable_p. Return true if MODE is a
tieable integer mode. */
static bool
@@ -16718,7 +16765,7 @@ ix86_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
if (mode2 == DFmode)
return mode1 == SFmode;
- /* If MODE2 is only appropriate for an SSE register, then tie with
+ /* If MODE2 is only appropriate for an SSE register, then tie with
any other mode acceptable to SSE registers. */
if (GET_MODE_SIZE (mode2) >= 8
&& ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode2))
@@ -18213,7 +18260,7 @@ ix86_expand_vector_init_general (bool mmx_ok, enum machine_mode mode,
if (!register_operand (op1, half_mode))
op1 = force_reg (half_mode, op1);
- emit_insn (gen_rtx_SET (VOIDmode, target,
+ emit_insn (gen_rtx_SET (VOIDmode, target,
gen_rtx_VEC_CONCAT (mode, op0, op1)));
}
else
@@ -18273,7 +18320,7 @@ ix86_expand_vector_init_general (bool mmx_ok, enum machine_mode mode,
}
}
-/* Initialize vector TARGET via VALS. Suppress the use of MMX
+/* Initialize vector TARGET via VALS. Suppress the use of MMX
instructions unless MMX_OK is true. */
void
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 24f741b..457f556 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -678,11 +678,44 @@
return 1;
})
-;; Return 1 when OP is operand acceptable for standard SSE move.
+/* Return true if operand is a vector constant that is all ones. */
+(define_predicate "vector_all_ones_operand"
+ (match_code "const_vector")
+{
+ int nunits = GET_MODE_NUNITS (mode);
+
+ if (GET_CODE (op) == CONST_VECTOR
+ && CONST_VECTOR_NUNITS (op) == nunits)
+ {
+ int i;
+ for (i = 0; i < nunits; ++i)
+ {
+ rtx x = CONST_VECTOR_ELT (op, i);
+ if (x != constm1_rtx)
+ return 0;
+ }
+ return 1;
+ }
+
+ return 0;
+})
+
+; Return 1 when OP is operand acceptable for standard SSE move.
(define_predicate "vector_move_operand"
(ior (match_operand 0 "nonimmediate_operand")
(match_operand 0 "const0_operand")))
+;; Return 1 when OP is nonimmediate or standard SSE constant.
+(define_predicate "nonimmediate_or_sse_const_operand"
+ (match_operand 0 "general_operand")
+{
+ if (nonimmediate_operand (op, mode))
+ return 1;
+ if (standard_sse_constant_p (op) > 0)
+ return 1;
+ return 0;
+})
+
;; Return true if OP is a register or a zero.
(define_predicate "reg_or_0_operand"
(ior (match_operand 0 "register_operand")
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index ed36276..8886e1f 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -59,16 +59,13 @@
(define_insn "*mov<mode>_internal"
[(set (match_operand:SSEMODEI 0 "nonimmediate_operand" "=x,x ,m")
- (match_operand:SSEMODEI 1 "vector_move_operand" "C ,xm,x"))]
+ (match_operand:SSEMODEI 1 "nonimmediate_or_sse_const_operand" "C ,xm,x"))]
"TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (which_alternative)
{
case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
+ return standard_sse_constant_opcode (insn, operands[1]);
case 1:
case 2:
if (get_attr_mode (insn) == MODE_V4SF)
@@ -101,12 +98,20 @@
(define_insn "*movv4sf_internal"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:V4SF 1 "vector_move_operand" "C,xm,x"))]
+ (match_operand:V4SF 1 "nonimmediate_or_sse_const_operand" "C,xm,x"))]
"TARGET_SSE"
- "@
- xorps\t%0, %0
- movaps\t{%1, %0|%0, %1}
- movaps\t{%1, %0|%0, %1}"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return standard_sse_constant_opcode (insn, operands[1]);
+ case 1:
+ case 2:
+ return "movaps\t{%1, %0|%0, %1}";
+ default:
+ abort();
+ }
+}
[(set_attr "type" "sselog1,ssemov,ssemov")
(set_attr "mode" "V4SF")])
@@ -135,16 +140,13 @@
(define_insn "*movv2df_internal"
[(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:V2DF 1 "vector_move_operand" "C,xm,x"))]
+ (match_operand:V2DF 1 "nonimmediate_or_sse_const_operand" "C,xm,x"))]
"TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (which_alternative)
{
case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "xorpd\t%0, %0";
+ return standard_sse_constant_opcode (insn, operands[1]);
case 1:
case 2:
if (get_attr_mode (insn) == MODE_V4SF)