[gcc r14-9480] gcc: xtensa: reorder movsi_internal patterns for better code generation during LRA
https://gcc.gnu.org/g:bc5a9dab55d13f888a3cdd150c8cf5c2244f35e0 commit r14-9480-gbc5a9dab55d13f888a3cdd150c8cf5c2244f35e0 Author: Max Filippov Date: Thu Mar 14 04:20:36 2024 -0700 gcc: xtensa: reorder movsi_internal patterns for better code generation during LRA After switching to LRA xtensa backend generates the following code for saving/loading registers: movi a9, 0x190 add a9, a9, sp s32i.n a3, a9, 0 instead of the shorter and more efficient s32i a3, a9, 0x190 E.g. the following code can be used to reproduce it: int f1(int a, int b, int c, int d, int e, int f, int *p); int f2(int a, int b, int c, int d, int e, int f, int *p); int f3(int a, int b, int c, int d, int e, int f, int *p); int foo(int a, int b, int c, int d, int e, int f) { int g[100]; return f1(a, b, c, d, e, f, g) + f2(a, b, c, d, e, f, g) + f3(a, b, c, d, e, f, g); } This happens in the LRA pass because s32i.n and l32i.n are listed before the s32i and l32i in the movsi_internal pattern and alternative consideration loop stops early. gcc/ * config/xtensa/xtensa.md (movsi_internal): Move l32i and s32i patterns ahead of the l32i.n and s32i.n. Diff: --- gcc/config/xtensa/xtensa.md | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 1a2249b059a..5cdf4dffe70 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1270,13 +1270,15 @@ }) (define_insn "movsi_internal" - [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,D,R,R,a,q,a,a,W,a,a,U,*a,*A") - (match_operand:SI 1 "move_operand" "M,D,d,R,D,d,r,r,I,Y,i,T,U,r,*A,*r"))] + [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,a,U,D,R,R,a,q,a,a,W,a,*a,*A") + (match_operand:SI 1 "move_operand" "M,D,d,U,r,R,D,d,r,r,I,Y,i,T,*A,*r"))] "xtensa_valid_move (SImode, operands)" "@ movi.n\t%0, %x1 mov.n\t%0, %1 mov.n\t%0, %1 + %v1l32i\t%0, %1 + %v0s32i\t%1, %0 %v1l32i.n\t%0, %1 %v0s32i.n\t%1, %0 %v0s32i.n\t%1, %0 @@ -1286,13 +1288,11 @@ movi\t%0, %1 const16\t%0, %t1\;const16\t%0, %b1 %v1l32r\t%0, %1 - %v1l32i\t%0, %1 - %v0s32i\t%1, %0 rsr\t%0, ACCLO wsr\t%1, ACCLO" - [(set_attr "type" "move,move,move,load,store,store,move,move,move,move,move,load,load,store,rsr,wsr") + [(set_attr "type" "move,move,move,load,store,load,store,store,move,move,move,move,move,load,rsr,wsr") (set_attr "mode""SI") - (set_attr "length" "2,2,2,2,2,2,3,3,3,3,6,3,3,3,3,3")]) + (set_attr "length" "2,2,2,3,3,2,2,2,3,3,3,3,6,3,3,3")]) (define_split [(set (match_operand:SHI 0 "register_operand")
[gcc r14-9638] xtensa: Add supplementary split pattern for "*addsubx"
https://gcc.gnu.org/g:7a01cc711f33530436712a5bfd18f8457a68ea1f commit r14-9638-g7a01cc711f33530436712a5bfd18f8457a68ea1f Author: Takayuki 'January June' Suwa Date: Fri Mar 22 08:36:30 2024 +0900 xtensa: Add supplementary split pattern for "*addsubx" int test(int a) { return a * 4 + 3; } In the example above, since Xtensa has instructions to add register value scaled by 2, 4 or 8 (and corresponding define_insns), we would expect them to be used but not, because it is transformed before reaching the RTL generation pass as below: int test(int a) { return (a + 7500) * 4; } Fortunately, the RTL combination pass tries a splitting pattern that matches the first example, so it is easy to solve by defining that pattern. gcc/ChangeLog: * config/xtensa/xtensa.md: Add new split pattern described above. Diff: --- gcc/config/xtensa/xtensa.md | 14 ++ 1 file changed, 14 insertions(+) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 5cdf4dffe70..fbe40ec671a 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -194,6 +194,20 @@ (set_attr "mode""SI") (set_attr "length" "3")]) +(define_split + [(set (match_operand:SI 0 "register_operand") + (plus:SI (ashift:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 3 "addsubx_operand")) +(match_operand:SI 2 "const_int_operand")))] + "TARGET_ADDX && can_create_pseudo_p ()" + [(set (match_dup 0) + (plus:SI (ashift:SI (match_dup 1) + (match_dup 3)) +(match_dup 2)))] +{ + operands[2] = force_reg (SImode, operands[2]); +}) + (define_expand "adddi3" [(set (match_operand:DI 0 "register_operand") (plus:DI (match_operand:DI 1 "register_operand")
[gcc r14-9655] libgcc: arm: fix build for FDPIC target
https://gcc.gnu.org/g:c2e68ff9edd5da7a55ba6574b4ce49ce6495b18d commit r14-9655-gc2e68ff9edd5da7a55ba6574b4ce49ce6495b18d Author: Max Filippov Date: Fri Mar 22 13:03:46 2024 -0700 libgcc: arm: fix build for FDPIC target libgcc/ * unwind-arm-common.inc (__gnu_personality_sigframe_fdpic): Cast last argument of _Unwind_VRS_Set to void *. Diff: --- libgcc/unwind-arm-common.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgcc/unwind-arm-common.inc b/libgcc/unwind-arm-common.inc index 5453f38186b..576f7e93e8a 100644 --- a/libgcc/unwind-arm-common.inc +++ b/libgcc/unwind-arm-common.inc @@ -248,7 +248,7 @@ __gnu_personality_sigframe_fdpic (_Unwind_State state, + ARM_SIGCONTEXT_R0; /* Restore regs saved on stack by the kernel. */ for (i = 0; i < 16; i++) - _Unwind_VRS_Set (context, _UVRSC_CORE, i, _UVRSD_UINT32, sp + 4 * i); + _Unwind_VRS_Set (context, _UVRSC_CORE, i, _UVRSD_UINT32, (void *)(sp + 4 * i)); return _URC_CONTINUE_UNWIND; }
[gcc r15-2385] gcc: xtensa: disable late-combine by default
https://gcc.gnu.org/g:9d5d6e61500411ea9043258e300d5b0f57e5c391 commit r15-2385-g9d5d6e61500411ea9043258e300d5b0f57e5c391 Author: Max Filippov Date: Fri Jul 19 17:27:03 2024 -0700 gcc: xtensa: disable late-combine by default gcc/ * config/xtensa/xtensa.cc (xtensa_option_override_after_change): New function. (TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE): Define as xtensa_option_override_after_change. (xtensa_option_override): Call xtensa_option_override_after_change. Diff: --- gcc/config/xtensa/xtensa.cc | 13 + 1 file changed, 13 insertions(+) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index d49d224466ad..10d964b51a96 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -114,6 +114,7 @@ struct GTY(()) machine_function }; static void xtensa_option_override (void); +static void xtensa_option_override_after_change (void); static enum internal_test map_test_to_internal_test (enum rtx_code); static rtx gen_int_relational (enum rtx_code, rtx, rtx); static rtx gen_float_relational (enum rtx_code, rtx, rtx); @@ -303,6 +304,9 @@ static rtx xtensa_delegitimize_address (rtx); #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE xtensa_option_override +#undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE +#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE xtensa_option_override_after_change + #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA xtensa_output_addr_const_extra @@ -2988,6 +2992,15 @@ xtensa_option_override (void) the define_insn_and_splits are fixed. */ if (!OPTION_SET_P (flag_late_combine_instructions)) flag_late_combine_instructions = 0; + + xtensa_option_override_after_change (); +} + +static void +xtensa_option_override_after_change (void) +{ + if (!OPTION_SET_P (flag_late_combine_instructions)) +flag_late_combine_instructions = 0; } /* Implement TARGET_HARD_REGNO_NREGS. */
[gcc r15-2391] xtensa: Make use of std::swap where appropriate
https://gcc.gnu.org/g:56c4979dd8be40681f2724861fc41ae6135e1e78 commit r15-2391-g56c4979dd8be40681f2724861fc41ae6135e1e78 Author: Takayuki 'January June' Suwa Date: Sun Jul 14 20:03:13 2024 +0900 xtensa: Make use of std::swap where appropriate No functional changes. gcc/ChangeLog: * config/xtensa/xtensa.cc (gen_int_relational, gen_float_relational): Replace tempvar-based value-swapping codes with std::swap. * config/xtensa/xtensa.md (movdi_internal, movdf_internal): Ditto. Diff: --- gcc/config/xtensa/xtensa.cc | 12 ++-- gcc/config/xtensa/xtensa.md | 10 -- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 10d964b51a96..772150c7fa22 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -794,11 +794,7 @@ gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */ } else if (p_info->reverse_regs) -{ - rtx temp = cmp0; - cmp0 = cmp1; - cmp1 = temp; -} +std::swap (cmp0, cmp1); return gen_rtx_fmt_ee (invert ? reverse_condition (p_info->test_code) : p_info->test_code, @@ -842,11 +838,7 @@ gen_float_relational (enum rtx_code test_code, /* relational test (EQ, etc) */ } if (reverse_regs) -{ - rtx temp = cmp0; - cmp0 = cmp1; - cmp1 = temp; -} +std::swap (cmp0, cmp1); brtmp = gen_rtx_REG (CCmode, FPCC_REGNUM); emit_insn (gen_fn (brtmp, cmp0, cmp1)); diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 8709ef6d7a7d..0fcbb0b7bc37 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1215,9 +1215,8 @@ xtensa_split_operand_pair (operands, SImode); if (reg_overlap_mentioned_p (operands[0], operands[3])) { - rtx tmp; - tmp = operands[0], operands[0] = operands[1], operands[1] = tmp; - tmp = operands[2], operands[2] = operands[3], operands[3] = tmp; + std::swap (operands[0], operands[1]); + std::swap (operands[2], operands[3]); } }) @@ -1562,9 +1561,8 @@ xtensa_split_operand_pair (operands, SFmode); if (reg_overlap_mentioned_p (operands[0], operands[3])) { - rtx tmp; - tmp = operands[0], operands[0] = operands[1], operands[1] = tmp; - tmp = operands[2], operands[2] = operands[3], operands[3] = tmp; + std::swap (operands[0], operands[1]); + std::swap (operands[2], operands[3]); } })
[gcc r15-2392] xtensa: Make use of scaled [U]FLOAT/TRUNC.S instructions
https://gcc.gnu.org/g:f9c7775f58798a051b57356ad321b758a2ee837d commit r15-2392-gf9c7775f58798a051b57356ad321b758a2ee837d Author: Takayuki 'January June' Suwa Date: Sun Jul 14 20:04:15 2024 +0900 xtensa: Make use of scaled [U]FLOAT/TRUNC.S instructions [U]FLOAT.S machine instruction in Xtensa ISA, which converts an integer to a hardware single-precision FP register, has the ability to divide the result by power of two (0 to 15th). Similarly, [U]TRUNC.S instruction, which truncates single-precision FP to integer, can multiply the source value by power of two in advance, but neither of these currently uses this function (always specified with 0th power of two, i.e. a scaling factor of 1). This patch unleashes the scaling ability of the above instructions. /* example */ float test0(int a) { return a / 2.f; } float test1(unsigned int a) { return a / 32768.f; } int test2(float a) { return a * 2; } unsigned int test3(float a) { return a * 32768; } ;; before test0: movi.n a9, 0x3f float.s f0, a2, 0 sllia9, a9, 24 wfr f1, a9 mul.s f0, f0, f1 rfr a2, f0 ret.n test1: movi.n a9, 7 ufloat.sf0, a2, 0 sllia9, a9, 27 wfr f1, a9 mul.s f0, f0, f1 rfr a2, f0 ret.n test2: wfr f1, a2 add.s f0, f1, f1 trunc.s a2, f0, 0 ret.n test3: movi.n a9, 0x47 sllia9, a9, 24 wfr f1, a2 wfr f2, a9 mul.s f0, f1, f2 utrunc.sa2, f0, 0 ret.n ;; after test0: float.s f0, a2, 1 rfr a2, f0 ret.n test1: ufloat.sf0, a2, 15 rfr a2, f0 ret.n test2: wfr f0, a2 trunc.s a2, f0, 1 ret.n test3: wfr f0, a2 utrunc.sa2, f0, 15 ret.n gcc/ChangeLog: * config/xtensa/predicates.md (fix_scaling_operand, float_scaling_operand): New predicates. * config/xtensa/xtensa.md (any_fix/m_fix/s_fix, any_float/m_float/s_float): New code iterators and their attributes. (fix_truncsfsi2): Change from "fix_truncsfsi2". (*fix_truncsfsi2_2x, *fix_truncsfsi2_scaled): New insn definitions. (floatsisf2): Change from "floatsisf2". (*floatsisf2_scaled): New insn definition. Diff: --- gcc/config/xtensa/predicates.md | 20 ++ gcc/config/xtensa/xtensa.md | 58 - 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md index 19b9f4cd7efe..e676fa4fb95c 100644 --- a/gcc/config/xtensa/predicates.md +++ b/gcc/config/xtensa/predicates.md @@ -159,6 +159,26 @@ return real_equal (CONST_DOUBLE_REAL_VALUE (op), &dconst1); }) +(define_predicate "fix_scaling_operand" + (match_code "const_double") +{ + REAL_VALUE_TYPE r = *CONST_DOUBLE_REAL_VALUE (op); + int exp = REAL_EXP (&r) - 1; + + SET_REAL_EXP (&r, 1); + return real_equal (&r, &dconst1) && IN_RANGE (exp, 2, 15); +}) + +(define_predicate "float_scaling_operand" + (match_code "const_double") +{ + REAL_VALUE_TYPE r = *CONST_DOUBLE_REAL_VALUE (op); + int exp = REAL_EXP (&r) - 1; + + SET_REAL_EXP (&r, 1); + return real_equal (&r, &dconst1) && IN_RANGE (-exp, 1, 15); +}) + (define_predicate "fpmem_offset_operand" (and (match_code "const_int") (match_test "xtensa_mem_offset (INTVAL (op), SFmode)"))) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 0fcbb0b7bc37..376d0f755446 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -91,6 +91,18 @@ ;; the same template. (define_mode_iterator SHI [SI HI]) +;; This iterator and attribute allow signed/unsigned FP truncations to be +;; generated from one template. +(define_code_iterator any_fix [fix unsigned_fix]) +(define_code_attr m_fix [(fix "trunc") (unsigned_fix "utrunc")]) +(define_code_attr s_fix [(fix "") (unsigned_fix "uns")]) + +;; This iterator and attribute allow signed/unsigned FP conversions to be +;; generated from one template. +(define_code_iterator any_float [float unsigned_float]) +(define_code_attr m_float [(float "float") (unsigned_float "ufloat")]) +(define_code_attr s_float [(float "") (unsigned_float "uns")]) + ;; Attributes. @@ -1132,38 +1144,60 @@ ;; Conversions. -(define_insn "fix_truncsfsi2" +(define_insn "fix_truncsfsi
[gcc r15-2396] xtensa: Fix the regression introduce by r15-959-gbe9b3f4375e7
https://gcc.gnu.org/g:8ebb1d79ea16f37214c33d853061d3c9cf5e7f46 commit r15-2396-g8ebb1d79ea16f37214c33d853061d3c9cf5e7f46 Author: Takayuki 'January June' Suwa Date: Sat Jul 20 05:35:33 2024 +0900 xtensa: Fix the regression introduce by r15-959-gbe9b3f4375e7 It is not wrong but also not optimal to specify that sibcalls require register A0 in RTX generation pass, by misleading DFA into thinking it is being used in function body. It would be better to specify it in pro_and_epilogue as with 'return' insn in order to avoid incorrect removing load that restores A0 in subsequent passes, but since it is not possible to modify each sibcall there, as a workaround we will preface it with a 'use' as before. This patch effectively reverts commit r15-959-gbe9b3f4375e7 gcc/ChangeLog: * config/xtensa/xtensa-protos.h (xtensa_expand_call): Remove the third argument. * config/xtensa/xtensa.cc (xtensa_expand_call): Remove the third argument and the code that uses it. * config/xtensa/xtensa.md (call, call_value, sibcall, sibcall_value): Remove each Boolean constant specified in the third argument of xtensa_expand_call. (sibcall_epilogue): Add emitting '(use A0_REG)' after calling xtensa_expand_epilogue. Diff: --- gcc/config/xtensa/xtensa-protos.h | 2 +- gcc/config/xtensa/xtensa.cc | 10 +- gcc/config/xtensa/xtensa.md | 9 + 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 8f645e87de96..3646ceaa0938 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -53,7 +53,7 @@ extern void xtensa_expand_atomic (enum rtx_code, rtx, rtx, rtx, bool); extern void xtensa_emit_loop_end (rtx_insn *, rtx *); extern char *xtensa_emit_branch (bool, rtx *); extern char *xtensa_emit_movcc (bool, bool, bool, rtx *); -extern void xtensa_expand_call (int, rtx *, bool); +extern void xtensa_expand_call (int, rtx *); extern char *xtensa_emit_call (int, rtx *); extern char *xtensa_emit_sibcall (int, rtx *); extern bool xtensa_tls_referenced_p (rtx); diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 772150c7fa22..1ccd42bcda89 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -2297,7 +2297,7 @@ xtensa_emit_movcc (bool inverted, bool isfp, bool isbool, rtx *operands) void -xtensa_expand_call (int callop, rtx *operands, bool sibcall_p) +xtensa_expand_call (int callop, rtx *operands) { rtx call; rtx_insn *call_insn; @@ -2339,14 +2339,6 @@ xtensa_expand_call (int callop, rtx *operands, bool sibcall_p) CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx_EXPR_LIST (Pmode, clob, CALL_INSN_FUNCTION_USAGE (call_insn)); } - else if (sibcall_p) -{ - /* Sibling call requires a return address to the caller, similar to -"return" insn. */ - rtx use = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, A0_REG)); - CALL_INSN_FUNCTION_USAGE (call_insn) = - gen_rtx_EXPR_LIST (Pmode, use, CALL_INSN_FUNCTION_USAGE (call_insn)); -} } diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 376d0f755446..a3b99dc381de 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -2597,7 +2597,7 @@ (match_operand 1 "" ""))] "" { - xtensa_expand_call (0, operands, false); + xtensa_expand_call (0, operands); DONE; }) @@ -2618,7 +2618,7 @@ (match_operand 2 "" "")))] "" { - xtensa_expand_call (1, operands, false); + xtensa_expand_call (1, operands); DONE; }) @@ -2639,7 +2639,7 @@ (match_operand 1 "" ""))] "!TARGET_WINDOWED_ABI" { - xtensa_expand_call (0, operands, true); + xtensa_expand_call (0, operands); DONE; }) @@ -2660,7 +2660,7 @@ (match_operand 2 "" "")))] "!TARGET_WINDOWED_ABI" { - xtensa_expand_call (1, operands, true); + xtensa_expand_call (1, operands); DONE; }) @@ -2777,6 +2777,7 @@ "!TARGET_WINDOWED_ABI" { xtensa_expand_epilogue (); + emit_use (gen_rtx_REG (SImode, A0_REG)); DONE; })
[gcc r15-2397] xtensa: Fix suboptimal loading of pooled constant value into hardware single-precision FP register
https://gcc.gnu.org/g:fb7b82964f54192d0723a45c0657d2eb7c5ac97c commit r15-2397-gfb7b82964f54192d0723a45c0657d2eb7c5ac97c Author: Takayuki 'January June' Suwa Date: Tue Jul 23 16:03:12 2024 +0900 xtensa: Fix suboptimal loading of pooled constant value into hardware single-precision FP register We would like to implement the following to store a single-precision FP constant in a hardware FP register: - Load the bit-exact integer image of the pooled single-precision FP constant into an address (integer) register - Then, assign from that address register to a hardware single-precision FP register .literal_position .literal.LC1, 0x3f80 ... l32ra9, .LC1 wfr f0, a9 However, it was emitted as follows: - Load the address of the FP constant entry in litpool into an address register - Then, dereference the address via that address register into a hardware single-precision FP register .literal_position .literal.LC1, 0x3f80 .literal.LC2, .LC1 ... l32ra9, .LC2 lsi f0, a9, 0 It is obviously inefficient to read the pool twice. gcc/ChangeLog: * config/xtensa/xtensa.md (movsf_internal): Reorder alternative that corresponds to L32R machine instruction, and prefix alternatives that correspond to LSI/SSI instructions with the constraint character '^' so that they are disparaged by reload/LRA. Diff: --- gcc/config/xtensa/xtensa.md | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index a3b99dc381de..f19e1fd16b54 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1453,8 +1453,8 @@ }) (define_insn "movsf_internal" - [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,U,D,D,R,a,f,a,a,W,a,a,U") - (match_operand:SF 1 "move_operand" "f,U,f,d,R,d,r,r,f,Y,iF,T,U,r"))] + [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,^U,D,a,D,R,a,f,a,a,W,a,U") + (match_operand:SF 1 "move_operand" "f,^U,f,d,T,R,d,r,r,f,Y,iF,U,r"))] "((register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)) && !(FP_REG_P (xt_true_regnum (operands[0])) @@ -1464,6 +1464,7 @@ %v1lsi\t%0, %1 %v0ssi\t%1, %0 mov.n\t%0, %1 + %v1l32r\t%0, %1 %v1l32i.n\t%0, %1 %v0s32i.n\t%1, %0 mov\t%0, %1 @@ -1471,12 +1472,11 @@ rfr\t%0, %1 movi\t%0, %y1 const16\t%0, %t1\;const16\t%0, %b1 - %v1l32r\t%0, %1 %v1l32i\t%0, %1 %v0s32i\t%1, %0" - [(set_attr "type" "farith,fload,fstore,move,load,store,move,farith,farith,move,move,load,load,store") + [(set_attr "type" "farith,fload,fstore,move,load,load,store,move,farith,farith,move,move,load,store") (set_attr "mode""SF") - (set_attr "length" "3,3,3,2,2,2,3,3,3,3,6,3,3,3")]) + (set_attr "length" "3,3,3,2,3,2,2,3,3,3,3,6,3,3")]) (define_insn "*lsiu" [(set (match_operand:SF 0 "register_operand" "=f")
[gcc r15-2398] xtensa: Add missing speed cost for TYPE_FARITH in TARGET_INSN_COST
https://gcc.gnu.org/g:c1d35de0d94d43b9976aff44001dadd4dd42b7ae commit r15-2398-gc1d35de0d94d43b9976aff44001dadd4dd42b7ae Author: Takayuki 'January June' Suwa Date: Wed Jul 24 06:07:06 2024 +0900 xtensa: Add missing speed cost for TYPE_FARITH in TARGET_INSN_COST According to the implemented pipeline model, this cost can be assumed to be 1 clock cycle. gcc/ChangeLog: * config/xtensa/xtensa.cc (xtensa_insn_cost): Add a case statement for TYPE_FARITH. Diff: --- gcc/config/xtensa/xtensa.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 1ccd42bcda89..43b1332d42b3 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -4723,6 +4723,7 @@ xtensa_insn_cost (rtx_insn *insn, bool speed) case TYPE_ARITH: case TYPE_MULTI: case TYPE_NOP: + case TYPE_FARITH: case TYPE_FSTORE: return COSTS_N_INSNS (n);
[gcc r15-935] xtensa: Use REG_P(), MEM_P(), etc. instead of comparing GET_CODE()
https://gcc.gnu.org/g:1e091097b1b42fed562a6d80a6e08603d1c648a2 commit r15-935-g1e091097b1b42fed562a6d80a6e08603d1c648a2 Author: Takayuki 'January June' Suwa Date: Thu May 30 22:32:24 2024 +0900 xtensa: Use REG_P(), MEM_P(), etc. instead of comparing GET_CODE() Instead of comparing directly, this patch replaces as much as possible with macros that determine RTX code such as REG_P(), SUBREG_P() or MEM_P(), etc. gcc/ChangeLog: * config/xtensa/xtensa.cc (xtensa_valid_move, constantpool_address_p, xtensa_tls_symbol_p, gen_int_relational, xtensa_emit_move_sequence, xtensa_copy_incoming_a7, xtensa_expand_block_move, xtensa_expand_nonlocal_goto, xtensa_emit_call, xtensa_legitimate_address_p, xtensa_legitimize_address, xtensa_tls_referenced_p, print_operand, print_operand_address, xtensa_output_literal): Replace RTX code comparisons with their predicate macros such as REG_P(). * config/xtensa/xtensa.h (CONSTANT_ADDRESS_P, LEGITIMATE_PIC_OPERAND_P): Ditto. * config/xtensa/xtensa.md (reload_literal, indirect_jump): Ditto. Diff: --- gcc/config/xtensa/xtensa.cc | 90 ++--- gcc/config/xtensa/xtensa.h | 10 ++--- gcc/config/xtensa/xtensa.md | 4 +- 3 files changed, 51 insertions(+), 53 deletions(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 9beac932467..75973cfbac0 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -551,18 +551,18 @@ xtensa_valid_move (machine_mode mode, rtx *operands) int smalloffset_mem_p (rtx op) { - if (GET_CODE (op) == MEM) + if (MEM_P (op)) { rtx addr = XEXP (op, 0); - if (GET_CODE (addr) == REG) + if (REG_P (addr)) return BASE_REG_P (addr, 0); if (GET_CODE (addr) == PLUS) { rtx offset = XEXP (addr, 0); HOST_WIDE_INT val; - if (GET_CODE (offset) != CONST_INT) + if (! CONST_INT_P (offset)) offset = XEXP (addr, 1); - if (GET_CODE (offset) != CONST_INT) + if (! CONST_INT_P (offset)) return FALSE; val = INTVAL (offset); @@ -596,7 +596,7 @@ constantpool_address_p (const_rtx addr) sym = XEXP (addr, 0); } - if ((GET_CODE (sym) == SYMBOL_REF) + if (SYMBOL_REF_P (sym) && CONSTANT_POOL_ADDRESS_P (sym)) return true; return false; @@ -606,9 +606,9 @@ constantpool_address_p (const_rtx addr) int constantpool_mem_p (rtx op) { - if (GET_CODE (op) == SUBREG) + if (SUBREG_P (op)) op = SUBREG_REG (op); - if (GET_CODE (op) == MEM) + if (MEM_P (op)) return constantpool_address_p (XEXP (op, 0)); return FALSE; } @@ -622,7 +622,7 @@ xtensa_tls_symbol_p (rtx x) if (! targetm.have_tls) return false; - return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0; + return SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0; } @@ -749,7 +749,7 @@ gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */ mode = GET_MODE (cmp1); /* Make sure we can handle any constants given to us. */ - if (GET_CODE (cmp1) == CONST_INT) + if (CONST_INT_P (cmp1)) { HOST_WIDE_INT value = INTVAL (cmp1); unsigned HOST_WIDE_INT uvalue = (unsigned HOST_WIDE_INT)value; @@ -768,7 +768,7 @@ gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */ cmp1 = force_reg (mode, cmp1); } } - else if ((GET_CODE (cmp1) != REG) && (GET_CODE (cmp1) != SUBREG)) + else if (! REG_P (cmp1) && ! SUBREG_P (cmp1)) { cmp1 = force_reg (mode, cmp1); } @@ -780,7 +780,7 @@ gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */ /* Comparison to constants, may involve adding 1 to change a LT into LE. Comparison between two registers, may involve switching operands. */ - if (GET_CODE (cmp1) == CONST_INT) + if (CONST_INT_P (cmp1)) { if (p_info->const_add != 0) cmp1 = GEN_INT (INTVAL (cmp1) + p_info->const_add); @@ -1271,7 +1271,7 @@ xtensa_emit_move_sequence (rtx *operands, machine_mode mode) rtx src = operands[1]; if (CONSTANT_P (src) - && (GET_CODE (src) != CONST_INT || ! xtensa_simm12b (INTVAL (src + && (! CONST_INT_P (src) || ! xtensa_simm12b (INTVAL (src { rtx dst = operands[0]; @@ -1368,12 +1368,12 @@ xtensa_copy_incoming_a7 (rtx opnd) /* The operand using a7 may come in a later instruction, so just return the original operand if it doesn't use a7. */ reg = opnd; - if (GET_CODE (reg) == SUBREG) + if (SUBREG_P (reg)) { gcc_assert (SUBREG_BYTE (reg) == 0); reg = SUBREG_REG (reg); } - if (GET_CODE (reg) != REG + if (! REG_P (reg) || REGNO (reg) > A7_REG || REGNO (reg) + hard_regno_nregs (A7_REG, mode) <= A7_REG)
[gcc r15-936] xtensa: Use epilogue_completed rather than cfun->machine->epilogue_done
https://gcc.gnu.org/g:1b58f46ba2079b327580ffa1720c0b40ab3db74d commit r15-936-g1b58f46ba2079b327580ffa1720c0b40ab3db74d Author: Takayuki 'January June' Suwa Date: Thu May 30 22:32:24 2024 +0900 xtensa: Use epilogue_completed rather than cfun->machine->epilogue_done In commit ad89d820bf, an "epilogue_done" member was added to the machine_function structure, but it is sufficient to use the existing "epilogue_completed" global variable. gcc/ChangeLog: * config/xtensa/xtensa-protos.h (xtensa_use_return_instruction_p): Remove. * config/xtensa/xtensa.cc (machine_function): Remove "epilogue_done" field. (xtensa_expand_epilogue): Remove "cfun->machine->epilogue_done" usage. (xtensa_use_return_instruction_p): Remove. * config/xtensa/xtensa.md ("return"): Replace calling "xtensa_use_return_instruction_p()" with inline code. Diff: --- gcc/config/xtensa/xtensa-protos.h | 1 - gcc/config/xtensa/xtensa.cc | 14 -- gcc/config/xtensa/xtensa.md | 5 - 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 508d5b28aa2..b87b3e8ac48 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -76,7 +76,6 @@ extern rtx xtensa_return_addr (int, rtx); extern void xtensa_setup_frame_addresses (void); extern int xtensa_debugger_regno (int); extern long compute_frame_size (poly_int64); -extern bool xtensa_use_return_instruction_p (void); extern void xtensa_expand_prologue (void); extern void xtensa_expand_epilogue (bool); extern void xtensa_adjust_reg_alloc_order (void); diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 75973cfbac0..84268db5c9d 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -104,7 +104,6 @@ struct GTY(()) machine_function compute_frame_size. */ int callee_save_size; bool frame_laid_out; - bool epilogue_done; bool inhibit_logues_a1_adjusts; rtx last_logues_a9_content; HARD_REG_SET eliminated_callee_saved; @@ -3747,25 +3746,12 @@ xtensa_expand_epilogue (bool sibcall_p) stack_pointer_rtx, EH_RETURN_STACKADJ_RTX)); } - cfun->machine->epilogue_done = true; if (sibcall_p) emit_use (gen_rtx_REG (SImode, A0_REG)); else emit_jump_insn (gen_return ()); } -bool -xtensa_use_return_instruction_p (void) -{ - if (!reload_completed) -return false; - if (TARGET_WINDOWED_ABI) -return true; - if (compute_frame_size (get_frame_size ()) == 0) -return true; - return cfun->machine->epilogue_done; -} - void xtensa_set_return_address (rtx address, rtx scratch) { diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 1b82a12d879..6061a86ee13 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -2735,7 +2735,10 @@ (define_insn "return" [(return) (use (reg:SI A0_REG))] - "xtensa_use_return_instruction_p ()" + "reload_completed + && (TARGET_WINDOWED_ABI + || compute_frame_size (get_frame_size ()) == 0 + || epilogue_completed)" { return TARGET_WINDOWED_ABI ? (TARGET_DENSITY ? "retw.n" : "retw") :
[gcc r15-958] xtensa: Simplify several MD templates
https://gcc.gnu.org/g:68cda24d3ac12292a599ff8f9b58fdbc95baba4e commit r15-958-g68cda24d3ac12292a599ff8f9b58fdbc95baba4e Author: Takayuki 'January June' Suwa Date: Fri May 31 19:23:13 2024 +0900 xtensa: Simplify several MD templates No functional changes. gcc/ChangeLog: * config/xtensa/predicates.md (subreg_HQI_lowpart_operator, xtensa_sminmax_operator): New operator predicates. * config/xtensa/xtensa-protos.h (xtensa_match_CLAMPS_imms_p): Remove. * config/xtensa/xtensa.cc (xtensa_match_CLAMPS_imms_p): Ditto. * config/xtensa/xtensa.md (*addsubx, *extzvsi-1bit_ashlsi3, *extzvsi-1bit_addsubx): Revise the output statements by conditional ternary operator rather than switch-case clause in order to avoid using gcc_unreachable(). (xtensa_clamps): Reduce to a single pattern definition using the predicate added above. (Some split patterns to assist *masktrue_const_bitcmpl): Ditto. Diff: --- gcc/config/xtensa/predicates.md | 23 gcc/config/xtensa/xtensa-protos.h | 1 - gcc/config/xtensa/xtensa.cc | 10 gcc/config/xtensa/xtensa.md | 109 +++--- 4 files changed, 43 insertions(+), 100 deletions(-) diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md index a296c7ecc99..19b9f4cd7ef 100644 --- a/gcc/config/xtensa/predicates.md +++ b/gcc/config/xtensa/predicates.md @@ -200,6 +200,29 @@ (define_predicate "xtensa_bit_join_operator" (match_code "plus,ior")) +(define_predicate "subreg_HQI_lowpart_operator" + (match_code "subreg") +{ + int ofs = SUBREG_BYTE (op), pos = 0; + switch (GET_MODE (op)) +{ +case QImode: + if (BYTES_BIG_ENDIAN) + pos = 3; + break; +case HImode: + if (BYTES_BIG_ENDIAN) + pos = 2; + break; +default: + return false; +} + return ofs == pos; +}) + +(define_predicate "xtensa_sminmax_operator" + (match_code "smin,smax")) + (define_predicate "tls_symbol_operand" (and (match_code "symbol_ref") (match_test "SYMBOL_REF_TLS_MODEL (op) != 0"))) diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index b87b3e8ac48..834f15e0e48 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -60,7 +60,6 @@ extern bool xtensa_tls_referenced_p (rtx); extern enum rtx_code xtensa_shlrd_which_direction (rtx, rtx); extern bool xtensa_split1_finished_p (void); extern void xtensa_split_DI_reg_imm (rtx *); -extern bool xtensa_match_CLAMPS_imms_p (rtx, rtx); #ifdef TREE_CODE extern void init_cumulative_args (CUMULATIVE_ARGS *, int); diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 84268db5c9d..301448c65e2 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -2666,16 +2666,6 @@ xtensa_emit_add_imm (rtx dst, rtx src, HOST_WIDE_INT imm, rtx scratch, } -/* Return true if the constants used in the application of smin() following - smax() meet the specifications of the CLAMPS machine instruction. */ -bool -xtensa_match_CLAMPS_imms_p (rtx cst_max, rtx cst_min) -{ - return IN_RANGE (exact_log2 (-INTVAL (cst_max)), 7, 22) -&& (INTVAL (cst_max) + INTVAL (cst_min)) == -1; -} - - /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */ static bool diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 6061a86ee13..03e816b8a12 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -180,15 +180,8 @@ "TARGET_ADDX" { operands[3] = GEN_INT (1 << INTVAL (operands[3])); - switch (GET_CODE (operands[4])) -{ -case PLUS: - return "addx%3\t%0, %1, %2"; -case MINUS: - return "subx%3\t%0, %1, %2"; -default: - gcc_unreachable (); -} + return GET_CODE (operands[4]) == PLUS + ? "addx%3\t%0, %1, %2" : "subx%3\t%0, %1, %2"; } [(set_attr "type""arith") (set_attr "mode""SI") @@ -535,34 +528,23 @@ ;; Signed clamp. -(define_insn_and_split "*xtensa_clamps" - [(set (match_operand:SI 0 "register_operand" "=a") - (smax:SI (smin:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "i")) -(match_operand:SI 3 "const_int_operand" "i")))] - "TARGET_MINMAX && TARGET_CLAMPS - && xtensa_match_CLAMPS_imms_p (operands[3], operands[2])" - "#" - "&& 1" - [(set (match_dup 0) - (smin:SI (smax:SI (match_dup 1) - (match_dup 3)) -(match_dup 2)))] - "" - [(set_attr "type""arith") - (set_attr "mode""SI") - (set_attr "length" "3")]) - (define_insn "*xtensa_clamps" [(set (match_operand:SI 0 "register_operand" "=a") - (smin:SI (smax:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const
[gcc r15-959] xtensa: Prepend "(use A0_REG)" to sibling call CALL_INSN_FUNCTION_USAGE instead of emitting it as in
https://gcc.gnu.org/g:be9b3f4375e74b6f10dd15fc563c93f803e91db5 commit r15-959-gbe9b3f4375e74b6f10dd15fc563c93f803e91db5 Author: Takayuki 'January June' Suwa Date: Fri May 31 19:24:48 2024 +0900 xtensa: Prepend "(use A0_REG)" to sibling call CALL_INSN_FUNCTION_USAGE instead of emitting it as insn at the end of epilogue No functional changes. gcc/ChangeLog: * config/xtensa/xtensa-protos.h (xtensa_expand_call): Add the third argument as boolean. (xtensa_expand_epilogue): Remove the first argument. * config/xtensa/xtensa.cc (xtensa_expand_call): Add the third argument "sibcall_p", and modify in order to prepend "(use A0_REG)" to CALL_INSN_FUNCTION_USAGE if the argument is true. (xtensa_expand_epilogue): Remove the first argument "sibcall_p" and its conditional clause. * config/xtensa/xtensa.md (call, call_value, sibcall, sibcall_value): Append a boolean value to the argument of xtensa_expand_call() indicating whether it is sibling call or not. (epilogue): Remove the boolean argument from xtensa_expand_epilogue(), and then append emitting "(return)". (sibcall_epilogue): Remove the boolean argument from xtensa_expand_epilogue(). Diff: --- gcc/config/xtensa/xtensa-protos.h | 4 ++-- gcc/config/xtensa/xtensa.cc | 16 ++-- gcc/config/xtensa/xtensa.md | 13 +++-- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 834f15e0e48..77553b0453f 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -53,7 +53,7 @@ extern void xtensa_expand_atomic (enum rtx_code, rtx, rtx, rtx, bool); extern void xtensa_emit_loop_end (rtx_insn *, rtx *); extern char *xtensa_emit_branch (bool, rtx *); extern char *xtensa_emit_movcc (bool, bool, bool, rtx *); -extern void xtensa_expand_call (int, rtx *); +extern void xtensa_expand_call (int, rtx *, bool); extern char *xtensa_emit_call (int, rtx *); extern char *xtensa_emit_sibcall (int, rtx *); extern bool xtensa_tls_referenced_p (rtx); @@ -76,7 +76,7 @@ extern void xtensa_setup_frame_addresses (void); extern int xtensa_debugger_regno (int); extern long compute_frame_size (poly_int64); extern void xtensa_expand_prologue (void); -extern void xtensa_expand_epilogue (bool); +extern void xtensa_expand_epilogue (void); extern void xtensa_adjust_reg_alloc_order (void); extern enum reg_class xtensa_regno_to_class (int regno); extern HOST_WIDE_INT xtensa_initial_elimination_offset (int from, int to); diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 301448c65e2..45dc1be3ff5 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -2239,7 +2239,7 @@ xtensa_emit_movcc (bool inverted, bool isfp, bool isbool, rtx *operands) void -xtensa_expand_call (int callop, rtx *operands) +xtensa_expand_call (int callop, rtx *operands, bool sibcall_p) { rtx call; rtx_insn *call_insn; @@ -2281,6 +2281,14 @@ xtensa_expand_call (int callop, rtx *operands) CALL_INSN_FUNCTION_USAGE (call_insn) = gen_rtx_EXPR_LIST (Pmode, clob, CALL_INSN_FUNCTION_USAGE (call_insn)); } + else if (sibcall_p) +{ + /* Sibling call requires a return address to the caller, similar to +"return" insn. */ + rtx use = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, A0_REG)); + CALL_INSN_FUNCTION_USAGE (call_insn) = + gen_rtx_EXPR_LIST (Pmode, use, CALL_INSN_FUNCTION_USAGE (call_insn)); +} } @@ -3671,7 +3679,7 @@ xtensa_expand_prologue (void) } void -xtensa_expand_epilogue (bool sibcall_p) +xtensa_expand_epilogue (void) { if (!TARGET_WINDOWED_ABI) { @@ -3736,10 +3744,6 @@ xtensa_expand_epilogue (bool sibcall_p) stack_pointer_rtx, EH_RETURN_STACKADJ_RTX)); } - if (sibcall_p) -emit_use (gen_rtx_REG (SImode, A0_REG)); - else -emit_jump_insn (gen_return ()); } void diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 03e816b8a12..ef826b63e44 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -2553,7 +2553,7 @@ (match_operand 1 "" ""))] "" { - xtensa_expand_call (0, operands); + xtensa_expand_call (0, operands, false); DONE; }) @@ -2574,7 +2574,7 @@ (match_operand 2 "" "")))] "" { - xtensa_expand_call (1, operands); + xtensa_expand_call (1, operands, false); DONE; }) @@ -2595,7 +2595,7 @@ (match_operand 1 "" ""))] "!TARGET_WINDOWED_ABI" { - xtensa_expand_call (0, operands); + xtensa_expand_call (0, operands, true); DONE; }) @@ -2616,7 +2616,7 @@ (match_operand 2 "" "")))] "!TARGET_WINDOWED_ABI" { - xtensa_expand_call (1, o
[gcc r15-1433] xtensa: constantsynth: Reforge to fix some non-fatal issues
https://gcc.gnu.org/g:23141088e8fb50bf916ac0b2e364b1eef9f3569d commit r15-1433-g23141088e8fb50bf916ac0b2e364b1eef9f3569d Author: Takayuki 'January June' Suwa Date: Wed Jun 19 11:55:57 2024 +0900 xtensa: constantsynth: Reforge to fix some non-fatal issues The previous constant synthesis logic had some issues that were non-fatal but worth considering: - It didn't work with DFmode literals, because those were cast to SImode rather SFmode when splitting into two natural-width words by split_double(). - It didn't work with large literals when TARGET_AUTO_LITPOOLS was enabled, because those were relaxed MOVI immediates rather references to literal pool entries, - It didn't take into account that when literals with the same RTL representation are pooled multiple times within a function, those entries are shared (especially important when optimizing for size). This patch addresses the above issues by making appropriate tweaks to the constant synthesis logic. gcc/ChangeLog: * config/xtensa/xtensa-protos.h (xtensa_constantsynth): Change the second argument from HOST_WIDE_INT to rtx. * config/xtensa/xtensa.cc (#include): Add "context.h" and "pass_manager.h". (machine_function): Add a new hash_map field "litpool_usage". (xtensa_constantsynth): Make "src" (the second operand) accept RTX literal instead of its value, and treat both bare and pooled SI/SFmode literals equally by bit-exact canonicalization into CONST_INT RTX internally. And then, make avoid synthesis if such multiple identical canonicalized literals are found in same function when optimizing for size. Finally, for literals where synthesis is not possible or has been avoided, re-emit "move" RTXes with canonicalized ones to increase the chances of sharing literal pool entries. * config/xtensa/xtensa.md (split patterns for constant synthesis): Change to simply invoke xtensa_constantsynth() as mentioned above, and add new patterns for when TARGET_AUTO_LITPOOLS is enabled. Diff: --- gcc/config/xtensa/xtensa-protos.h | 2 +- gcc/config/xtensa/xtensa.cc | 75 +++ gcc/config/xtensa/xtensa.md | 56 + 3 files changed, 103 insertions(+), 30 deletions(-) diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 77553b0453f1..8f645e87de96 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -44,7 +44,7 @@ extern int xtensa_expand_scc (rtx *, machine_mode); extern int xtensa_expand_block_move (rtx *); extern int xtensa_expand_block_set (rtx *); extern void xtensa_split_operand_pair (rtx *, machine_mode); -extern int xtensa_constantsynth (rtx, HOST_WIDE_INT); +extern int xtensa_constantsynth (rtx, rtx); extern int xtensa_emit_move_sequence (rtx *, machine_mode); extern rtx xtensa_copy_incoming_a7 (rtx); extern void xtensa_expand_nonlocal_goto (rtx *); diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 45dc1be3ff52..bc127997ac6c 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -58,6 +58,8 @@ along with GCC; see the file COPYING3. If not see #include "insn-attr.h" #include "tree-pass.h" #include "print-rtl.h" +#include "context.h" +#include "pass_manager.h" #include /* This file should be included last. */ @@ -107,6 +109,7 @@ struct GTY(()) machine_function bool inhibit_logues_a1_adjusts; rtx last_logues_a9_content; HARD_REG_SET eliminated_callee_saved; + hash_map *litpool_usage; }; static void xtensa_option_override (void); @@ -1104,7 +1107,7 @@ xtensa_split_operand_pair (rtx operands[4], machine_mode mode) } -/* Try to emit insns to load srcval (that cannot fit into signed 12-bit) +/* Try to emit insns to load src (either naked or pooled SI/SF constant) into dst with synthesizing a such constant value from a sequence of load-immediate / arithmetic ones, instead of a L32R instruction (plus a constant in litpool). */ @@ -1190,11 +1193,67 @@ xtensa_constantsynth_rtx_ADDSUBX (rtx reg, HOST_WIDE_INT imm) } int -xtensa_constantsynth (rtx dst, HOST_WIDE_INT srcval) +xtensa_constantsynth (rtx dst, rtx src) { + HOST_WIDE_INT srcval; + static opt_pass *pass_rtl_split2; + int *pv; + + /* Derefer if src is litpool entry, and get integer constant value. */ + src = avoid_constant_pool_reference (src); + if (CONST_INT_P (src)) +srcval = INTVAL (src); + else if (CONST_DOUBLE_P (src) && GET_MODE (src) == SFmode) +{ + long l; + + REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (src), l); + srcval = (int32_t)l, src = GEN_INT (srcval); +} + else +return 0; + + /* Force dst
[gcc r15-1453] xtensa: Eliminate double MEMW insertions for volatile memory
https://gcc.gnu.org/g:0982552bc4eeffb5520deba10dedecfb2390a8de commit r15-1453-g0982552bc4eeffb5520deba10dedecfb2390a8de Author: Takayuki 'January June' Suwa Date: Wed Jun 19 13:59:54 2024 +0900 xtensa: Eliminate double MEMW insertions for volatile memory This patch makes avoid inserting a MEMW instruction before a load/store nstruction with volatile memory reference if there is already a MEMW immediately before it. gcc/ChangeLog: * config/xtensa/xtensa.cc (print_operand): When outputting MEMW before the instruction, check if the previous instruction is already that. Diff: --- gcc/config/xtensa/xtensa.cc | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index bc127997ac6c..e2549de5df05 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -3078,7 +3078,17 @@ print_operand (FILE *file, rtx x, int letter) /* For a volatile memory reference, emit a MEMW before the load or store. */ if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE) - fprintf (file, "memw\n\t"); + { + rtx_insn *prev_insn + = prev_nonnote_nondebug_insn (current_output_insn); + rtx pat, src; + + if (! (prev_insn && NONJUMP_INSN_P (prev_insn) +&& GET_CODE (pat = PATTERN (prev_insn)) == SET +&& GET_CODE (src = SET_SRC (pat)) == UNSPEC +&& XINT (src, 1) == UNSPEC_MEMW)) + fprintf (file, "memw\n\t"); + } } else output_operand_lossage ("invalid %%v value");
[gcc r15-4706] xtensa: Define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P target hook
https://gcc.gnu.org/g:211459e12147e9ed42c0a0947b1b95b551e03ef3 commit r15-4706-g211459e12147e9ed42c0a0947b1b95b551e03ef3 Author: Takayuki 'January June' Suwa Date: Wed Oct 23 11:31:15 2024 +0900 xtensa: Define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P target hook In commit bc5a9dab55d13f888a3cdd150c8cf5c2244f35e0 ("gcc: xtensa: reorder movsi_internal patterns for better code generation during LRA"), the instruction order in "movsi_internal" MD definition was changed to make LRA use load/store instructions with larger memory address displacements, but as a side effect, it now uses the larger displacements (ie., the larger instructions) even outside of reload operations. The underlying problem is that LRA assumes by default that there is only one maximal legitimate displacement for the same address structure, meaning that it has no choice but to use the first load/store instruction it finds. To fix this, define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook to always return true. gcc/ChangeLog: * config/xtensa/xtensa.cc (TARGET_DIFFERENT_ADDR_DISPLACEMENT_P): Add new target hook to always return true. * config/xtensa/xtensa.md (movsi_internal): Revert the previous changes. Diff: --- gcc/config/xtensa/xtensa.cc | 3 +++ gcc/config/xtensa/xtensa.md | 12 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 43b1332d42b3..d2793822641c 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -363,6 +363,9 @@ static rtx xtensa_delegitimize_address (rtx); #undef TARGET_MAX_ANCHOR_OFFSET #define TARGET_MAX_ANCHOR_OFFSET 1020 +#undef TARGET_DIFFERENT_ADDR_DISPLACEMENT_P +#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true + struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index f19e1fd16b54..2c08c7d6bf10 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1279,15 +1279,13 @@ }) (define_insn "movsi_internal" - [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,a,U,D,R,R,a,q,a,a,W,a,*a,*A") - (match_operand:SI 1 "move_operand" "M,D,d,U,r,R,D,d,r,r,I,Y,i,T,*A,*r"))] + [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,D,R,R,a,q,a,a,W,a,a,U,*a,*A") + (match_operand:SI 1 "move_operand" "M,D,d,R,D,d,r,r,I,Y,i,T,U,r,*A,*r"))] "xtensa_valid_move (SImode, operands)" "@ movi.n\t%0, %x1 mov.n\t%0, %1 mov.n\t%0, %1 - %v1l32i\t%0, %1 - %v0s32i\t%1, %0 %v1l32i.n\t%0, %1 %v0s32i.n\t%1, %0 %v0s32i.n\t%1, %0 @@ -1297,11 +1295,13 @@ movi\t%0, %1 const16\t%0, %t1\;const16\t%0, %b1 %v1l32r\t%0, %1 + %v1l32i\t%0, %1 + %v0s32i\t%1, %0 rsr\t%0, ACCLO wsr\t%1, ACCLO" - [(set_attr "type" "move,move,move,load,store,load,store,store,move,move,move,move,move,load,rsr,wsr") + [(set_attr "type" "move,move,move,load,store,store,move,move,move,move,move,load,load,store,rsr,wsr") (set_attr "mode""SI") - (set_attr "length" "2,2,2,3,3,2,2,2,3,3,3,3,6,3,3,3")]) + (set_attr "length" "2,2,2,2,2,2,3,3,3,3,6,3,3,3,3,3")]) (define_split [(set (match_operand:SHI 0 "register_operand")
[gcc r15-5074] xtensa: Fix the issue in "*extzvsi-1bit_addsubx"
https://gcc.gnu.org/g:b433140a6cb40acedb2e6cb43c4e5a388e33f805 commit r15-5074-gb433140a6cb40acedb2e6cb43c4e5a388e33f805 Author: Takayuki 'January June' Suwa Date: Sun Nov 10 15:39:22 2024 +0900 xtensa: Fix the issue in "*extzvsi-1bit_addsubx" The second source register of insn "*extzvsi-1bit_addsubx" cannot be the same as the destination register, because that register will be overwritten with an intermediate value after insn splitting. /* example #1 */ int test1(int b, int a) { return ((a & 1024) ? 4 : 0) + b; } ;; result #1 (incorrect) test1: extui a2, a3, 10, 1 ;; overwrites A2 before used addx4 a2, a2, a2 ret.n This patch fixes that. ;; result #1 (correct) test1: extui a3, a3, 10, 1 ;; uses A3 and then overwrites addx4 a2, a3, a2 ret.n However, it should be noted that the first source register can be the same as the destination without any problems. /* example #2 */ int test2(int a, int b) { return ((a & 1024) ? 4 : 0) + b; } ;; result (correct) test2: extui a2, a2, 10, 1 ;; uses A2 and then overwrites addx4 a2, a2, a3 ret.n gcc/ChangeLog: * config/xtensa/xtensa.md (*extzvsi-1bit_addsubx): Add '&' to the destination register constraint to indicate that it is 'earlyclobber', append '0' to the first source register constraint to indicate that it can be the same as the destination register, and change the split condition from 1 to reload_completed so that the insn will be split only after RA in order to obtain allocated registers that satisfy the above constraints. Diff: --- gcc/config/xtensa/xtensa.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 2c08c7d6bf10..cecd319685c0 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1109,17 +1109,17 @@ (const_int 6)))]) (define_insn_and_split "*extzvsi-1bit_addsubx" - [(set (match_operand:SI 0 "register_operand" "=a") + [(set (match_operand:SI 0 "register_operand" "=&a") (match_operator:SI 5 "addsub_operator" [(and:SI (match_operator:SI 6 "logical_shift_operator" - [(match_operand:SI 1 "register_operand" "r") + [(match_operand:SI 1 "register_operand" "r0") (match_operand:SI 3 "const_int_operand" "i")]) (match_operand:SI 4 "const_int_operand" "i")) (match_operand:SI 2 "register_operand" "r")]))] "TARGET_ADDX && IN_RANGE (exact_log2 (INTVAL (operands[4])), 1, 3)" "#" - "&& 1" + "&& reload_completed" [(set (match_dup 0) (zero_extract:SI (match_dup 1) (const_int 1)
[gcc r16-529] xtensa: Fix up unwanted spills of SFmode hard registers holding function arguments/returns
https://gcc.gnu.org/g:6d73d75a7c04caf3457297400372f87765b9a653 commit r16-529-g6d73d75a7c04caf3457297400372f87765b9a653 Author: Takayuki 'January June' Suwa Date: Sun May 11 04:51:11 2025 +0900 xtensa: Fix up unwanted spills of SFmode hard registers holding function arguments/returns Until now (presumably after transition to LRA), hard registers storing function arguments or return values were spilling undesirably when TARGET_HARD_FLOAT is enabled. /* example */ float test0(float a, float b) { return a + b; } extern float foo(void); float test1(void) { return foo() * 3.14f; } ;; before test0: entry sp, 48 wfr f0, a2 wfr f1, a3 add.s f0, f0, f1 s32i.n a2, sp, 0 ;; unwanted spilling-out s32i.n a3, sp, 4 ;; rfr a2, f0 retw.n .literal .LC1, 1078523331 test1: entry sp, 48 call8 foo l32ra8, .LC1 wfr f0, a10 wfr f1, a8 mul.s f0, f0, f1 s32i.n a10, sp, 0 ;; unwanted spilling-out rfr a2, f0 retw.n Ultimately, that is because the costs of moving between integer and floating-point hard registers are undefined and the default (large value) is used. This patch fixes this. ;; after test0: entry sp, 32 wfr f1, a2 wfr f0, a3 add.s f0, f1, f0 rfr a2, f0 retw.n .literal .LC1, 1078523331 test1: entry sp, 32 call8 foo l32ra8, .LC1 wfr f1, a10 wfr f0, a8 mul.s f0, f1, f0 rfr a2, f0 retw.n gcc/ChangeLog: * config/xtensa/xtensa.cc (xtensa_register_move_cost): Add appropriate move costs between AR_REGS and FP_REGS. Diff: --- gcc/config/xtensa/xtensa.cc | 28 +++- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 53db06ec6f2c..621fb0aeb461 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -4430,17 +4430,27 @@ static int xtensa_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, reg_class_t from, reg_class_t to) { - if (from == to && from != BR_REGS && to != BR_REGS) + /* If both are equal (except for BR_REGS) or belong to AR_REGS, + the cost is 2 (the default value). */ + if ((from == to && from != BR_REGS && to != BR_REGS) + || (reg_class_subset_p (from, AR_REGS) + && reg_class_subset_p (to, AR_REGS))) return 2; - else if (reg_class_subset_p (from, AR_REGS) - && reg_class_subset_p (to, AR_REGS)) -return 2; - else if (reg_class_subset_p (from, AR_REGS) && to == ACC_REG) -return 3; - else if (from == ACC_REG && reg_class_subset_p (to, AR_REGS)) + + /* The cost between AR_REGS and FR_REGS must be <= 8 (2x the default + MEMORY_MOVE_COST) to avoid unwanted spills, and > 4 (2x the above + case) to avoid excessive register-to-register moves. */ + if ((reg_class_subset_p (from, AR_REGS) && to == FP_REGS) + || (from == FP_REGS && reg_class_subset_p (to, AR_REGS))) +return 5; + + if ((reg_class_subset_p (from, AR_REGS) && to == ACC_REG) + || (from == ACC_REG && reg_class_subset_p (to, AR_REGS))) return 3; - else -return 10; + + /* Otherwise, spills to stack (because greater than 2x the default + MEMORY_MOVE_COST). */ + return 10; } /* Compute a (partial) cost for rtx X. Return true if the complete
[gcc r16-530] testsuite: xtensa: add support for effective_target_sync_*
https://gcc.gnu.org/g:aa0d25683bb5c7f2256d9e897fe471f0de84ea9b commit r16-530-gaa0d25683bb5c7f2256d9e897fe471f0de84ea9b Author: Max Filippov Date: Sun Apr 27 18:05:20 2025 -0700 testsuite: xtensa: add support for effective_target_sync_* Add new function check_effective_target_xtensa_atomic and use it in the check_effective_target_sync_int_long and check_effective_target_sync_char_short. gcc/testsuite/ChangeLog: * lib/target-supports.exp (check_effective_target_xtensa_atomic): New function. (check_effective_target_sync_int_long) (check_effective_target_sync_char_short): Add test for xtensa. Diff: --- gcc/testsuite/lib/target-supports.exp | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 287e51bbfc66..24d0b3d08e34 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -10145,6 +10145,7 @@ proc check_effective_target_sync_int_long { } { || ([istarget arc*-*-*] && [check_effective_target_arc_atomic]) || [check_effective_target_mips_llsc] || [istarget nvptx*-*-*] +|| ([istarget xtensa*-*-*] && [check_effective_target_xtensa_atomic]) }}] } @@ -10182,7 +10183,9 @@ proc check_effective_target_sync_char_short { } { || ([istarget riscv*-*-*] && ([check_effective_target_riscv_zalrsc] || [check_effective_target_riscv_zabha])) -|| [check_effective_target_mips_llsc] }}] +|| [check_effective_target_mips_llsc] +|| ([istarget xtensa*-*-*] && [check_effective_target_xtensa_atomic]) +}}] } # Return 1 if thread_fence does not rely on __sync_synchronize @@ -14407,3 +14410,12 @@ proc check_effective_target_speculation_barrier_defined { } { } }] } + +# Return 1 if this is a compiler supporting Xtensa atomic operations +proc check_effective_target_xtensa_atomic { } { +return [check_no_compiler_messages xtensa_atomic assembly { + #if __XCHAL_HAVE_S32C1I != 1 && __XCHAL_HAVE_EXCLUSIVE != 1 + #error FOO + #endif +}] +}
[gcc r16-1031] xtensa: Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS
https://gcc.gnu.org/g:9050005673b68f5267a4c8262363b547555337a0 commit r16-1031-g9050005673b68f5267a4c8262363b547555337a0 Author: Takayuki 'January June' Suwa Date: Tue May 27 15:57:26 2025 +0900 xtensa: Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS in order to avoid using ALL_REGS rclass as is done on other targets, instead of overestimating between integer and FP register move costs. gcc/ChangeLog: * config/xtensa/xtensa.cc (xtensa_ira_change_pseudo_allocno_class): New prototype and function. (TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS): Define macro. (xtensa_register_move_cost): Change between integer and FP register move cost to a value based on actual behavior, i.e. 2, the default and the same as the move cost between integer registers. Diff: --- gcc/config/xtensa/xtensa.cc | 27 +++ 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index e03dee3f4c4a..d1856f76c053 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -197,6 +197,8 @@ static void xtensa_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, tree function); static rtx xtensa_delegitimize_address (rtx); +static reg_class_t xtensa_ira_change_pseudo_allocno_class (int, reg_class_t, + reg_class_t); @@ -366,6 +368,9 @@ static rtx xtensa_delegitimize_address (rtx); #undef TARGET_DIFFERENT_ADDR_DISPLACEMENT_P #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true +#undef TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS +#define TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS xtensa_ira_change_pseudo_allocno_class + struct gcc_target targetm = TARGET_INITIALIZER; @@ -4432,12 +4437,10 @@ xtensa_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, && reg_class_subset_p (to, AR_REGS))) return 2; - /* The cost between AR_REGS and FR_REGS must be <= 8 (2x the default - MEMORY_MOVE_COST) to avoid unwanted spills, and > 4 (2x the above - case) to avoid excessive register-to-register moves. */ + /* The cost between AR_REGS and FR_REGS is 2 (the default value). */ if ((reg_class_subset_p (from, AR_REGS) && to == FP_REGS) || (from == FP_REGS && reg_class_subset_p (to, AR_REGS))) -return 5; +return 2; if ((reg_class_subset_p (from, AR_REGS) && to == ACC_REG) || (from == ACC_REG && reg_class_subset_p (to, AR_REGS))) @@ -5433,4 +5436,20 @@ xtensa_delegitimize_address (rtx op) return op; } +/* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS, in order to tell + the register allocator to avoid using ALL_REGS rclass. */ + +static reg_class_t +xtensa_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class, + reg_class_t best_class) +{ + if (allocno_class != ALL_REGS) +return allocno_class; + + if (best_class != ALL_REGS) +return best_class; + + return FLOAT_MODE_P (PSEUDO_REGNO_MODE (regno)) ? FP_REGS : AR_REGS; +} + #include "gt-xtensa.h"
[gcc r16-1032] xtensa: Remove an unnecessary constraint modifier from movsf_internal insn pattern
https://gcc.gnu.org/g:2e5130f6870bdb016f58f42f2ff99a2226e93af6 commit r16-1032-g2e5130f6870bdb016f58f42f2ff99a2226e93af6 Author: Takayuki 'January June' Suwa Date: Tue May 27 15:58:35 2025 +0900 xtensa: Remove an unnecessary constraint modifier from movsf_internal insn pattern In this case, there is no need to consider reloading when memory is the destination. On the other hand, when memory is the source, reloading read from constant pool becomes double indirection and should obviously be avoided. gcc/ChangeLog: * config/xtensa/xtensa.md (movsf_internal): Remove destination side constraint modifier '^' in the third alternative. Diff: --- gcc/config/xtensa/xtensa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 88f011cd0ef6..c7ac456ae5f3 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1453,7 +1453,7 @@ }) (define_insn "movsf_internal" - [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,^U,D,a,D,R,a,f,a,a,W,a,U") + [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,U,D,a,D,R,a,f,a,a,W,a,U") (match_operand:SF 1 "move_operand" "f,^U,f,d,T,R,d,r,r,f,Y,iF,U,r"))] "((register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode))
[gcc r16-1033] xtensa: Remove include of reload.h
https://gcc.gnu.org/g:2e1f0142708e29bf0f19ef76c9dded913081a0ef commit r16-1033-g2e1f0142708e29bf0f19ef76c9dded913081a0ef Author: Takayuki 'January June' Suwa Date: Tue May 27 15:59:21 2025 +0900 xtensa: Remove include of reload.h As one of the last steps in removing old reload. gcc/ChangeLog: * config/xtensa/xtensa.cc: Remove include of reload.h. Diff: --- gcc/config/xtensa/xtensa.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index d1856f76c053..a9d67a56cd6a 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -48,7 +48,6 @@ along with GCC; see the file COPYING3. If not see #include "alias.h" #include "explow.h" #include "expr.h" -#include "reload.h" #include "langhooks.h" #include "gimplify.h" #include "builtins.h"
[gcc r16-1280] xtensa: Implement l(ceil|floor)sfsi2 insn patterns and their scaled variants
https://gcc.gnu.org/g:5f3b5b0616fe883e86e95d9476371cf87059ca7f commit r16-1280-g5f3b5b0616fe883e86e95d9476371cf87059ca7f Author: Takayuki 'January June' Suwa Date: Sun Jun 8 14:05:05 2025 +0900 xtensa: Implement l(ceil|floor)sfsi2 insn patterns and their scaled variants By using the previously unused CEIL|FLOOR.S floating-point coprocessor instructions. In addition, two instruction operand format codes are added to output the scale value as assembler source. /* example */ int test0(float a) { return __builtin_lceilf(a); } int test1(float a) { return __builtin_lceilf(a * 2); } int test2(float a) { return __builtin_lfloorf(a); } int test3(float a) { return __builtin_lfloorf(a * 32768); } ;; result test0: entry sp, 32 wfr f0, a2 ceil.s a2, f0, 0 retw.n test1: entry sp, 32 wfr f0, a2 ceil.s a2, f0, 1 retw.n test2: entry sp, 32 wfr f0, a2 floor.s a2, f0, 0 retw.n test3: entry sp, 32 wfr f0, a2 floor.s a2, f0, 15 retw.n However, because the rounding-half behavior (e.g., the rule that determines whether 1.5 should be rounded to 1 or 2) of the two is inconsistent; the lroundsfsi2 pattern is explicitly specified that rounding to nearest integer and away from zero, but the other hand, the ROUND.S instruction is not specified that by the ISA and is implementation-dependent. Therefore lroundsfsi2 cannot be implemented by ROUND.S. gcc/ChangeLog: * config/xtensa/xtensa.cc (printx, print_operand): Add two instruction operand format codes 'U' and 'V', whose represent scale factors of 0 to 15th positive/negative power of two. * config/xtensa/xtensa.md (c_enum "unspec"): Add UNSPEC_CEIL and UNSPEC_FLOOR. (int_iterator ANY_ROUND, int_attr m_round): New integer iterator and its attribute. (fix_truncsfsi2, *fix_truncsfsi2_2x, *fix_truncsfsi2_scaled, floatsisf2, *floatsisf2_scaled): Use output templates with the operand formats added above, instead of individual output statements. (lsfsi2, *lsfsi2_2x, *lsfsi2_scaled): New insn patterns. Diff: --- gcc/config/xtensa/xtensa.cc | 16 +++ gcc/config/xtensa/xtensa.md | 50 ++--- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index a9d67a56cd6a..90b5ff93042f 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -3047,6 +3047,8 @@ xtensa_modes_tieable_p (machine_mode mode1, machine_mode mode2) 'K' CONST_INT, print number of bits in mask for EXTUI 'R' CONST_INT, print (X & 0x1f) 'L' CONST_INT, print ((32 - X) & 0x1f) + 'U', CONST_DOUBLE:SF, print (REAL_EXP (rval) - 1) + 'V', CONST_DOUBLE:SF, print (1 - REAL_EXP (rval)) 'D' REG, print second register of double-word register operand 'N' MEM, print address of next word following a memory operand 'v' MEM, if memory reference is volatile, output a MEMW before it @@ -3143,6 +3145,20 @@ print_operand (FILE *file, rtx x, int letter) output_operand_lossage ("invalid %%R value"); break; +case 'U': + if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode) + fprintf (file, "%d", REAL_EXP (CONST_DOUBLE_REAL_VALUE (x)) - 1); + else + output_operand_lossage ("invalid %%U value"); + break; + +case 'V': + if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode) + fprintf (file, "%d", 1 - REAL_EXP (CONST_DOUBLE_REAL_VALUE (x))); + else + output_operand_lossage ("invalid %%V value"); + break; + case 'x': if (CONST_INT_P (x)) printx (file, INTVAL (x)); diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index c7ac456ae5f3..56e222dddfd2 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -41,6 +41,8 @@ UNSPEC_LSETUP_START UNSPEC_LSETUP_END UNSPEC_FRAME_BLOCKAGE + UNSPEC_CEIL + UNSPEC_FLOOR ]) (define_c_enum "unspecv" [ @@ -103,6 +105,11 @@ (define_code_attr m_float [(float "float") (unsigned_float "ufloat")]) (define_code_attr s_float [(float "") (unsigned_float "uns")]) +;; This iterator and attribute allow FP-to-integer rounding of two types +;; to be generated from one template. +(define_int_iterator ANY_ROUND [UNSPEC_CEIL UNSPEC_FLOOR]) +(define_int_attr m_round [(UNSPEC_CEIL "ceil") (UNSPEC_FLOOR "floor")]) + ;; Attributes. @@ -1168,12 +1175,7 @@ (any_fix:SI (mult:S