diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2020-05-15 16:22:19 +0200 |
---|---|---|
committer | Uros Bizjak <ubizjak@gmail.com> | 2020-05-15 16:22:19 +0200 |
commit | 75514d157e9e28616c6de4e8c2740d8c87b6857d (patch) | |
tree | dffa5eba21b2aa7cffd7806657ff33b6fc3e8a81 | |
parent | 271e3da859f92e32e0f3a8779fb6ac0c2a7909c4 (diff) | |
download | gcc-75514d157e9e28616c6de4e8c2740d8c87b6857d.zip gcc-75514d157e9e28616c6de4e8c2740d8c87b6857d.tar.gz gcc-75514d157e9e28616c6de4e8c2740d8c87b6857d.tar.bz2 |
i386: Allow SI, DI and TImode pushes from XMM registers
Also change XMM register constraint from "x" to "v" in FP push insns.
gcc/ChangeLog:
2020-05-15 Uroš Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (SWI48DWI): New mode iterator.
(*push<mode>2): 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.
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 75 |
2 files changed, 62 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5eaa1b8..d44ad8b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2020-05-15 Uroš Bizjak <ubizjak@gmail.com> + + * config/i386/i386.md (SWI48DWI): New mode iterator. + (*push<mode>2): 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 <rguenther@suse.de> PR tree-optimization/92260 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b555c16..1bf0c1a 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 <MODE_SIZE> than ;; GET_MODE_SIZE (<MODE>mode). For XFmode which depends on @@ -1672,8 +1675,8 @@ ;; Push/pop instructions. (define_insn "*push<mode>2" - [(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 (<SWI48DWI:MODE>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 "*push<mode>2_rex64" - [(set (match_operand:SWI124 0 "push_operand" "=X") - (match_operand:SWI124 1 "nonmemory_no_elim_operand" "r<i>"))] - "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 "*push<mode>2" [(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 "*push<mode>2_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. */ |