From 75514d157e9e28616c6de4e8c2740d8c87b6857d Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Fri, 15 May 2020 16:22:19 +0200 Subject: [PATCH] i386: Allow SI, DI and TImode pushes from XMM registers MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Also change XMM register constraint from "x" to "v" in FP push insns. gcc/ChangeLog: 2020-05-15 Uroš Bizjak * config/i386/i386.md (SWI48DWI): New mode iterator. (*push2): Allow XMM registers. (*pushdi2_rex64): Ditto. (*pushsi2_rex64): Ditto. (*pushsi2): Ditto. (push XMM reg splitter): New splitter (*pushdf) Change "x" operand constraint to "v". (*pushsf_rex64): Ditto. (*pushsf): Ditto. --- gcc/ChangeLog | 13 +++++++ gcc/config/i386/i386.md | 75 +++++++++++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5eaa1b8af27..d44ad8be801 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2020-05-15 Uroš Bizjak + + * config/i386/i386.md (SWI48DWI): New mode iterator. + (*push2): Allow XMM registers. + (*pushdi2_rex64): Ditto. + (*pushsi2_rex64): Ditto. + (*pushsi2): Ditto. + (push XMM reg splitter): New splitter + + (*pushdf) Change "x" operand constraint to "v". + (*pushsf_rex64): Ditto. + (*pushsf): Ditto. + 2020-05-15 Richard Biener PR tree-optimization/92260 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b555c165647..1bf0c1a7f01 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1051,6 +1051,9 @@ ;; SWI and DWI together. (define_mode_iterator SWIDWI [QI HI SI DI (TI "TARGET_64BIT")]) +;; SWI48 and DWI together. +(define_mode_iterator SWI48DWI [SI DI (TI "TARGET_64BIT")]) + ;; GET_MODE_SIZE for selected modes. As GET_MODE_SIZE is not ;; compile time constant, it is faster to use than ;; GET_MODE_SIZE (mode). For XFmode which depends on @@ -1672,8 +1675,8 @@ ;; Push/pop instructions. (define_insn "*push2" - [(set (match_operand:DWI 0 "push_operand" "=<") - (match_operand:DWI 1 "general_no_elim_operand" "riF*o"))] + [(set (match_operand:DWI 0 "push_operand" "=<,<") + (match_operand:DWI 1 "general_no_elim_operand" "riF*o,*v"))] "" "#" [(set_attr "type" "multi") @@ -1687,13 +1690,14 @@ "ix86_split_long_move (operands); DONE;") (define_insn "*pushdi2_rex64" - [(set (match_operand:DI 0 "push_operand" "=<,!<") - (match_operand:DI 1 "general_no_elim_operand" "re*m,n"))] + [(set (match_operand:DI 0 "push_operand" "=<,<,!<") + (match_operand:DI 1 "general_no_elim_operand" "re*m,*v,n"))] "TARGET_64BIT" "@ push{q}\t%1 + # #" - [(set_attr "type" "push,multi") + [(set_attr "type" "push,multi,multi") (set_attr "mode" "DI")]) ;; Convert impossible pushes of immediate to existing instructions. @@ -1727,34 +1731,53 @@ plus_constant (Pmode, stack_pointer_rtx, 4)); }) +;; For TARGET_64BIT we always round up to 8 bytes. +(define_insn "*pushsi2_rex64" + [(set (match_operand:SI 0 "push_operand" "=X,X") + (match_operand:SI 1 "nonmemory_no_elim_operand" "ri,*v"))] + "TARGET_64BIT" + "@ + push{q}\t%q1 + #" + [(set_attr "type" "push,multi") + (set_attr "mode" "DI")]) + (define_insn "*pushsi2" - [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "general_no_elim_operand" "ri*m"))] + [(set (match_operand:SI 0 "push_operand" "=<,<") + (match_operand:SI 1 "general_no_elim_operand" "ri*m,*v"))] "!TARGET_64BIT" - "push{l}\t%1" - [(set_attr "type" "push") + "@ + push{l}\t%1 + #" + [(set_attr "type" "push,multi") (set_attr "mode" "SI")]) -;; emit_push_insn when it calls move_by_pieces requires an insn to -;; "push a byte/word". But actually we use pushl, which has the effect -;; of rounding the amount pushed up to a word. +(define_split + [(set (match_operand:SWI48DWI 0 "push_operand") + (match_operand:SWI48DWI 1 "sse_reg_operand"))] + "TARGET_SSE && reload_completed" + [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (match_dup 2))) + (set (match_dup 0) (match_dup 1))] +{ + operands[2] = GEN_INT (-PUSH_ROUNDING (GET_MODE_SIZE (mode))); + /* Preserve memory attributes. */ + operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx); +}) -;; For TARGET_64BIT we always round up to 8 bytes. -(define_insn "*push2_rex64" - [(set (match_operand:SWI124 0 "push_operand" "=X") - (match_operand:SWI124 1 "nonmemory_no_elim_operand" "r"))] - "TARGET_64BIT" - "push{q}\t%q1" - [(set_attr "type" "push") - (set_attr "mode" "DI")]) +;; emit_push_insn when it calls move_by_pieces requires an insn to +;; "push a byte/word". But actually we use push{l,q}, which has +;; the effect of rounding the amount pushed up to a word. (define_insn "*push2" [(set (match_operand:SWI12 0 "push_operand" "=X") (match_operand:SWI12 1 "nonmemory_no_elim_operand" "rn"))] - "!TARGET_64BIT" - "push{l}\t%k1" + "" + "* return TARGET_64BIT ? \"push{q}\t%q1\" : \"push{l}\t%k1\";" [(set_attr "type" "push") - (set_attr "mode" "SI")]) + (set (attr "mode") + (if_then_else (match_test "TARGET_64BIT") + (const_string "DI") + (const_string "SI")))]) (define_insn "*push2_prologue" [(set (match_operand:W 0 "push_operand" "=<") @@ -3031,7 +3054,7 @@ (define_insn "*pushdf" [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f,r,*r,oF,rmC,x"))] + (match_operand:DF 1 "general_no_elim_operand" "f,r,*r,oF,rmC,v"))] "" { /* This insn should be already split before reg-stack. */ @@ -3064,7 +3087,7 @@ (define_insn "*pushsf_rex64" [(set (match_operand:SF 0 "push_operand" "=X,X,X") - (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))] + (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,v"))] "TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ @@ -3078,7 +3101,7 @@ (define_insn "*pushsf" [(set (match_operand:SF 0 "push_operand" "=<,<,<") - (match_operand:SF 1 "general_no_elim_operand" "f,rmF,x"))] + (match_operand:SF 1 "general_no_elim_operand" "f,rmF,v"))] "!TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ -- 2.30.2