From patchwork Mon Jun 10 19:22:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 1113295 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-502703-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="L6fgL4hj"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="r9XFIvze"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45N31z3mQKz9s6w for ; Tue, 11 Jun 2019 05:22:59 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=NIhyr4ABjOZmPSE0bxBMGlLsc2qUJoH2qTEyrqVdGaxjUz ypKGcoBciI/aJtegdwzKUfXjkfkIlNhubryYWiOF4LJe3vUIiTRwGEtzLIwUqhKt 8AvoBq2tos9IkTwTX7q4OxZDfzw5gDg7TTVMWN27/4rck1nmB3HtXTsMlB2QQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=j1gbayjehc0t0N6Cr2DJQ6kMstg=; b=L6fgL4hjfI9aAfaPxkTu XSd1nexQ1qRbtFQGBvjJDqafOhL0X1am6zqQX4guvl7IEPacf7maB3Sb8oJb9RMq l/jEDGkJCziIBf6ZrblzAwgmPLcFmRlXryquJ9lHH5Wvi+fZS+o+Ma3V4dTYFzCj lIsO4pYGiA3LN7KTcA4vH1I= Received: (qmail 119071 invoked by alias); 10 Jun 2019 19:22:51 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 119056 invoked by uid 89); 10 Jun 2019 19:22:51 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-6.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=sk:ix86_bu, UD:i386-expand.c, sk:ix86_ex, ssemd X-HELO: mail-it1-f170.google.com Received: from mail-it1-f170.google.com (HELO mail-it1-f170.google.com) (209.85.166.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Jun 2019 19:22:47 +0000 Received: by mail-it1-f170.google.com with SMTP id q14so861842itc.5 for ; Mon, 10 Jun 2019 12:22:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=VjidnC7yPPthakasnjZmHL8pyM6TQ5shnR7cY6YvaSY=; b=r9XFIvzeWSR2VNfuMwkktLNmc06mC4g+TQvR1F6rAH2b/7LXveZZoi50HoXlTnJlDB bXKK3NRHgl44dcZCJ/sFZThLPCWd4mlwtMBUhsDgbKlXDBEvnG7dabnlzY6GRZ6rT4pB IjNg4j1lBE4BVIYW68mv/Tzw2oVPivyrSFohPCFEkRt7Nf2e0bFdn169elb+q195393y o2fnH9n1QLCy/LxNyYJleiH4gfuPi7waquNBGaqxF5L2hAg20y4mAPFs00lEynhaa0a8 VQVTuD3pnNnbqKMXwU5hjz8qYufINJ05d7oYeAIxbgZ8Cr9x0V8/PUkVDE8t+zCc1Gm4 2HVw== MIME-Version: 1.0 From: Uros Bizjak Date: Mon, 10 Jun 2019 21:22:34 +0200 Message-ID: Subject: [PATCH, i386]: Improve and modernize ABS/NEG patterns To: "gcc-patches@gcc.gnu.org" Attached patch improves ABS/NEG expander to emit clobber that enables ABS/NEG with integer registers also when SSE is disabled. The patch modernizes ABS/NEG insn patterns and splitters to use absneg code iterator and relevant mode iterators. Additionally, the patch enables three operand AVX instructions with SSE registers. 2019-06-10 Uroš Bizjak * config/i386/i386-protos.h (ix86_split_fp_absneg_operator): New prototype. * config/i386/i386-expand.c (ix86_expand_fp_absneg_operator): Emit clobber also for non-sse operations. (ix86_split_fp_absneg_operator): New function. * config/i386/i386.md (SSEMODEF): New mode iterator. (ssevecmodef): New mode attribute. (tf2): Use absneg code iterator. (*tf2_1): Rename from *absnegtf3_sse. Use absneg code iterator. Add three-operand AVX alternatives. (*2_i387_1): Rename from *absnegxf2_i387. Use absneg code iterator and X87MODEF mode iterator. (absneg fp_reg non-sse splitter): Call absneg code iterator and X87MODEF mode iterator. (absneg general_reg non-sse splitter): Use absneg code iterator and X87MODEF mode iterator. Use ix86_split_fp_absneg_operator. (*2_1): Rename from *absneg2. Use absneg code iterator. Add three-operand AVX alternative. (absneg sse_reg splitter): Use absneg code iterator and SSEMODEF mode iterator. Handle AVX operands. (absneg fp_reg splitter): Use absneg code iterator and MODEF mode iterator. (absneg general_reg splitter): Merge splitters using MODEF mode iterator. Use absneg code iterator. Call ix86_split_fp_absneg_operator. (*2_i387): Rename from *2_1. Do not enable for non-sse modes before reload. (CSGNMODE): Remove. (CSGNVMODE): Ditto. (copysing3): Use SSEMODEF instead of CSGNMODE and ssevecmodef mode attribute instaed of CSGNVMODE. (copysign3_const): Ditto. (copysign3_var): Ditto. * config/i386/i386.md (*2): Rename from *absneg2. Use absneg code iterator. Simplify code using std::swap. * config/i386/predicates.md (absneg_operator): Remove. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros. Index: config/i386/i386-expand.c =================================================================== --- config/i386/i386-expand.c (revision 272119) +++ config/i386/i386-expand.c (working copy) @@ -1704,10 +1704,11 @@ void ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode, rtx operands[]) { - rtx mask, set, dst, src; + rtx set, dst, src; bool use_sse = false; bool vector_mode = VECTOR_MODE_P (mode); machine_mode vmode = mode; + rtvec par; if (vector_mode) use_sse = true; @@ -1722,13 +1723,6 @@ ix86_expand_fp_absneg_operator (enum rtx_code code vmode = V2DFmode; } - /* NEG and ABS performed with SSE use bitwise mask operations. - Create the appropriate mask now. */ - if (use_sse) - mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS); - else - mask = NULL_RTX; - dst = operands[0]; src = operands[1]; @@ -1735,11 +1729,13 @@ ix86_expand_fp_absneg_operator (enum rtx_code code set = gen_rtx_fmt_e (code, mode, src); set = gen_rtx_SET (dst, set); - if (mask) + if (use_sse) { - rtx use, clob; - rtvec par; + rtx mask, use, clob; + /* NEG and ABS performed with SSE use bitwise mask operations. + Create the appropriate mask now. */ + mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS); use = gen_rtx_USE (VOIDmode, mask); if (vector_mode) par = gen_rtvec (2, set, use); @@ -1748,12 +1744,106 @@ ix86_expand_fp_absneg_operator (enum rtx_code code clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); par = gen_rtvec (3, set, use, clob); } - emit_insn (gen_rtx_PARALLEL (VOIDmode, par)); } else - emit_insn (set); + { + rtx clob; + + /* Changing of sign for FP values is doable using integer unit too. */ + clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); + par = gen_rtvec (2, set, clob); + } + + emit_insn (gen_rtx_PARALLEL (VOIDmode, par)); } +/* Deconstruct a floating point ABS or NEG operation + with integer registers into integer operations. */ + +void +ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode, + rtx operands[]) +{ + enum rtx_code absneg_op; + rtx dst, set; + + gcc_assert (operands_match_p (operands[0], operands[1])); + + switch (mode) + { + case E_SFmode: + dst = gen_lowpart (SImode, operands[0]); + + if (code == ABS) + { + set = gen_int_mode (0x7fffffff, SImode); + absneg_op = AND; + } + else + { + set = gen_int_mode (0x80000000, SImode); + absneg_op = XOR; + } + set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set); + break; + + case E_DFmode: + if (TARGET_64BIT) + { + dst = gen_lowpart (DImode, operands[0]); + dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63)); + + if (code == ABS) + set = const0_rtx; + else + set = gen_rtx_NOT (DImode, dst); + } + else + { + dst = gen_highpart (SImode, operands[0]); + + if (code == ABS) + { + set = gen_int_mode (0x7fffffff, SImode); + absneg_op = AND; + } + else + { + set = gen_int_mode (0x80000000, SImode); + absneg_op = XOR; + } + set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set); + } + break; + + case E_XFmode: + dst = gen_rtx_REG (SImode, + REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2)); + if (code == ABS) + { + set = GEN_INT (0x7fff); + absneg_op = AND; + } + else + { + set = GEN_INT (0x8000); + absneg_op = XOR; + } + set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set); + break; + + default: + gcc_unreachable (); + } + + set = gen_rtx_SET (dst, set); + + rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); + rtvec par = gen_rtvec (2, set, clob); + + emit_insn (gen_rtx_PARALLEL (VOIDmode, par)); +} + /* Expand a copysign operation. Special case operand 0 being a constant. */ void Index: config/i386/i386-protos.h =================================================================== --- config/i386/i386-protos.h (revision 272119) +++ config/i386/i386-protos.h (working copy) @@ -121,6 +121,8 @@ extern rtx ix86_expand_adjust_ufix_to_sfix_si (rtx extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code); extern void ix86_expand_fp_absneg_operator (enum rtx_code, machine_mode, rtx[]); +extern void ix86_split_fp_absneg_operator (enum rtx_code, machine_mode, + rtx[]); extern void ix86_expand_copysign (rtx []); extern void ix86_split_copysign_const (rtx []); extern void ix86_split_copysign_var (rtx []); Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 272119) +++ config/i386/i386.md (working copy) @@ -1162,6 +1162,10 @@ ;; All x87 floating point modes (define_mode_iterator X87MODEF [SF DF XF]) +;; All SSE floating point modes +(define_mode_iterator SSEMODEF [SF DF TF]) +(define_mode_attr ssevecmodef [(SF "V4SF") (DF "V2DF") (TF "TF")]) + ;; SSE instruction suffix for various modes (define_mode_attr ssemodesuffix [(SF "ss") (DF "sd") @@ -9488,8 +9492,22 @@ [(set_attr "type" "negnot") (set_attr "mode" "")]) -;; Changing of sign for FP values is doable using integer unit too. +(define_expand "tf2" + [(set (match_operand:TF 0 "register_operand") + (absneg:TF (match_operand:TF 1 "register_operand")))] + "TARGET_SSE" + "ix86_expand_fp_absneg_operator (, TFmode, operands); DONE;") +(define_insn "*tf2_1" + [(set (match_operand:TF 0 "register_operand" "=x,x,Yv,Yv") + (absneg:TF + (match_operand:TF 1 "vector_operand" "0,xBm,Yv,m"))) + (use (match_operand:TF 2 "vector_operand" "xBm,0,Yvm,Yv")) + (clobber (reg:CC FLAGS_REG))] + "TARGET_SSE" + "#" + [(set_attr "isa" "noavx,noavx,avx,avx")]) + (define_expand "2" [(set (match_operand:X87MODEF 0 "register_operand") (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand")))] @@ -9496,180 +9514,108 @@ "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" "ix86_expand_fp_absneg_operator (, mode, operands); DONE;") -(define_insn "*absneg2" - [(set (match_operand:MODEF 0 "register_operand" "=Yv,Yv,f,!r") - (match_operator:MODEF 3 "absneg_operator" - [(match_operand:MODEF 1 "register_operand" "0,Yv,0,0")])) - (use (match_operand: 2 "nonimmediate_operand" "Yvm,0,X,X")) +;; Changing of sign for FP values is doable using integer unit too. +(define_insn "*2_i387_1" + [(set (match_operand:X87MODEF 0 "register_operand" "=f,!r") + (absneg:X87MODEF + (match_operand:X87MODEF 1 "register_operand" "0,0"))) (clobber (reg:CC FLAGS_REG))] + "TARGET_80387" + "#") + +(define_split + [(set (match_operand:X87MODEF 0 "fp_register_operand") + (absneg:X87MODEF (match_operand:X87MODEF 1 "fp_register_operand"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_80387 && reload_completed" + [(set (match_dup 0) (absneg:X87MODEF (match_dup 1)))]) + +(define_split + [(set (match_operand:X87MODEF 0 "general_reg_operand") + (absneg:X87MODEF (match_operand:X87MODEF 1 "general_reg_operand"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_80387 && reload_completed" + [(const_int 0)] + "ix86_split_fp_absneg_operator (, mode, operands); DONE;") + +(define_insn "*2_1" + [(set (match_operand:MODEF 0 "register_operand" "=x,x,Yv,f,!r") + (absneg:MODEF + (match_operand:MODEF 1 "register_operand" "0,x,Yv,0,0"))) + (use (match_operand: 2 "vector_operand" "xBm,0,Yvm,X,X")) + (clobber (reg:CC FLAGS_REG))] "TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" "#" - [(set (attr "enabled") + [(set_attr "isa" "noavx,noavx,avx,*,*") + (set (attr "enabled") (if_then_else (match_test ("SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH")) (if_then_else - (eq_attr "alternative" "2") + (eq_attr "alternative" "3,4") (symbol_ref "TARGET_MIX_SSE_I387") - (symbol_ref "true")) + (const_string "*")) (if_then_else - (eq_attr "alternative" "2,3") + (eq_attr "alternative" "3,4") (symbol_ref "true") (symbol_ref "false"))))]) -(define_insn "*absnegxf2_i387" - [(set (match_operand:XF 0 "register_operand" "=f,!r") - (match_operator:XF 3 "absneg_operator" - [(match_operand:XF 1 "register_operand" "0,0")])) - (use (match_operand 2)) - (clobber (reg:CC FLAGS_REG))] - "TARGET_80387" - "#") - -(define_expand "tf2" - [(set (match_operand:TF 0 "register_operand") - (absneg:TF (match_operand:TF 1 "register_operand")))] - "TARGET_SSE" - "ix86_expand_fp_absneg_operator (, TFmode, operands); DONE;") - -(define_insn "*absnegtf2_sse" - [(set (match_operand:TF 0 "register_operand" "=Yv,Yv") - (match_operator:TF 3 "absneg_operator" - [(match_operand:TF 1 "register_operand" "0,Yv")])) - (use (match_operand:TF 2 "nonimmediate_operand" "Yvm,0")) - (clobber (reg:CC FLAGS_REG))] - "TARGET_SSE" - "#") - -;; Splitters for fp abs and neg. - (define_split - [(set (match_operand 0 "fp_register_operand") - (match_operator 1 "absneg_operator" [(match_dup 0)])) - (use (match_operand 2)) + [(set (match_operand:SSEMODEF 0 "sse_reg_operand") + (absneg:SSEMODEF + (match_operand:SSEMODEF 1 "vector_operand"))) + (use (match_operand: 2 "vector_operand")) (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))]) - -(define_split - [(set (match_operand 0 "sse_reg_operand") - (match_operator 3 "absneg_operator" - [(match_operand 1 "register_operand")])) - (use (match_operand 2 "nonimmediate_operand")) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" + "((SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) + || (TARGET_SSE && (mode == TFmode))) + && reload_completed" [(set (match_dup 0) (match_dup 3))] { - machine_mode mode = GET_MODE (operands[0]); - machine_mode vmode = GET_MODE (operands[2]); - rtx tmp; + machine_mode mode = mode; + machine_mode vmode = mode; + enum rtx_code absneg_op = == ABS ? AND : XOR; operands[0] = lowpart_subreg (vmode, operands[0], mode); operands[1] = lowpart_subreg (vmode, operands[1], mode); - if (operands_match_p (operands[0], operands[2])) - std::swap (operands[1], operands[2]); - if (GET_CODE (operands[3]) == ABS) - tmp = gen_rtx_AND (vmode, operands[1], operands[2]); - else - tmp = gen_rtx_XOR (vmode, operands[1], operands[2]); - operands[3] = tmp; -}) -(define_split - [(set (match_operand:SF 0 "general_reg_operand") - (match_operator:SF 1 "absneg_operator" [(match_dup 0)])) - (use (match_operand:V4SF 2)) - (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(parallel [(set (match_dup 0) (match_dup 1)) - (clobber (reg:CC FLAGS_REG))])] -{ - rtx tmp; - operands[0] = gen_lowpart (SImode, operands[0]); - if (GET_CODE (operands[1]) == ABS) + if (TARGET_AVX) { - tmp = gen_int_mode (0x7fffffff, SImode); - tmp = gen_rtx_AND (SImode, operands[0], tmp); + if (MEM_P (operands[1])) + std::swap (operands[1], operands[2]); } else - { - tmp = gen_int_mode (0x80000000, SImode); - tmp = gen_rtx_XOR (SImode, operands[0], tmp); - } - operands[1] = tmp; + { + if (operands_match_p (operands[0], operands[2])) + std::swap (operands[1], operands[2]); + } + + operands[3] + = gen_rtx_fmt_ee (absneg_op, vmode, operands[1], operands[2]); }) (define_split - [(set (match_operand:DF 0 "general_reg_operand") - (match_operator:DF 1 "absneg_operator" [(match_dup 0)])) + [(set (match_operand:MODEF 0 "fp_register_operand") + (absneg:MODEF (match_operand:MODEF 1 "fp_register_operand"))) (use (match_operand 2)) (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(parallel [(set (match_dup 0) (match_dup 1)) - (clobber (reg:CC FLAGS_REG))])] -{ - rtx tmp; - if (TARGET_64BIT) - { - tmp = gen_lowpart (DImode, operands[0]); - tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63)); - operands[0] = tmp; + "TARGET_80387 && reload_completed" + [(set (match_dup 0) (absneg:X87MODEF (match_dup 1)))]) - if (GET_CODE (operands[1]) == ABS) - tmp = const0_rtx; - else - tmp = gen_rtx_NOT (DImode, tmp); - } - else - { - operands[0] = gen_highpart (SImode, operands[0]); - if (GET_CODE (operands[1]) == ABS) - { - tmp = gen_int_mode (0x7fffffff, SImode); - tmp = gen_rtx_AND (SImode, operands[0], tmp); - } - else - { - tmp = gen_int_mode (0x80000000, SImode); - tmp = gen_rtx_XOR (SImode, operands[0], tmp); - } - } - operands[1] = tmp; -}) - (define_split - [(set (match_operand:XF 0 "general_reg_operand") - (match_operator:XF 1 "absneg_operator" [(match_dup 0)])) + [(set (match_operand:MODEF 0 "general_reg_operand") + (absneg:MODEF (match_operand:MODEF 1 "general_reg_operand"))) (use (match_operand 2)) (clobber (reg:CC FLAGS_REG))] - "reload_completed" - [(parallel [(set (match_dup 0) (match_dup 1)) - (clobber (reg:CC FLAGS_REG))])] -{ - rtx tmp; - operands[0] = gen_rtx_REG (SImode, - REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2)); - if (GET_CODE (operands[1]) == ABS) - { - tmp = GEN_INT (0x7fff); - tmp = gen_rtx_AND (SImode, operands[0], tmp); - } - else - { - tmp = GEN_INT (0x8000); - tmp = gen_rtx_XOR (SImode, operands[0], tmp); - } - operands[1] = tmp; -}) + "TARGET_80387 && reload_completed" + [(const_int 0)] + "ix86_split_fp_absneg_operator (, mode, operands); DONE;") ;; Conditionalize these after reload. If they match before reload, we ;; lose the clobber and ability to use integer instructions. -(define_insn "*2_1" +(define_insn "*2_i387" [(set (match_operand:X87MODEF 0 "register_operand" "=f") (absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))] - "TARGET_80387 - && (reload_completed - || !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH))" + "TARGET_80387 && reload_completed" "" [(set_attr "type" "fsgn") (set_attr "mode" "")]) @@ -9676,23 +9622,20 @@ ;; Copysign instructions -(define_mode_iterator CSGNMODE [SF DF TF]) -(define_mode_attr CSGNVMODE [(SF "V4SF") (DF "V2DF") (TF "TF")]) - (define_expand "copysign3" - [(match_operand:CSGNMODE 0 "register_operand") - (match_operand:CSGNMODE 1 "nonmemory_operand") - (match_operand:CSGNMODE 2 "register_operand")] + [(match_operand:SSEMODEF 0 "register_operand") + (match_operand:SSEMODEF 1 "nonmemory_operand") + (match_operand:SSEMODEF 2 "register_operand")] "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) || (TARGET_SSE && (mode == TFmode))" "ix86_expand_copysign (operands); DONE;") (define_insn_and_split "copysign3_const" - [(set (match_operand:CSGNMODE 0 "register_operand" "=Yv") - (unspec:CSGNMODE - [(match_operand: 1 "nonimm_or_0_operand" "YvmC") - (match_operand:CSGNMODE 2 "register_operand" "0") - (match_operand: 3 "nonimmediate_operand" "Yvm")] + [(set (match_operand:SSEMODEF 0 "register_operand" "=Yv") + (unspec:SSEMODEF + [(match_operand: 1 "nonimm_or_0_operand" "YvmC") + (match_operand:SSEMODEF 2 "register_operand" "0") + (match_operand: 3 "nonimmediate_operand" "Yvm")] UNSPEC_COPYSIGN))] "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) || (TARGET_SSE && (mode == TFmode))" @@ -9702,29 +9645,29 @@ "ix86_split_copysign_const (operands); DONE;") (define_insn "copysign3_var" - [(set (match_operand:CSGNMODE 0 "register_operand" "=Yv,Yv,Yv,Yv,Yv") - (unspec:CSGNMODE - [(match_operand:CSGNMODE 2 "register_operand" "Yv,0,0,Yv,Yv") - (match_operand:CSGNMODE 3 "register_operand" "1,1,Yv,1,Yv") - (match_operand: 4 + [(set (match_operand:SSEMODEF 0 "register_operand" "=Yv,Yv,Yv,Yv,Yv") + (unspec:SSEMODEF + [(match_operand:SSEMODEF 2 "register_operand" "Yv,0,0,Yv,Yv") + (match_operand:SSEMODEF 3 "register_operand" "1,1,Yv,1,Yv") + (match_operand: 4 "nonimmediate_operand" "X,Yvm,Yvm,0,0") - (match_operand: 5 + (match_operand: 5 "nonimmediate_operand" "0,Yvm,1,Yvm,1")] UNSPEC_COPYSIGN)) - (clobber (match_scratch: 1 "=Yv,Yv,Yv,Yv,Yv"))] + (clobber (match_scratch: 1 "=Yv,Yv,Yv,Yv,Yv"))] "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) || (TARGET_SSE && (mode == TFmode))" "#") (define_split - [(set (match_operand:CSGNMODE 0 "register_operand") - (unspec:CSGNMODE - [(match_operand:CSGNMODE 2 "register_operand") - (match_operand:CSGNMODE 3 "register_operand") - (match_operand: 4) - (match_operand: 5)] + [(set (match_operand:SSEMODEF 0 "register_operand") + (unspec:SSEMODEF + [(match_operand:SSEMODEF 2 "register_operand") + (match_operand:SSEMODEF 3 "register_operand") + (match_operand: 4) + (match_operand: 5)] UNSPEC_COPYSIGN)) - (clobber (match_scratch: 1))] + (clobber (match_scratch: 1))] "((SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) || (TARGET_SSE && (mode == TFmode))) && reload_completed" Index: config/i386/predicates.md =================================================================== --- config/i386/predicates.md (revision 272119) +++ config/i386/predicates.md (working copy) @@ -1404,9 +1404,6 @@ (define_predicate "compare_operator" (match_code "compare")) -(define_predicate "absneg_operator" - (match_code "abs,neg")) - ;; Return true if OP is a memory operand, aligned to ;; less than its natural alignment. (define_predicate "misaligned_operand" Index: config/i386/sse.md =================================================================== --- config/i386/sse.md (revision 272119) +++ config/i386/sse.md (working copy) @@ -1720,41 +1720,31 @@ "TARGET_SSE" "ix86_expand_fp_absneg_operator (, mode, operands); DONE;") -(define_insn_and_split "*absneg2" +(define_insn_and_split "*2" [(set (match_operand:VF 0 "register_operand" "=x,x,v,v") - (match_operator:VF 3 "absneg_operator" - [(match_operand:VF 1 "vector_operand" "0, xBm,v, m")])) + (absneg:VF + (match_operand:VF 1 "vector_operand" "0, xBm,v, m"))) (use (match_operand:VF 2 "vector_operand" "xBm,0, vm,v"))] "TARGET_SSE" "#" "&& reload_completed" - [(const_int 0)] + [(set (match_dup 0) (match_dup 3))] { - enum rtx_code absneg_op; - rtx op1, op2; - rtx t; + enum rtx_code absneg_op = == ABS ? AND : XOR; if (TARGET_AVX) { if (MEM_P (operands[1])) - op1 = operands[2], op2 = operands[1]; - else - op1 = operands[1], op2 = operands[2]; + std::swap (operands[1], operands[2]); } else - { - op1 = operands[0]; - if (rtx_equal_p (operands[0], operands[1])) - op2 = operands[2]; - else - op2 = operands[1]; - } + { + if (operands_match_p (operands[0], operands[2])) + std::swap (operands[1], operands[2]); + } - absneg_op = GET_CODE (operands[3]) == NEG ? XOR : AND; - t = gen_rtx_fmt_ee (absneg_op, mode, op1, op2); - t = gen_rtx_SET (operands[0], t); - emit_insn (t); - DONE; + operands[3] + = gen_rtx_fmt_ee (absneg_op, mode, operands[1], operands[2]); } [(set_attr "isa" "noavx,noavx,avx,avx")])