Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2228196/?format=api
{ "id": 2228196, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2228196/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260425161006.3588504-1-yoshinori.sato@nifty.com/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/1.1/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null }, "msgid": "<20260425161006.3588504-1-yoshinori.sato@nifty.com>", "date": "2026-04-25T16:10:03", "name": "[RFC,v3] RX: enable LRA is default", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "01543e6bd1975e0ae0423b6c543fadbbcd7cd71f", "submitter": { "id": 91050, "url": "http://patchwork.ozlabs.org/api/1.1/people/91050/?format=api", "name": "Yoshinori Sato", "email": "yoshinori.sato@nifty.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260425161006.3588504-1-yoshinori.sato@nifty.com/mbox/", "series": [ { "id": 501453, "url": "http://patchwork.ozlabs.org/api/1.1/series/501453/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=501453", "date": "2026-04-25T16:10:03", "name": "[RFC,v3] RX: enable LRA is default", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/501453/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2228196/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2228196/checks/", "tags": {}, "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=nifty.com header.i=@nifty.com header.a=rsa-sha256\n header.s=default-1th84yt82rvi header.b=Hb//FXOH;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=nifty.com header.i=@nifty.com header.a=rsa-sha256\n header.s=default-1th84yt82rvi header.b=Hb//FXOH", "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=nifty.com", "sourceware.org; spf=pass smtp.mailfrom=nifty.com", "server2.sourceware.org;\n arc=none smtp.remote-ip=106.153.226.42" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g2vvM48BLz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 26 Apr 2026 02:10:54 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 385714BB3BFC\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 25 Apr 2026 16:10:52 +0000 (GMT)", "from mta-snd-e10.mail.nifty.com (mta-snd-e10.mail.nifty.com\n [106.153.226.42])\n by sourceware.org (Postfix) with ESMTPS id 031FA4BAD177\n for <gcc-patches@gcc.gnu.org>; Sat, 25 Apr 2026 16:10:13 +0000 (GMT)", "from sakura.ysato.name by mta-snd-e10.mail.nifty.com with ESMTP\n id <20260425161010689.VPL.3198.sakura.ysato.name@nifty.com>;\n Sun, 26 Apr 2026 01:10:10 +0900", "from SIOS1075.constellations.internal (ZM005235.ppp.dion.ne.jp\n [222.8.5.235])\n by sakura.ysato.name (Postfix) with ESMTPSA id 33BFA1C00A4;\n Sun, 26 Apr 2026 01:10:10 +0900 (JST)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 385714BB3BFC", "OpenDKIM Filter v2.11.0 sourceware.org 031FA4BAD177" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 031FA4BAD177", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 031FA4BAD177", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777133415; cv=none;\n b=LIsh/YPS0Va1eUd+wK4uTtu1YLb8DodcwfcHb8tvP4LRML29DVXUm7xFBhdIrPzkH9ExYYPLG/lwXmLX2w3xB6hd86KqN1uzjIgQZ+wKOlTjZqpGXbLjYxDGM1uRZH9EBScR1NwpBxKUb+VcFExDDd2UZNPNXj8ZHcUlMstPA0I=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777133415; c=relaxed/simple;\n bh=6EONAuvT6YcpHMSLtxWk6neA648EbjBLVtSHZkFuPaQ=;\n h=From:To:Subject:Date:Message-ID:MIME-Version:DKIM-Signature;\n b=ZNsFyKoXGtuOxUvOxvqsjWrUqq3/ERw5Cp2YpxcuEJIFagk5jygI2RfTBYUCrsnnaAJ63qnHNmeUkZHB7H66YGSiKvGxq3pHpWsTSvDZWTJ1BHzRmHYXm83GxkIsFpYR/E4oFNGTtFzwe9XwyJiaYkQ/iFt12sTP+9L5+mGJl6k=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "From": "Yoshinori Sato <yoshinori.sato@nifty.com>", "To": "gcc-patches@gcc.gnu.org", "Cc": "Yoshinori Sato <yoshinori.sato@nifty.com>", "Subject": "[RFC PATCH v3] RX: enable LRA is default", "Date": "Sun, 26 Apr 2026 01:10:03 +0900", "Message-ID": "<20260425161006.3588504-1-yoshinori.sato@nifty.com>", "X-Mailer": "git-send-email 2.47.3", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com;\n s=default-1th84yt82rvi; t=1777133410;\n bh=VLC+mYGrnUp/bcOJo/PXDOTLKzcm2vHr8jc51LRI/Lo=;\n h=From:To:Cc:Subject:Date;\n b=Hb//FXOH8MBbz60dB780vwLU90zTxQGIk8EdasnE7lEcHz3WBI5lBJ25YffJA53Lf0GYj1dQ\n wnIJOZIQi7CsXoIxsY92Vh4sURkv/6EoXInfqdlccXmg+JWW6zj0Fw5Mepgh+AdXG5pnZN4jyz\n pLAQRDZIP3405LimJG/Xf6y8eXXzA1Sy7bJ+diO+olZbeL8e2W/62coosAjOc22uFKfj477k6q\n Ckkpg4f58u+yzYkrBEshiIqxSSvi1YIsb9ByfcSJc5inqsdI7pem8vtKDQQkoz7oGwFcpbNcWn\n OlFrCWU5Bi6LzZpA29F9CKvmy6fTaFK8v0AUoPepYIkWoOKA==", "X-BeenThere": "gcc-patches@gcc.gnu.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>", "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>", "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "Always enable LRA on RX targets.\nhttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=113948\n\nThe previous fix did not adequately address the LRA infinite loop issue.\nIt was discovered that the infinite loop was caused by the definition of\nthe register class.\nThe stack frame manipulation was not compatible with LRA register spills,\nso that part has also been corrected.\n\nv3 changes.\n- A complete solution to the LRA infinite loop.\n- I reverted the memory access cost adjustment because it no longer made sense.\n- revert adc and sbb.\n\nChangeLog:\n * gcc/config/rx/predicates.md (rx_double_src_operand): New.\n (rx_double_dest_operand): New.\n * gcc/config/rx/rx-protos.h (rx_split_double_move): New helper proto.\n (rx_relax_double_operands): Likewise.\n * gcc/config/rx/rx.cc (rx_legitimize_address): Add expand complex case\n\t(rx_gen_move_template): Fix operation size in unsigned extend.\n (rx_gen_move_template): Remove DImode and DFmode.\n\t(rx_get_stack_layout): Fix for frame size calculation.\n\t(rx_initial_elimination_offset): The calculation method has been changed to one that supports LRA.\n (rx_enable_lra): Remove.\n\t(rx_hard_regno_nregs): Rewrite.\n (rx_hard_regno_mode_ok): Add ATTRIBUTE_UNUSED.\n (rx_modes_tieable_p): Add int case.\n (rx_get_subword): New. Double word move helper.\n (rx_split_double_move): Likewise.\n (rx_relax_double_operands): Likewise.\n (TARGET_LRA_P): Remove.\n\t* gcc/config/rx/rx.h (reg_class): Add CC for all regsisters.\n\t(CLASS_MAX_NREGS): Remove.\n * gcc/config/rx/rx.md (mov<register_modes:mode>):\n\tReplace copy_to_mode_reg to force_reg.\n (movdi): Limit the arguments to make register allocation easier.\n (movdf): Likewise.\n (movdi_internal): New.\n (movdf_internal): New.\n (addsi3_pid): New. Handling UNSPEC_PID_ADDR.\n (adddi3): New. simplify implementation.\n (subdi3): Likewise.\n (addsi3_lra): New. alternative addptrsi3.\n (ashlsi3_lra): likewise.\n * gcc/config/rx/rx.opt (mlra): Remove.\n\nSigned-off-by: Yoshinori Sato <yoshinori.sato@nifty.com>\n---\n gcc/config/rx/predicates.md | 14 ++\n gcc/config/rx/rx-protos.h | 2 +\n gcc/config/rx/rx.cc | 190 ++++++++++++++++++--------\n gcc/config/rx/rx.h | 5 +-\n gcc/config/rx/rx.md | 263 ++++++++++++++++--------------------\n gcc/config/rx/rx.opt | 6 -\n 6 files changed, 266 insertions(+), 214 deletions(-)", "diff": "diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md\nindex aa926be31ac..37fd63b538a 100644\n--- a/gcc/config/rx/predicates.md\n+++ b/gcc/config/rx/predicates.md\n@@ -307,3 +307,17 @@\n (define_predicate \"rshift_operator\"\n (match_code \"ashiftrt,lshiftrt\")\n )\n+\n+;; DI and DF are expanded into multiple mov instructions,\n+;; so they require stronger constraints than regular move.\n+(define_predicate \"rx_double_src_operand\"\n+ (ior (and (match_code \"reg,subreg,const_int,const_double\")\n+ (match_operand 0 \"general_operand\"))\n+ (and (match_code \"mem\")\n+ (match_operand 0 \"rx_restricted_mem_operand\"))))\n+\n+(define_predicate \"rx_double_dest_operand\"\n+ (ior (and (match_code \"reg,subreg\")\n+ (match_operand 0 \"general_operand\"))\n+ (and (match_code \"mem\")\n+ (match_operand 0 \"rx_restricted_mem_operand\"))))\ndiff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h\nindex 829882b0bc8..5a36ef26948 100644\n--- a/gcc/config/rx/rx-protos.h\n+++ b/gcc/config/rx/rx-protos.h\n@@ -70,6 +70,8 @@ extern void rx_copy_reg_dead_or_unused_notes (rtx reg, const rtx_insn* src,\n \n extern bool rx_fuse_in_memory_bitop (rtx* operands, rtx_insn* curr_insn,\n \t\t\t\t rtx (*gen_insn)(rtx, rtx));\n+extern void rx_split_double_move (rtx* operands, machine_mode mode);\n+extern void rx_relax_double_operands (rtx* operands, machine_mode mode);\n \n /* Result value of rx_find_set_of_reg. */\n struct set_of_reg\ndiff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc\nindex 902e756a34e..4675cf6b286 100644\n--- a/gcc/config/rx/rx.cc\n+++ b/gcc/config/rx/rx.cc\n@@ -148,17 +148,41 @@ rx_legitimize_address (rtx x,\n \t\t rtx oldx ATTRIBUTE_UNUSED,\n \t\t machine_mode mode ATTRIBUTE_UNUSED)\n {\n+ rtx op0 = XEXP (x, 0);\n+ rtx op1 = XEXP (x, 1);\n+\n if (rx_pid_data_operand (x) == PID_UNENCODED)\n {\n rtx rv = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), x);\n return rv;\n }\n \n- if (GET_CODE (x) == PLUS\n- && GET_CODE (XEXP (x, 0)) == PLUS\n- && REG_P (XEXP (XEXP (x, 0), 0))\n- && REG_P (XEXP (x, 1)))\n- return force_reg (SImode, x);\n+ if (GET_CODE (x) == PLUS)\n+ {\n+ if (GET_CODE (op0) == PLUS && REG_P (XEXP (op0, 0)) &&\n+\t CONST_INT_P (op1))\n+\t{\n+\t rtx base = XEXP (op0, 0);\n+\t rtx index = XEXP (op0, 1);\n+\n+\t rtx new_base = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, op1));\n+\t return gen_rtx_PLUS (Pmode, new_base, index);\n+\t}\n+\n+ if (GET_CODE (op0) == MULT || GET_CODE (op0) == ASHIFT)\n+\top0 = force_reg (Pmode, op0);\n+\n+ if (GET_CODE (op1) == MULT || GET_CODE (op1) == ASHIFT)\n+\top1 = force_reg (Pmode, op1);\n+\n+ if (GET_CODE (op0) == PLUS)\n+\top0 = rx_legitimize_address (op0, op0, mode);\n+ if (GET_CODE (op1) == PLUS)\n+\top1 = rx_legitimize_address (op1, op1, mode);\n+\n+ if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))\n+\treturn gen_rtx_PLUS (Pmode, op0, op1);\n+ }\n \n return x;\n }\n@@ -970,7 +994,8 @@ rx_gen_move_template (rtx * operands, bool is_movu)\n rtx src = operands[1];\n \n /* Decide which extension, if any, should be given to the move instruction. */\n- switch (CONST_INT_P (src) ? GET_MODE (dest) : GET_MODE (src))\n+ /* When zero-extending, always check the size of the source. */\n+ switch ((is_movu || MEM_P(src)) ? GET_MODE (src) : GET_MODE(dest))\n {\n case E_QImode:\n /* The .B extension is not valid when\n@@ -984,10 +1009,9 @@ rx_gen_move_template (rtx * operands, bool is_movu)\n \t loading an immediate into a register. */\n \textension = \".W\";\n break;\n- case E_DFmode:\n- case E_DImode:\n case E_SFmode:\n case E_SImode:\n+ gcc_assert(! is_movu);\n extension = \".L\";\n break;\n case E_VOIDmode:\n@@ -1025,18 +1049,8 @@ rx_gen_move_template (rtx * operands, bool is_movu)\n else\n dst_template = \"%0\";\n \n- if (GET_MODE (dest) == DImode || GET_MODE (dest) == DFmode)\n- {\n- gcc_assert (! is_movu);\n-\n- if (REG_P (src) && REG_P (dest) && (REGNO (dest) == REGNO (src) + 1))\n-\tsprintf (out_template, \"mov.L\\t%%H1, %%H0 ! mov.L\\t%%1, %%0\");\n- else\n-\tsprintf (out_template, \"mov.L\\t%%1, %%0 ! mov.L\\t%%H1, %%H0\");\n- }\n- else\n- sprintf (out_template, \"%s%s\\t%s, %s\", is_movu ? \"movu\" : \"mov\",\n-\t extension, src_template, dst_template);\n+ sprintf (out_template, \"%s%s\\t%s, %s\", is_movu ? \"movu\" : \"mov\",\n+\t extension, src_template, dst_template);\n return out_template;\n }\n \f\n@@ -1568,12 +1582,9 @@ rx_get_stack_layout (unsigned int * lowest,\n * register_mask = 0;\n }\n \n- * frame_size = rx_round_up\n- (get_frame_size (), STACK_BOUNDARY / BITS_PER_UNIT);\n-\n- if (crtl->args.size > 0)\n- * frame_size += rx_round_up\n- (crtl->args.size, STACK_BOUNDARY / BITS_PER_UNIT);\n+ * frame_size = rx_round_up (\n+ get_frame_size () + crtl->args.pretend_args_size,\n+ STACK_BOUNDARY / BITS_PER_UNIT);\n \n * stack_size = rx_round_up\n (crtl->outgoing_args_size, STACK_BOUNDARY / BITS_PER_UNIT);\n@@ -2221,30 +2232,27 @@ rx_initial_elimination_offset (int from, int to)\n unsigned int frame_size;\n unsigned int stack_size;\n unsigned int mask;\n+ unsigned int saved_regs_size = 0;\n \n rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);\n \n- if (from == ARG_POINTER_REGNUM)\n- {\n- /* Extend the computed size of the stack frame to\n-\t include the registers pushed in the prologue. */\n- if (low)\n-\tframe_size += ((high - low) + 1) * UNITS_PER_WORD;\n- else\n-\tframe_size += bit_count (mask) * UNITS_PER_WORD;\n-\n- /* Remember to include the return address. */\n- frame_size += 1 * UNITS_PER_WORD;\n+ if (mask != 0)\n+ /* multiple push reg */\n+ saved_regs_size = bit_count (mask) * UNITS_PER_WORD;\n+ else if (low != 0)\n+ /* pushm low - high */\n+ saved_regs_size = (high - low + 1) * UNITS_PER_WORD;\n \n+ if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)\n+ return stack_size;\n+ else if (from == ARG_POINTER_REGNUM)\n+ {\n if (to == FRAME_POINTER_REGNUM)\n-\treturn frame_size;\n-\n- gcc_assert (to == STACK_POINTER_REGNUM);\n- return frame_size + stack_size;\n+\treturn frame_size + saved_regs_size + 4;\n+ else if (to == STACK_POINTER_REGNUM)\n+\treturn frame_size + stack_size + saved_regs_size + 4;\n }\n-\n- gcc_assert (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM);\n- return stack_size;\n+ gcc_unreachable ();\n }\n \n /* Decide if a variable should go into one of the small data sections. */\n@@ -3495,12 +3503,6 @@ rx_ok_to_inline (tree caller, tree callee)\n || lookup_attribute (\"gnu_inline\", DECL_ATTRIBUTES (callee)) != NULL_TREE;\n }\n \n-static bool\n-rx_enable_lra (void)\n-{\n- return TARGET_ENABLE_LRA;\n-}\n-\n rx_atomic_sequence::rx_atomic_sequence (const_tree fun_decl)\n {\n if (is_fast_interrupt_func (fun_decl) || is_interrupt_func (fun_decl))\n@@ -3611,13 +3613,13 @@ rx_fuse_in_memory_bitop (rtx* operands, rtx_insn* curr_insn,\n static unsigned int\n rx_hard_regno_nregs (unsigned int, machine_mode mode)\n {\n- return CLASS_MAX_NREGS (0, mode);\n+ return (GET_MODE_SIZE (mode) <= 4) ? 1 : (GET_MODE_SIZE (mode) + 3) / 4;\n }\n \n /* Implement TARGET_HARD_REGNO_MODE_OK. */\n \n static bool\n-rx_hard_regno_mode_ok (unsigned int regno, machine_mode)\n+rx_hard_regno_mode_ok (unsigned int regno, machine_mode mode ATTRIBUTE_UNUSED)\n {\n return REGNO_REG_CLASS (regno) == GR_REGS;\n }\n@@ -3627,7 +3629,9 @@ rx_hard_regno_mode_ok (unsigned int regno, machine_mode)\n static bool\n rx_modes_tieable_p (machine_mode mode1, machine_mode mode2)\n {\n- return ((GET_MODE_CLASS (mode1) == MODE_FLOAT\n+ return (GET_MODE_CLASS (mode1) == MODE_INT\n+\t && GET_MODE_CLASS (mode2) == MODE_INT)\n+ || ((GET_MODE_CLASS (mode1) == MODE_FLOAT\n \t || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)\n \t == (GET_MODE_CLASS (mode2) == MODE_FLOAT\n \t || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));\n@@ -3644,7 +3648,82 @@ rx_c_mode_for_floating_type (enum tree_index ti)\n return TARGET_64BIT_DOUBLES ? DFmode : SFmode;\n return default_mode_for_floating_type (ti);\n }\n+\n+static rtx\n+rx_get_subword (rtx op, machine_mode mode, int reg_offset)\n+{\n+ int mem_offset = reg_offset * 4;\n+ if (TARGET_BIG_ENDIAN_DATA)\n+ mem_offset = 4 - mem_offset;\n+\n+ if (MEM_P (op))\n+ {\n+ rtx addr = XEXP (op, 0);\n+ rtx new_addr = plus_constant (Pmode, addr, mem_offset);\n+ rtx new_mem = gen_rtx_MEM (SImode, new_addr);\n+ MEM_COPY_ATTRIBUTES (new_mem, op);\n+ return new_mem;\n+ }\n+\n+ if (REG_P (op) && REGNO (op) < FIRST_PSEUDO_REGISTER)\n+ return gen_rtx_REG (SImode, REGNO (op) + reg_offset);\n+\n+ return simplify_gen_subreg (SImode, op, mode, mem_offset);\n+}\n+\n+void\n+rx_split_double_move (rtx * operands, machine_mode mode)\n+{\n+ rtx dest = operands[0];\n+ rtx src = operands[1];\n+\n+ rtx real_dest = (GET_CODE (dest) == SUBREG) ? SUBREG_REG (dest) : dest;\n+ rtx real_src = (GET_CODE (src) == SUBREG) ? SUBREG_REG (src) : src;\n+\n+ rtx dest_low, dest_high, src_low, src_high;\n+\n+ src_low = rx_get_subword (MEM_P (real_src) ? real_src : src, mode, 0);\n+ src_high = rx_get_subword (MEM_P (real_src) ? real_src : src, mode, 1);\n+\n+ dest_low = rx_get_subword (MEM_P (real_dest) ? real_dest : dest, mode, 0);\n+ dest_high = rx_get_subword (MEM_P (real_dest) ? real_dest : dest, mode, 1);\n+\n+ if (REG_P (operands[0]) && reg_overlap_mentioned_p (dest_low, operands[1]))\n+ {\n+ emit_move_insn (dest_high, src_high);\n+ emit_move_insn (dest_low, src_low);\n+ }\n+ else\n+ {\n+ emit_move_insn (dest_low, src_low);\n+ emit_move_insn (dest_high, src_high);\n+ }\n+}\n+\n+void\n+rx_relax_double_operands(rtx * operands, machine_mode mode)\n+{\n+ if (MEM_P (operands[0]) && !rx_restricted_mem_operand (operands[0], mode))\n+ {\n+ rtx addr = XEXP (operands[0], 0);\n+ addr = force_reg (Pmode, addr);\n+ operands[0] = replace_equiv_address (operands[0], addr);\n+ }\n+\n+ if (MEM_P (operands[1]) && !rx_restricted_mem_operand (operands[1], mode))\n+ {\n+ rtx addr = XEXP (operands[1], 0);\n+ addr = force_reg (Pmode, addr);\n+ operands[1] = replace_equiv_address (operands[1], addr);\n+ }\n+\n+ if (MEM_P (operands[0]) && !REG_P (operands[1]))\n+ {\n+ operands[1] = force_reg (mode, operands[1]);\n+ }\n+}\n \f\n+\n #undef TARGET_NARROW_VOLATILE_BITFIELD\n #define TARGET_NARROW_VOLATILE_BITFIELD\t\trx_narrow_volatile_bitfield\n \n@@ -3786,16 +3865,13 @@ rx_c_mode_for_floating_type (enum tree_index ti)\n #undef TARGET_WARN_FUNC_RETURN\n #define TARGET_WARN_FUNC_RETURN \t\trx_warn_func_return\n \n-#undef TARGET_LRA_P\n-#define TARGET_LRA_P \t\t\t\trx_enable_lra\n-\n #undef TARGET_HARD_REGNO_NREGS\n #define TARGET_HARD_REGNO_NREGS\t\t\trx_hard_regno_nregs\n #undef TARGET_HARD_REGNO_MODE_OK\n #define TARGET_HARD_REGNO_MODE_OK\t\trx_hard_regno_mode_ok\n \n #undef TARGET_MODES_TIEABLE_P\n-#define TARGET_MODES_TIEABLE_P\t\t\trx_modes_tieable_p\n+#define TARGET_MODES_TIEABLE_P rx_modes_tieable_p\n \n #undef TARGET_RTX_COSTS\n #define TARGET_RTX_COSTS rx_rtx_costs\ndiff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h\nindex a363a3caaad..f78c103fcb2 100644\n--- a/gcc/config/rx/rx.h\n+++ b/gcc/config/rx/rx.h\n@@ -195,13 +195,10 @@ enum reg_class\n {\t\t\t\t\t\t\t\\\n { 0x00000000 },\t/* No registers, */\t\t\\\n { 0x0000ffff },\t/* Integer registers. */\t\\\n- { 0x0000ffff }\t/* All registers. */\t\t\\\n+ { 0x0001ffff }\t/* All registers. */\t\t\\\n }\n \n #define N_REG_CLASSES\t\t\t(int) LIM_REG_CLASSES\n-#define CLASS_MAX_NREGS(CLASS, MODE) ((GET_MODE_SIZE (MODE) \\\n-\t\t\t\t\t + UNITS_PER_WORD - 1) \\\n-\t\t\t\t\t / UNITS_PER_WORD)\n \n #define GENERAL_REGS\t\t\tGR_REGS\n #define BASE_REG_CLASS \t\tGR_REGS\ndiff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md\nindex 808dfc8b35a..0cccb342ff8 100644\n--- a/gcc/config/rx/rx.md\n+++ b/gcc/config/rx/rx.md\n@@ -575,17 +575,11 @@\n \"\"\n {\n if (MEM_P (operands[0]) && MEM_P (operands[1]))\n- operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);\n+ operands[1] = force_reg (<register_modes:MODE>mode, operands[1]);\n operands[0] = rx_maybe_pidify_operand (operands[0], 0);\n operands[1] = rx_maybe_pidify_operand (operands[1], 0);\n- if (GET_CODE (operands[0]) != REG\n-\t&& GET_CODE (operands[1]) == PLUS)\n- operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);\n- if (GET_CODE (operands[1]) == PLUS && GET_MODE (operands[1]) == SImode)\n- {\n- emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), XEXP (operands[1], 1)));\n- DONE;\n- }\n+ if (MEM_P (operands[0]) && GET_CODE (operands[1]) == PLUS)\n+ operands[1] = force_reg (<register_modes:MODE>mode, operands[1]);\n if (CONST_INT_P (operand1)\n && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))\n FAIL;\n@@ -603,6 +597,58 @@\n (set_attr \"timings\" \"11,11,11,11,11,12,11,11,11,11,11,11\")]\n )\n \n+(define_expand \"movdi\"\n+ [(set (match_operand:DI 0 \"nonimmediate_operand\" \"\")\n+ (match_operand:DI 1 \"general_operand\" \"\"))]\n+ \"\"\n+ {\n+ rx_relax_double_operands(operands, DImode);\n+\n+ emit_insn (gen_movdi_internal (operands[0], operands[1]));\n+ DONE;\n+ }\n+)\n+\n+(define_insn_and_split \"movdi_internal\"\n+ [(set (match_operand:DI 0 \"rx_double_dest_operand\" \"=r,r,m\")\n+ (match_operand:DI 1 \"rx_double_src_operand\" \"ri,m,r\"))]\n+ \"\"\n+ \"#\"\n+ \"reload_completed\"\n+ [(const_int 0)]\n+ {\n+ rx_split_double_move (operands, DImode);\n+ DONE;\n+ }\n+ [(set_attr \"length\" \"8\")]\n+)\n+\n+(define_expand \"movdf\"\n+ [(set (match_operand:DF 0 \"nonimmediate_operand\" \"\")\n+ (match_operand:DF 1 \"general_operand\" \"\"))]\n+ \"\"\n+ {\n+ rx_relax_double_operands(operands, DFmode);\n+\n+ emit_insn (gen_movdf_internal (operands[0], operands[1]));\n+ DONE;\n+ }\n+)\n+\n+(define_insn_and_split \"movdf_internal\"\n+ [(set (match_operand:DF 0 \"rx_double_dest_operand\" \"=r,r,m\")\n+ (match_operand:DF 1 \"rx_double_src_operand\" \"rF,m,r\"))]\n+ \"\"\n+ \"#\"\n+ \"reload_completed\"\n+ [(const_int 0)]\n+ {\n+ rx_split_double_move (operands, DFmode);\n+ DONE;\n+ }\n+ [(set_attr \"length\" \"8\")]\n+)\n+\n (define_insn \"extend<small_int_modes:mode>si2\"\n [(set (match_operand:SI 0 \"register_operand\" \"=r,r\")\n (sign_extend:SI (match_operand:small_int_modes\n@@ -974,6 +1020,29 @@\n (set_attr \"length\" \"3,4,5,6,7,6\")]\n )\n \n+(define_insn \"addsi3_pid\"\n+ [(set (match_operand:SI 0 \"register_operand\" \"=r\")\n+ (plus:SI (match_operand:SI 1 \"register_operand\" \"%0\")\n+ (const:SI (unspec:SI [(match_operand:SI 2 \"immediate_operand\" \"i\")] UNSPEC_PID_ADDR))))]\n+ \"\"\n+ \"add\\t%2, %0\"\n+ [(set_attr \"length\" \"6\")\n+ (set_attr \"timings\" \"11\")]\n+)\n+\n+(define_insn \"adddi3\"\n+ [(set (match_operand:DI 0 \"register_operand\" \"=r,r,r\")\n+\t(plus:DI (match_operand:DI 1 \"register_operand\" \"%0,0,0\")\n+\t\t (match_operand:DI 2 \"rx_source_operand\" \"r,i,Q\")))\n+ (clobber (reg:CC CC_REG))]\n+ \"\"\n+ {\n+ return \"add\\t%L2, %L0\\n\\tadc\\t%H2, %H0\";\n+ }\n+ [(set_attr \"length\" \"6\")\n+ (set_attr \"timings\" \"22\")]\n+)\n+\n ;; Peepholes to match:\n ;; (set (reg A) (reg B))\n ;; (set (CC) (compare:CC (reg A/reg B) (const_int 0)))\n@@ -1007,93 +1076,6 @@\n \t\t (plus:SI (match_dup 1) (const_int 0)))])]\n )\n \n-(define_expand \"adddi3\"\n- [(set (match_operand:DI 0 \"register_operand\")\n-\t(plus:DI (match_operand:DI 1 \"register_operand\")\n-\t\t (match_operand:DI 2 \"rx_source_operand\")))]\n- \"\"\n-{\n- rtx op0l, op0h, op1l, op1h, op2l, op2h;\n-\n- op0l = gen_lowpart (SImode, operands[0]);\n- op1l = gen_lowpart (SImode, operands[1]);\n- op2l = gen_lowpart (SImode, operands[2]);\n- op0h = gen_highpart (SImode, operands[0]);\n- op1h = gen_highpart (SImode, operands[1]);\n- op2h = gen_highpart_mode (SImode, DImode, operands[2]);\n-\n- emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));\n- DONE;\n-})\n-\n-(define_insn_and_split \"adddi3_internal\"\n- [(set (match_operand:SI 0 \"register_operand\" \"=&r\")\n-\t(plus:SI (match_operand:SI 2 \"register_operand\" \"r\")\n-\t\t (match_operand:SI 3 \"rx_source_operand\" \"riQ\")))\n- (set (match_operand:SI 1 \"register_operand\" \"=r\")\n-\t(plus:SI\n-\t (plus:SI\n-\t (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))\n-\t (match_operand:SI 4 \"register_operand\" \"%1\"))\n-\t (match_operand:SI 5 \"rx_source_operand\" \"riQ\")))\n- (clobber (match_scratch:SI 6 \"=&r\"))\n- (clobber (reg:CC CC_REG))]\n- \"\"\n- \"#\"\n- \"reload_completed\"\n- [(const_int 0)]\n-{\n- rtx op0l = operands[0];\n- rtx op0h = operands[1];\n- rtx op1l = operands[2];\n- rtx op2l = operands[3];\n- rtx op1h = operands[4];\n- rtx op2h = operands[5];\n- rtx scratch = operands[6];\n- rtx x;\n-\n- if (reg_overlap_mentioned_p (op0l, op1h))\n- {\n- emit_move_insn (scratch, op0l);\n- op1h = scratch;\n- if (reg_overlap_mentioned_p (op0l, op2h))\n-\top2h = scratch;\n- }\n- else if (reg_overlap_mentioned_p (op0l, op2h))\n- {\n- emit_move_insn (scratch, op0l);\n- op2h = scratch;\n- }\n-\n- if (rtx_equal_p (op0l, op1l))\n- ;\n- /* It is preferable that op0l == op1l... */\n- else if (rtx_equal_p (op0l, op2l))\n- x = op1l, op1l = op2l, op2l = x;\n- /* ... but it is only a requirement if op2l == MEM. */\n- else if (MEM_P (op2l))\n- {\n- /* Let's hope that we still have a scratch register free. */\n- gcc_assert (op1h != scratch);\n- emit_move_insn (scratch, op2l);\n- op2l = scratch;\n- }\n-\n- emit_insn (gen_addsi3_flags (op0l, op1l, op2l));\n-\n- if (rtx_equal_p (op0h, op1h))\n- ;\n- else if (rtx_equal_p (op0h, op2h))\n- x = op1h, op1h = op2h, op2h = x;\n- else\n- {\n- emit_move_insn (op0h, op1h);\n- op1h = op0h;\n- }\n- emit_insn (gen_adc_internal (op0h, op1h, op2h));\n- DONE;\n-})\n-\n (define_insn_and_split \"andsi3\"\n [(set (match_operand:SI 0 \"register_operand\" \"=r,r,r,r,r,r,r,r,r\")\n \t(and:SI (match_operand:SI 1 \"register_operand\" \"%0,0,0,0,0,0,r,r,0\")\n@@ -1694,45 +1676,18 @@\n (set_attr \"length\" \"3,6\")]\n )\n \n-(define_expand \"subdi3\"\n- [(set (match_operand:DI 0 \"register_operand\")\n-\t(minus:DI (match_operand:DI 1 \"register_operand\")\n-\t\t (match_operand:DI 2 \"register_operand\")))]\n- \"\"\n-{\n- rtx op0l, op0h, op1l, op1h, op2l, op2h;\n-\n- op0l = gen_lowpart (SImode, operands[0]);\n- op1l = gen_lowpart (SImode, operands[1]);\n- op2l = gen_lowpart (SImode, operands[2]);\n- op0h = gen_highpart (SImode, operands[0]);\n- op1h = gen_highpart (SImode, operands[1]);\n- op2h = gen_highpart_mode (SImode, DImode, operands[2]);\n-\n- emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));\n- DONE;\n-})\n-\n-(define_insn_and_split \"subdi3_internal\"\n- [(set (match_operand:SI 0 \"register_operand\" \"=&r,&r\")\n-\t(minus:SI (match_operand:SI 2 \"register_operand\" \" 0, r\")\n-\t\t (match_operand:SI 3 \"rx_compare_operand\" \"rQ, r\")))\n- (set (match_operand:SI 1 \"register_operand\" \"= r, r\")\n-\t(minus:SI\n-\t (minus:SI\n-\t (match_operand:SI 4 \"register_operand\" \" 1, 1\")\n-\t (match_operand:SI 5 \"rx_compare_operand\" \" rQ,rQ\"))\n-\t (gtu:SI (match_dup 3) (match_dup 2))))\n+(define_insn \"subdi3\"\n+ [(set (match_operand:DI 0 \"register_operand\" \"=r,r\")\n+\t(minus:DI (match_operand:DI 1 \"register_operand\" \"0,0\")\n+\t\t (match_operand:DI 2 \"rx_source_operand\" \"r,Q\")))\n (clobber (reg:CC CC_REG))]\n \"\"\n- \"#\"\n- \"reload_completed\"\n- [(const_int 0)]\n-{\n- emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));\n- emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));\n- DONE;\n-})\n+ {\n+ return \"sub\\t%L2, %L0\\n\\tsbb\\t%H2, %H0\";\n+ }\n+ [(set_attr \"length\" \"6\")\n+ (set_attr \"timings\" \"22\")]\n+)\n \n (define_insn_and_split \"xorsi3\"\n [(set (match_operand:SI 0 \"register_operand\" \"=r,r,r,r,r,r\")\n@@ -1936,6 +1891,7 @@\n [(set_attr \"timings\" \"33\")\n (set_attr \"length\" \"5\")] ;; This length is corrected in rx_adjust_insn_length\n )\n+\n \f\n ;; Floating Point Instructions\n \n@@ -2870,20 +2826,33 @@\n \"\"\n )\n \n-(define_insn \"movdi\"\n- [(set (match_operand:DI 0 \"nonimmediate_operand\" \"=rm\")\n- (match_operand:DI 1 \"general_operand\" \"rmi\"))]\n- \"TARGET_ENABLE_LRA\"\n- { return rx_gen_move_template (operands, false); }\n- [(set_attr \"length\" \"16\")\n- (set_attr \"timings\" \"22\")]\n+;; RX does not allow addition without destroying CC.\n+;; As an alternative to addptrsi3, we define addsi3, which hides changes to CC.\n+(define_insn_and_split \"*addsi3_lra\"\n+ [(set (match_operand:SI 0 \"register_operand\" \"=r,r\")\n+ (plus:SI (match_operand:SI 1 \"register_operand\" \"0,r\")\n+ (match_operand:SI 2 \"rx_source_operand\" \"ri,ri\")))]\n+ \"lra_in_progress || reload_completed\"\n+ \"#\"\n+ \"&& reload_completed\"\n+ [(parallel [\n+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))\n+ (clobber (reg:CC 16))\n+ ])]\n )\n \n-(define_insn \"movdf\"\n- [(set (match_operand:DF 0 \"nonimmediate_operand\" \"=rm\")\n- (match_operand:DF 1 \"general_operand\" \"rmi\"))]\n- \"TARGET_ENABLE_LRA\"\n- { return rx_gen_move_template (operands, false); }\n- [(set_attr \"length\" \"16\")\n- (set_attr \"timings\" \"22\")]\n+(define_insn_and_split \"*ashlsi3_lra\"\n+ [(set (match_operand:SI 0 \"register_operand\" \"=r,r,r\")\n+ (ashift:SI (match_operand:SI 1 \"register_operand\" \"%0,0,r\")\n+ (match_operand:SI 2 \"rx_shift_operand\" \"r,i,i\")))]\n+ \"lra_in_progress || reload_completed\"\n+ \"@\n+ shll\\t%2, %0\n+ shll\\t%2, %0\n+ shll\\t%2, %1, %0\"\n+ \"&& reload_completed\"\n+ [(parallel [\n+ (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))\n+ (clobber (reg:CC CC_REG))\n+ ])]\n )\ndiff --git a/gcc/config/rx/rx.opt b/gcc/config/rx/rx.opt\nindex 5caad487389..0e4c9872356 100644\n--- a/gcc/config/rx/rx.opt\n+++ b/gcc/config/rx/rx.opt\n@@ -128,12 +128,6 @@ Enable the use the standard RX ABI where all stacked function arguments are natu\n \n ;---------------------------------------------------\n \n-mlra\n-Target Mask(ENABLE_LRA)\n-Enable the use of the LRA register allocator.\n-\n-;---------------------------------------------------\n-\n mallow-string-insns\n Target Var(rx_allow_string_insns) Init(1)\n Enables or disables the use of the SMOVF, SMOVB, SMOVU, SUNTIL, SWHILE and RMPA instructions. Enabled by default.\n", "prefixes": [ "RFC", "v3" ] }