+2009-11-25 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/predicates.md (emms_operation): New predicate.
+ (vzeroupper_operation): Ditto.
+ (vzeroall_operation): Improve pattern recognition.
+ * config/i386/sse.md (avx_vzeroupper_rex64): Remove insn pattern.
+ (avx_vzeroupper): Change insn pattern to expander.
+ (*avx_vzeroupper): New insn pattern. Use vzeroupper_operation
+ predicate.
+ (*avx_vzeroall): Remove operands 1 and 2.
+ * config/i386/mmx.md (mmx_emms): Change insn pattern to expander.
+ (mmx_femms): Ditto.
+ (*mmx_emms): New insn pattern. Use emms_operation predicate.
+ (*mmx_femms): Ditto.
+ * config/i386/i386.c (enum ix86_builtins)
+ <IX86_BUILTIN_VZEROUPPER_REX64>: Remove.
+ (struct builtin_description) <CODE_FOR_avx_vzeroupper_rex64>:
+ Remove initailization.
+ <CODE_FOR_avx_vzeroupper>: Unconditionally initialize here.
+
2009-11-25 Paul Brook <paul@codesourcery.com>
* config/arm/arm.md (consttable_4): Handle (high ...).
IX86_BUILTIN_EXTRACTF128SI256,
IX86_BUILTIN_VZEROALL,
IX86_BUILTIN_VZEROUPPER,
- IX86_BUILTIN_VZEROUPPER_REX64,
IX86_BUILTIN_VPERMILVARPD,
IX86_BUILTIN_VPERMILVARPS,
IX86_BUILTIN_VPERMILVARPD256,
/* AVX */
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vzeroall, "__builtin_ia32_vzeroall", IX86_BUILTIN_VZEROALL, UNKNOWN, (int) VOID_FTYPE_VOID },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vzeroupper, 0, IX86_BUILTIN_VZEROUPPER, UNKNOWN, (int) VOID_FTYPE_VOID },
- { OPTION_MASK_ISA_AVX | OPTION_MASK_ISA_64BIT, CODE_FOR_avx_vzeroupper_rex64, 0, IX86_BUILTIN_VZEROUPPER_REX64, UNKNOWN, (int) VOID_FTYPE_VOID },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vzeroupper, "__builtin_ia32_vzeroupper", IX86_BUILTIN_VZEROUPPER, UNKNOWN, (int) VOID_FTYPE_VOID },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vbroadcastss, "__builtin_ia32_vbroadcastss", IX86_BUILTIN_VBROADCASTSS, UNKNOWN, (int) V4SF_FTYPE_PCFLOAT },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vbroadcastsd256, "__builtin_ia32_vbroadcastsd256", IX86_BUILTIN_VBROADCASTSD256, UNKNOWN, (int) V4DF_FTYPE_PCDOUBLE },
def_builtin_const (OPTION_MASK_ISA_PCLMUL, "__builtin_ia32_pclmulqdq128",
V2DI_FTYPE_V2DI_V2DI_INT, IX86_BUILTIN_PCLMULQDQ128);
- /* AVX */
- def_builtin (OPTION_MASK_ISA_AVX, "__builtin_ia32_vzeroupper",
- VOID_FTYPE_VOID,
- (TARGET_64BIT ? IX86_BUILTIN_VZEROUPPER_REX64
- : IX86_BUILTIN_VZEROUPPER));
-
/* MMX access to the vec_init patterns. */
def_builtin_const (OPTION_MASK_ISA_MMX, "__builtin_ia32_vec_init_v2si",
V2SI_FTYPE_INT_INT, IX86_BUILTIN_VEC_INIT_V2SI);
[(set_attr "type" "mmxcvt")
(set_attr "mode" "DI")])
-(define_insn "mmx_emms"
- [(unspec_volatile [(const_int 0)] UNSPECV_EMMS)
- (clobber (reg:XF ST0_REG))
- (clobber (reg:XF ST1_REG))
- (clobber (reg:XF ST2_REG))
- (clobber (reg:XF ST3_REG))
- (clobber (reg:XF ST4_REG))
- (clobber (reg:XF ST5_REG))
- (clobber (reg:XF ST6_REG))
- (clobber (reg:XF ST7_REG))
- (clobber (reg:DI MM0_REG))
- (clobber (reg:DI MM1_REG))
- (clobber (reg:DI MM2_REG))
- (clobber (reg:DI MM3_REG))
- (clobber (reg:DI MM4_REG))
- (clobber (reg:DI MM5_REG))
- (clobber (reg:DI MM6_REG))
- (clobber (reg:DI MM7_REG))]
+(define_expand "mmx_emms"
+ [(match_par_dup 0 [(const_int 0)])]
+ "TARGET_MMX"
+{
+ int regno;
+
+ operands[0] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (17));
+
+ XVECEXP (operands[0], 0, 0)
+ = gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec (1, const0_rtx),
+ UNSPECV_EMMS);
+
+ for (regno = 0; regno < 8; regno++)
+ {
+ XVECEXP (operands[0], 0, regno + 1)
+ = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (XFmode, FIRST_STACK_REG + regno));
+
+ XVECEXP (operands[0], 0, regno + 9)
+ = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (DImode, FIRST_MMX_REG + regno));
+ }
+})
+
+(define_insn "*mmx_emms"
+ [(match_parallel 0 "emms_operation"
+ [(unspec_volatile [(const_int 0)] UNSPECV_EMMS)])]
"TARGET_MMX"
"emms"
[(set_attr "type" "mmx")
(set_attr "modrm" "0")
- (set_attr "memory" "unknown")])
-
-(define_insn "mmx_femms"
- [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS)
- (clobber (reg:XF ST0_REG))
- (clobber (reg:XF ST1_REG))
- (clobber (reg:XF ST2_REG))
- (clobber (reg:XF ST3_REG))
- (clobber (reg:XF ST4_REG))
- (clobber (reg:XF ST5_REG))
- (clobber (reg:XF ST6_REG))
- (clobber (reg:XF ST7_REG))
- (clobber (reg:DI MM0_REG))
- (clobber (reg:DI MM1_REG))
- (clobber (reg:DI MM2_REG))
- (clobber (reg:DI MM3_REG))
- (clobber (reg:DI MM4_REG))
- (clobber (reg:DI MM5_REG))
- (clobber (reg:DI MM6_REG))
- (clobber (reg:DI MM7_REG))]
+ (set_attr "memory" "none")])
+
+(define_expand "mmx_femms"
+ [(match_par_dup 0 [(const_int 0)])]
+ "TARGET_3DNOW"
+{
+ int regno;
+
+ operands[0] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (17));
+
+ XVECEXP (operands[0], 0, 0)
+ = gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec (1, const0_rtx),
+ UNSPECV_FEMMS);
+
+ for (regno = 0; regno < 8; regno++)
+ {
+ XVECEXP (operands[0], 0, regno + 1)
+ = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (XFmode, FIRST_STACK_REG + regno));
+
+ XVECEXP (operands[0], 0, regno + 9)
+ = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (DImode, FIRST_MMX_REG + regno));
+ }
+})
+
+(define_insn "*mmx_femms"
+ [(match_parallel 0 "emms_operation"
+ [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS)])]
"TARGET_3DNOW"
"femms"
[(set_attr "type" "mmx")
(and (match_code "mem")
(match_test "MEM_ALIGN (op) < GET_MODE_ALIGNMENT (mode)")))
+;; Return 1 if OP is a emms operation, known to be a PARALLEL.
+(define_predicate "emms_operation"
+ (match_code "parallel")
+{
+ unsigned i;
+
+ if (XVECLEN (op, 0) != 17)
+ return 0;
+
+ for (i = 0; i < 8; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i+1);
+
+ if (GET_CODE (elt) != CLOBBER
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != XFmode
+ || REGNO (SET_DEST (elt)) != FIRST_STACK_REG + i)
+ return 0;
+
+ elt = XVECEXP (op, 0, i+9);
+
+ if (GET_CODE (elt) != CLOBBER
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != DImode
+ || REGNO (SET_DEST (elt)) != FIRST_MMX_REG + i)
+ return 0;
+ }
+ return 1;
+})
+
;; Return 1 if OP is a vzeroall operation, known to be a PARALLEL.
(define_predicate "vzeroall_operation"
(match_code "parallel")
{
- int nregs = TARGET_64BIT ? 16 : 8;
+ unsigned i, nregs = TARGET_64BIT ? 16 : 8;
- if (XVECLEN (op, 0) != nregs + 1)
+ if ((unsigned) XVECLEN (op, 0) != 1 + nregs)
return 0;
+ for (i = 0; i < nregs; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i+1);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V8SImode
+ || REGNO (SET_DEST (elt)) != SSE_REGNO (i)
+ || SET_SRC (elt) != CONST0_RTX (V8SImode))
+ return 0;
+ }
+ return 1;
+})
+
+;; Return 1 if OP is a vzeroupper operation, known to be a PARALLEL.
+(define_predicate "vzeroupper_operation"
+ (match_code "parallel")
+{
+ unsigned i, nregs = TARGET_64BIT ? 16 : 8;
+
+ if ((unsigned) XVECLEN (op, 0) != 1 + nregs)
+ return 0;
+
+ for (i = 0; i < nregs; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i+1);
+
+ if (GET_CODE (elt) != CLOBBER
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V8SImode
+ || REGNO (SET_DEST (elt)) != SSE_REGNO (i))
+ return 0;
+ }
return 1;
})
(define_insn "*avx_vzeroall"
[(match_parallel 0 "vzeroall_operation"
- [(unspec_volatile [(const_int 0)] UNSPECV_VZEROALL)
- (set (match_operand 1 "register_operand" "=x")
- (match_operand 2 "const0_operand" "X"))])]
+ [(unspec_volatile [(const_int 0)] UNSPECV_VZEROALL)])]
"TARGET_AVX"
"vzeroall"
[(set_attr "type" "sse")
(set_attr "mode" "OI")])
;; vzeroupper clobbers the upper 128bits of AVX registers.
-(define_insn "avx_vzeroupper"
- [(unspec_volatile [(const_int 0)] UNSPECV_VZEROUPPER)
- (clobber (reg:V8SI XMM0_REG))
- (clobber (reg:V8SI XMM1_REG))
- (clobber (reg:V8SI XMM2_REG))
- (clobber (reg:V8SI XMM3_REG))
- (clobber (reg:V8SI XMM4_REG))
- (clobber (reg:V8SI XMM5_REG))
- (clobber (reg:V8SI XMM6_REG))
- (clobber (reg:V8SI XMM7_REG))]
- "TARGET_AVX && !TARGET_64BIT"
- "vzeroupper"
- [(set_attr "type" "sse")
- (set_attr "modrm" "0")
- (set_attr "memory" "none")
- (set_attr "prefix" "vex")
- (set_attr "mode" "OI")])
+(define_expand "avx_vzeroupper"
+ [(match_par_dup 0 [(const_int 0)])]
+ "TARGET_AVX"
+{
+ int nregs = TARGET_64BIT ? 16 : 8;
+ int regno;
-(define_insn "avx_vzeroupper_rex64"
- [(unspec_volatile [(const_int 0)] UNSPECV_VZEROUPPER)
- (clobber (reg:V8SI XMM0_REG))
- (clobber (reg:V8SI XMM1_REG))
- (clobber (reg:V8SI XMM2_REG))
- (clobber (reg:V8SI XMM3_REG))
- (clobber (reg:V8SI XMM4_REG))
- (clobber (reg:V8SI XMM5_REG))
- (clobber (reg:V8SI XMM6_REG))
- (clobber (reg:V8SI XMM7_REG))
- (clobber (reg:V8SI XMM8_REG))
- (clobber (reg:V8SI XMM9_REG))
- (clobber (reg:V8SI XMM10_REG))
- (clobber (reg:V8SI XMM11_REG))
- (clobber (reg:V8SI XMM12_REG))
- (clobber (reg:V8SI XMM13_REG))
- (clobber (reg:V8SI XMM14_REG))
- (clobber (reg:V8SI XMM15_REG))]
- "TARGET_AVX && TARGET_64BIT"
+ operands[0] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nregs + 1));
+
+ XVECEXP (operands[0], 0, 0)
+ = gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec (1, const0_rtx),
+ UNSPECV_VZEROUPPER);
+
+ for (regno = 0; regno < nregs; regno++)
+ XVECEXP (operands[0], 0, regno + 1)
+ = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (V8SImode, SSE_REGNO (regno)));
+})
+
+(define_insn "*avx_vzeroupper"
+ [(match_parallel 0 "vzeroupper_operation"
+ [(unspec_volatile [(const_int 0)] UNSPECV_VZEROUPPER)])]
+ "TARGET_AVX"
"vzeroupper"
[(set_attr "type" "sse")
(set_attr "modrm" "0")