| From 0061fabeb9393c362601486105202cfe837a5a68 Mon Sep 17 00:00:00 2001 |
| From: Claudiu Zissulescu <claziss@synopsys.com> |
| Date: Wed, 9 Jun 2021 12:12:57 +0300 |
| Subject: [PATCH] arc: Update 64bit move split patterns. |
| |
| ARCv2HS can use a limited number of instructions to implement 64bit |
| moves. The VADD2 is used as a 64bit move, the LDD/STD are 64 bit loads |
| and stores. All those instructions are not baseline, hence we need to |
| provide alternatives when they are not available or cannot be generate |
| due to instruction restriction. |
| |
| This patch is cleaning up those move patterns, and updates splits |
| instruction lengths. |
| |
| This is a backport from mainline gcc. |
| |
| gcc/ |
| 2021-06-09 Claudiu Zissulescu <claziss@synopsys.com> |
| |
| * config/arc/arc-protos.h (arc_split_move_p): New prototype. |
| * config/arc/arc.c (arc_split_move_p): New function. |
| (arc_split_move): Clean up. |
| * config/arc/arc.md (movdi_insn): Clean up, use arc_split_move_p. |
| (movdf_insn): Likewise. |
| * config/arc/simdext.md (mov<VWH>_insn): Likewise. |
| |
| Upstream-Status: Backport [https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0061fabeb9393c362601486105202cfe837a5a68] |
| |
| Signed-off-by: Claudiu Zissulescu <claziss@synopsys.com> |
| (cherry picked from commit c0ba7a8af5366c37241f20e8be41e362f7260389) |
| Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com> |
| --- |
| gcc/config/arc/arc-protos.h | 1 + |
| gcc/config/arc/arc.c | 44 ++++++++++++---------- |
| gcc/config/arc/arc.md | 91 +++++++++------------------------------------ |
| gcc/config/arc/simdext.md | 38 ++++--------------- |
| 4 files changed, 52 insertions(+), 122 deletions(-) |
| |
| diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h |
| index 1f56a0d82e4..62d7e45d29d 100644 |
| --- a/gcc/config/arc/arc-protos.h |
| +++ b/gcc/config/arc/arc-protos.h |
| @@ -50,6 +50,7 @@ extern void arc_split_ior (rtx *); |
| extern bool arc_check_mov_const (HOST_WIDE_INT ); |
| extern bool arc_split_mov_const (rtx *); |
| extern bool arc_can_use_return_insn (void); |
| +extern bool arc_split_move_p (rtx *); |
| #endif /* RTX_CODE */ |
| |
| extern bool arc_ccfsm_branch_deleted_p (void); |
| diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c |
| index 3201c3fefd7..db541bc11f5 100644 |
| --- a/gcc/config/arc/arc.c |
| +++ b/gcc/config/arc/arc.c |
| @@ -10129,6 +10129,31 @@ arc_process_double_reg_moves (rtx *operands) |
| return true; |
| } |
| |
| + |
| +/* Check if we need to split a 64bit move. We do not need to split it if we can |
| + use vadd2 or ldd/std instructions. */ |
| + |
| +bool |
| +arc_split_move_p (rtx *operands) |
| +{ |
| + machine_mode mode = GET_MODE (operands[0]); |
| + |
| + if (TARGET_LL64 |
| + && ((memory_operand (operands[0], mode) |
| + && (even_register_operand (operands[1], mode) |
| + || satisfies_constraint_Cm3 (operands[1]))) |
| + || (memory_operand (operands[1], mode) |
| + && even_register_operand (operands[0], mode)))) |
| + return false; |
| + |
| + if (TARGET_PLUS_QMACW |
| + && even_register_operand (operands[0], mode) |
| + && even_register_operand (operands[1], mode)) |
| + return false; |
| + |
| + return true; |
| +} |
| + |
| /* operands 0..1 are the operands of a 64 bit move instruction. |
| split it into two moves with operands 2/3 and 4/5. */ |
| |
| @@ -10146,25 +10171,6 @@ arc_split_move (rtx *operands) |
| return; |
| } |
| |
| - if (TARGET_LL64 |
| - && ((memory_operand (operands[0], mode) |
| - && (even_register_operand (operands[1], mode) |
| - || satisfies_constraint_Cm3 (operands[1]))) |
| - || (memory_operand (operands[1], mode) |
| - && even_register_operand (operands[0], mode)))) |
| - { |
| - emit_move_insn (operands[0], operands[1]); |
| - return; |
| - } |
| - |
| - if (TARGET_PLUS_QMACW |
| - && even_register_operand (operands[0], mode) |
| - && even_register_operand (operands[1], mode)) |
| - { |
| - emit_move_insn (operands[0], operands[1]); |
| - return; |
| - } |
| - |
| if (TARGET_PLUS_QMACW |
| && GET_CODE (operands[1]) == CONST_VECTOR) |
| { |
| diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md |
| index 7a52551eef5..91a838a38e4 100644 |
| --- a/gcc/config/arc/arc.md |
| +++ b/gcc/config/arc/arc.md |
| @@ -1329,47 +1329,20 @@ core_3, archs4x, archs4xd, archs4xd_slow" |
| "register_operand (operands[0], DImode) |
| || register_operand (operands[1], DImode) |
| || (satisfies_constraint_Cm3 (operands[1]) |
| - && memory_operand (operands[0], DImode))" |
| - "* |
| -{ |
| - switch (which_alternative) |
| - { |
| - default: |
| - return \"#\"; |
| - |
| - case 0: |
| - if (TARGET_PLUS_QMACW |
| - && even_register_operand (operands[0], DImode) |
| - && even_register_operand (operands[1], DImode)) |
| - return \"vadd2%?\\t%0,%1,0\"; |
| - return \"#\"; |
| - |
| - case 2: |
| - if (TARGET_LL64 |
| - && memory_operand (operands[1], DImode) |
| - && even_register_operand (operands[0], DImode)) |
| - return \"ldd%U1%V1 %0,%1%&\"; |
| - return \"#\"; |
| - |
| - case 3: |
| - if (TARGET_LL64 |
| - && memory_operand (operands[0], DImode) |
| - && (even_register_operand (operands[1], DImode) |
| - || satisfies_constraint_Cm3 (operands[1]))) |
| - return \"std%U0%V0 %1,%0\"; |
| - return \"#\"; |
| - } |
| -}" |
| - "&& reload_completed" |
| + && memory_operand (operands[0], DImode))" |
| + "@ |
| + vadd2\\t%0,%1,0 |
| + # |
| + ldd%U1%V1\\t%0,%1 |
| + std%U0%V0\\t%1,%0" |
| + "&& reload_completed && arc_split_move_p (operands)" |
| [(const_int 0)] |
| { |
| arc_split_move (operands); |
| DONE; |
| } |
| [(set_attr "type" "move,move,load,store") |
| - ;; ??? The ld/st values could be 4 if it's [reg,bignum]. |
| - (set_attr "length" "8,16,*,*")]) |
| - |
| + (set_attr "length" "8,16,16,16")]) |
| |
| ;; Floating point move insns. |
| |
| @@ -1408,50 +1381,22 @@ core_3, archs4x, archs4xd, archs4xd_slow" |
| (define_insn_and_split "*movdf_insn" |
| [(set (match_operand:DF 0 "move_dest_operand" "=D,r,r,r,r,m") |
| (match_operand:DF 1 "move_double_src_operand" "r,D,r,E,m,r"))] |
| - "register_operand (operands[0], DFmode) |
| - || register_operand (operands[1], DFmode)" |
| - "* |
| -{ |
| - switch (which_alternative) |
| - { |
| - default: |
| - return \"#\"; |
| - |
| - case 2: |
| - if (TARGET_PLUS_QMACW |
| - && even_register_operand (operands[0], DFmode) |
| - && even_register_operand (operands[1], DFmode)) |
| - return \"vadd2%?\\t%0,%1,0\"; |
| - return \"#\"; |
| - |
| - case 4: |
| - if (TARGET_LL64 |
| - && ((even_register_operand (operands[0], DFmode) |
| - && memory_operand (operands[1], DFmode)) |
| - || (memory_operand (operands[0], DFmode) |
| - && even_register_operand (operands[1], DFmode)))) |
| - return \"ldd%U1%V1 %0,%1%&\"; |
| - return \"#\"; |
| - |
| - case 5: |
| - if (TARGET_LL64 |
| - && ((even_register_operand (operands[0], DFmode) |
| - && memory_operand (operands[1], DFmode)) |
| - || (memory_operand (operands[0], DFmode) |
| - && even_register_operand (operands[1], DFmode)))) |
| - return \"std%U0%V0 %1,%0\"; |
| - return \"#\"; |
| - } |
| -}" |
| - "reload_completed" |
| + "(register_operand (operands[0], DFmode) |
| + || register_operand (operands[1], DFmode))" |
| + "@ |
| + # |
| + # |
| + vadd2\\t%0,%1,0 |
| + # |
| + ldd%U1%V1\\t%0,%1 |
| + std%U0%V0\\t%1,%0" |
| + "&& reload_completed && arc_split_move_p (operands)" |
| [(const_int 0)] |
| { |
| arc_split_move (operands); |
| DONE; |
| } |
| [(set_attr "type" "move,move,move,move,load,store") |
| - (set_attr "predicable" "no,no,no,yes,no,no") |
| - ;; ??? The ld/st values could be 16 if it's [reg,bignum]. |
| (set_attr "length" "4,16,8,16,16,16")]) |
| |
| (define_insn_and_split "*movdf_insn_nolrsr" |
| diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md |
| index f0900757452..36f41a5c3d0 100644 |
| --- a/gcc/config/arc/simdext.md |
| +++ b/gcc/config/arc/simdext.md |
| @@ -1402,41 +1402,19 @@ |
| (match_operand:VWH 1 "general_operand" "i,r,m,r"))] |
| "(register_operand (operands[0], <MODE>mode) |
| || register_operand (operands[1], <MODE>mode))" |
| - "* |
| -{ |
| - switch (which_alternative) |
| - { |
| - default: |
| - return \"#\"; |
| - |
| - case 1: |
| - if (TARGET_PLUS_QMACW |
| - && even_register_operand (operands[0], <MODE>mode) |
| - && even_register_operand (operands[1], <MODE>mode)) |
| - return \"vadd2%?\\t%0,%1,0\"; |
| - return \"#\"; |
| - |
| - case 2: |
| - if (TARGET_LL64) |
| - return \"ldd%U1%V1 %0,%1\"; |
| - return \"#\"; |
| - |
| - case 3: |
| - if (TARGET_LL64) |
| - return \"std%U0%V0 %1,%0\"; |
| - return \"#\"; |
| - } |
| -}" |
| - "reload_completed" |
| + "@ |
| + # |
| + vadd2\\t%0,%1,0 |
| + ldd%U1%V1\\t%0,%1 |
| + std%U0%V0\\t%1,%0" |
| + "&& reload_completed && arc_split_move_p (operands)" |
| [(const_int 0)] |
| { |
| arc_split_move (operands); |
| DONE; |
| } |
| - [(set_attr "type" "move,multi,load,store") |
| - (set_attr "predicable" "no,no,no,no") |
| - (set_attr "iscompact" "false,false,false,false") |
| - ]) |
| + [(set_attr "type" "move,move,load,store") |
| + (set_attr "length" "16,8,16,16")]) |
| |
| (define_expand "movmisalign<mode>" |
| [(set (match_operand:VWH 0 "general_operand" "") |
| -- |
| 2.16.2 |
| |