Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2231246/?format=api
{ "id": 2231246, "url": "http://patchwork.ozlabs.org/api/patches/2231246/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/CAMe9rOrG=Pk9YsEVyFHCi302Y1pi8VOSxZGesruDqmO8ngOasw@mail.gmail.com/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/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, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<CAMe9rOrG=Pk9YsEVyFHCi302Y1pi8VOSxZGesruDqmO8ngOasw@mail.gmail.com>", "list_archive_url": null, "date": "2026-04-30T12:28:53", "name": "x86: Implement TARGET_FNTYPE_ABI", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "e93cfbfffe041393bbdfee9421f6544628367fe2", "submitter": { "id": 4387, "url": "http://patchwork.ozlabs.org/api/people/4387/?format=api", "name": "H.J. Lu", "email": "hjl.tools@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/CAMe9rOrG=Pk9YsEVyFHCi302Y1pi8VOSxZGesruDqmO8ngOasw@mail.gmail.com/mbox/", "series": [ { "id": 502296, "url": "http://patchwork.ozlabs.org/api/series/502296/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=502296", "date": "2026-04-30T12:28:53", "name": "x86: Implement TARGET_FNTYPE_ABI", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/502296/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2231246/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2231246/checks/", "tags": {}, "related": [], "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=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=U6xmWdi8;\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=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=U6xmWdi8", "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "sourceware.org; spf=pass smtp.mailfrom=gmail.com", "server2.sourceware.org;\n arc=pass smtp.remote-ip=209.85.215.180" ], "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 4g5tmJ3bhhz1yHZ\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 30 Apr 2026 22:30:08 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id A280A436F7C2\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 30 Apr 2026 12:30:06 +0000 (GMT)", "from mail-pg1-f180.google.com (mail-pg1-f180.google.com\n [209.85.215.180])\n by sourceware.org (Postfix) with ESMTPS id 6228D4371D70\n for <gcc-patches@gcc.gnu.org>; Thu, 30 Apr 2026 12:29:32 +0000 (GMT)", "by mail-pg1-f180.google.com with SMTP id\n 41be03b00d2f7-c736261ee8dso288454a12.1\n for <gcc-patches@gcc.gnu.org>; Thu, 30 Apr 2026 05:29:32 -0700 (PDT)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org A280A436F7C2", "OpenDKIM Filter v2.11.0 sourceware.org 6228D4371D70" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 6228D4371D70", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 6228D4371D70", "ARC-Seal": [ "i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1777552172; cv=pass;\n b=pqi0WCTmkQ95utid9WRnCCPyrU6LpDFEZmPLla2s4GqX/WogX9YHFDzy+Ox2e0IHenhE1AdUhA0ifMDEr1pPCiGhrkm6nyE+U2N38lAx7gTnKWKnxitSdSDsC75Y82pCpkXuTG2H03SkNirCJE1JFbQKpynL9sE5w+kCZnEsnwY=", "i=1; a=rsa-sha256; t=1777552171; cv=none;\n d=google.com; s=arc-20240605;\n b=TUOXTiEaZPa/o4yWPz9ajCWod7rCE6DW6vemcUM6IMDYgPku5WgL5vnbhP+lagIedW\n btQbgjgdaz46kB9YrEx+gKCxJmgbC5D2dckoZEEdnTprrOuFowo2uZQpu0X/5XEC8TYm\n UpA3YQ+n8xTzcphRgsnjAEebC3DiICneNc+H/SP427LdZKnmJMSBDETw+w7lBv3IZwgs\n LwQagb3yfQrg9t5cKI863ACLLHM9JYjoB4+8nnhrTdB4EtpCO+XLdXRGPwtcnkMioJnJ\n mv5CnhqDs1oFH5GVw57VWgxHyJlFzv/gxoa5mP1fkxU9/azSduWlAyUgEQhpRthC2kos\n RwlA==" ], "ARC-Message-Signature": [ "i=2; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777552172; c=relaxed/simple;\n bh=BLUP8wjhbcqEEAAFEWH4cmjFG/uN1G+RVzgWWPnIj9U=;\n h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To;\n b=kmhngsymREj7N62TYgyUKZ2ctrMJiP0ocpLJXW0zmewJUwSUBRAKYeGs8kti1TZyw5oSFLxBM9ylfpxNAFlvsx7maaC027GmgTHShdD68EASqXWxpbgwwAtaxkZwS0D4Zo9q5iuPAbQxoWku45mNwKgKa3QrVobDzskQVayL67k=", "i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com;\n s=arc-20240605;\n h=to:subject:message-id:date:from:mime-version:dkim-signature;\n bh=ee/HzurH3GR8Ybq5eB2XvpA8Eq6ZS81HvRfwR2oczOI=;\n fh=83snE5t1iR5QXMcAAhy1f7NFmMeqVCeXIkq3dVlORPM=;\n b=fFCDVzeCvfF0R2GljmJcKvHaD5TajSmnO0on37IBfyFxqaNN3FL5QndBPKShUhv0xo\n HjC88i8+kwp+mGrg9ZP4IYuoTTDOmfCyfQI+bPNXOsfbXOiMNCXZ2xA8Y5UtMlsEL+Hm\n 5i1FH8n9+cFCCFbf8W8HItVHJLIdYA+1mDQgMYOTy4tqsf8GgmGqg8j14n6wGToZYFK+\n +XFhsJwusDVSJ9BeJXrzDVAQVibzSm8H2tBjwJryI38pfVzkJJyEGShAxwV+n/Moz98f\n /3KYZmjr0513YJPvvFnNvag7DqCxOPYPS8/MbjKRbEl1xT+iMswAsMOiIpNRaCCjjwjM\n dwhw==; darn=gcc.gnu.org" ], "ARC-Authentication-Results": [ "i=2; server2.sourceware.org", "i=1; mx.google.com; arc=none" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777552171; x=1778156971; darn=gcc.gnu.org;\n h=to:subject:message-id:date:from:mime-version:from:to:cc:subject\n :date:message-id:reply-to;\n bh=ee/HzurH3GR8Ybq5eB2XvpA8Eq6ZS81HvRfwR2oczOI=;\n b=U6xmWdi8oHdJ2rVNnGY+8pOo+8p1bk4ZD+z6G4IRfy549QB0av7rbR06ZKxTpxrqn0\n s0i19E5b7oowSPKIRmDIjqhzvGILNre67YyaneglM558yaM+OORT2aBedGv5WOnj3E94\n sYIWAOBD/ThAgZUHUQBpRYPEhvhinEleDsBD6qZV0j8+mxx196AYdjk+2QZTQwiP2mCn\n Xj/g8dWB5Gm256sNDk3Ai5Or1Egh/3cHCcCN+8XsM5MQyCMOcZJs3VAkZS84q2trO0nJ\n xAfdSnM4rG/sQl2hk56p5zj6IZeiJPKhkQ3uYF0glE4HeFwU4jjwdZ5CpLs0az1fd9w/\n ktSw==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777552171; x=1778156971;\n h=to:subject:message-id:date:from:mime-version:x-gm-gg\n :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n bh=ee/HzurH3GR8Ybq5eB2XvpA8Eq6ZS81HvRfwR2oczOI=;\n b=XFLE90RH7CLOHWCm6tz6tnEDegE1f1SH7TMe97uzQsJhGsQZ/5ovnCPr+dlhcffkUo\n /6JWBw+O36kXLkdkhKeJytVjwjwRB2ZBvG8ARCwoyBpV9B1wVDYs7vSGyvwiAmnBvqH4\n dV7gKuIsBFZvEdv1rW4YktC3kGU3XH9RneOpj+Px8tJ2Zusg80bKtvb2Y6PTcvPzru+C\n 0RatEi8yG5bgN/fyEyP0B7J1A+bGIOYdy1Cnfc87PXhRx+b5hKuoC4dIfalBhurJOm1Y\n HRMqG64Gq84xCK7QEZTP5guOsfSjmsB6CVciPQjDZJmrXADff6Y4Nx+4V8wA0cub7E/M\n 3gfA==", "X-Gm-Message-State": "AOJu0Yz8AbANP6GrEObm5YV7XZb80PvWJ9+syENfDBToEuG5ib+S2q0S\n wnmabkq4bEzEgziEchBDbOvskNQwu9d7RFDhXqOvrIpNjPouI4vcqZVuq2yzpN+Umi8QEJq8P+Q\n vdOIQorstzFBPhuQJoArbkZK2z0I4wD6UXzbX2lII30Qu", "X-Gm-Gg": "AeBDievaDHCWq6HEDb83TK7QJebI+M5KyyVQeV+LrNz395/BF+0wW7X3cZtjl5Ra3aw\n Z1VRfsCN7rEPPejASVpDEZEn9tdgPQ4FN1G3kkW88ZUknkgV14pR3wKMevUeiXxWcaic/uTWf3/\n K1z/HiBa0RJtHwWlrIty1XsOMwqlPySHpqDXBgRRLX2stqMH2OFbmcD4CaD+pHYMCqKJVKpAp9+\n 160IEWhR34u5zpmy926YNMh7BQrYzDYtfVSctyUyo4woiGn5kWjy/B5RjiDzvj3drK8V84sGfgm\n hTERtko6Tz9EgcIWAw==", "X-Received": "by 2002:a05:6a21:6d9c:b0:3a1:90ef:7e31 with SMTP id\n adf61e73a8af0-3a3cf8c2cc4mr3248481637.54.1777552170857; Thu, 30 Apr 2026\n 05:29:30 -0700 (PDT)", "MIME-Version": "1.0", "From": "\"H.J. Lu\" <hjl.tools@gmail.com>", "Date": "Thu, 30 Apr 2026 20:28:53 +0800", "X-Gm-Features": "AVHnY4K9qoBq47TQi3XMMveMhvkV1fdIkT7tf3Mxx8HNZ2MplMuTq_hlOM4_IcU", "Message-ID": "\n <CAMe9rOrG=Pk9YsEVyFHCi302Y1pi8VOSxZGesruDqmO8ngOasw@mail.gmail.com>", "Subject": "[PATCH] x86: Implement TARGET_FNTYPE_ABI", "To": "GCC Patches <gcc-patches@gcc.gnu.org>, Uros Bizjak <ubizjak@gmail.com>,\n Hongtao Liu <hongtao.liu@intel.com>", "Content-Type": "multipart/mixed; boundary=\"000000000000b6d5ed0650ac9d12\"", "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": "Implement TARGET_FNTYPE_ABI to avoid spills of callee-saved registers\nwhen calling functions with no_caller_saved_registers attribute.\n\n1. For functions with no_callee_saved_registers attribute, frame register\nis preserved to mitigate PR target/114116. MMX and x87 registers are\npreserved if MMX and x87 aren't enabled.\n2. For functions with no_caller_saved_registers attribute, MMX and x87\nregisters aren't preserved since saving and restoring registers doesn't\ninclude MMX nor x87 registers.\n3. Don't mark disabled registers as call used.\n\ngcc/\n\nPR target/124798\n* config/i386/i386.cc (ix86_conditional_register_usage): Don't\nmark disabled registers as call used.\n(ix86_no_callee_saved_abi): New function.\n(ix86_no_caller_saved_abi_void): Likewise.\n(ix86_no_caller_saved_abi_ax): Likewise.\n(ix86_no_caller_saved_abi_ax_dx): Likewise.\n(ix86_no_caller_saved_abi_xmm0): Likewise.\n(ix86_no_caller_saved_abi_xmm0_xmm1): Likewise.\n(ix86_fntype_abi): Likewise.\n(ix86_hard_regno_call_part_clobbered): Handle newly added ABIs.\n(TARGET_FNTYPE_ABI): New.\n* config/i386/i386.md: Add ABI_NO_CALLEE_SAVED,\nABI_NO_CALLER_SAVED_RETURN_VOID, ABI_NO_CALLER_SAVED_RETURN_AX,\nABI_NO_CALLER_SAVED_RETURN_AX_DX, ABI_NO_CALLER_SAVED_RETURN_XMM0\nand ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1.\n\ngcc/testsuite/\n\nPR target/124798\n* gcc.target/i386/no-callee-saved-2.c: Check frame register isn't\nsaved or restored in 64-bit mode.\n* gcc.target/i386/preserve-none-7.c: Likewise.\n* gcc.target/i386/no-caller-saved-1.c: New test.\n* gcc.target/i386/no-caller-saved-2.c: Likewise.\n* gcc.target/i386/no-caller-saved-3.c: Likewise.\n* gcc.target/i386/no-caller-saved-4.c: Likewise.\n* gcc.target/i386/no-caller-saved-5.c: Likewise.\n* gcc.target/i386/no-caller-saved-6.c: Likewise.\n* gcc.target/i386/no-caller-saved-7.c: Likewise.", "diff": "From f0d2b28e80fc35f100a25d4da51982c1b8a733d6 Mon Sep 17 00:00:00 2001\nFrom: \"H.J. Lu\" <hjl.tools@gmail.com>\nDate: Tue, 14 Apr 2026 18:37:20 +0800\nSubject: [PATCH] x86: Implement TARGET_FNTYPE_ABI\n\nImplement TARGET_FNTYPE_ABI to avoid spills of callee-saved registers\nwhen calling functions with no_caller_saved_registers attribute.\n\n1. For functions with no_callee_saved_registers attribute, frame register\nis preserved to mitigate PR target/114116. MMX and x87 registers are\npreserved if MMX and x87 aren't enabled.\n2. For functions with no_caller_saved_registers attribute, MMX and x87\nregisters aren't preserved since saving and restoring registers doesn't\ninclude MMX nor x87 registers.\n3. Don't mark disabled registers as call used.\n\ngcc/\n\n\tPR target/124798\n\t* config/i386/i386.cc (ix86_conditional_register_usage): Don't\n\tmark disabled registers as call used.\n\t(ix86_no_callee_saved_abi): New function.\n\t(ix86_no_caller_saved_abi_void): Likewise.\n\t(ix86_no_caller_saved_abi_ax): Likewise.\n\t(ix86_no_caller_saved_abi_ax_dx): Likewise.\n\t(ix86_no_caller_saved_abi_xmm0): Likewise.\n\t(ix86_no_caller_saved_abi_xmm0_xmm1): Likewise.\n\t(ix86_fntype_abi): Likewise.\n\t(ix86_hard_regno_call_part_clobbered): Handle newly added ABIs.\n\t(TARGET_FNTYPE_ABI): New.\n\t* config/i386/i386.md: Add ABI_NO_CALLEE_SAVED,\n\tABI_NO_CALLER_SAVED_RETURN_VOID, ABI_NO_CALLER_SAVED_RETURN_AX,\n\tABI_NO_CALLER_SAVED_RETURN_AX_DX, ABI_NO_CALLER_SAVED_RETURN_XMM0\n\tand ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1.\n\ngcc/testsuite/\n\n\tPR target/124798\n\t* gcc.target/i386/no-callee-saved-2.c: Check frame register isn't\n\tsaved or restored in 64-bit mode.\n\t* gcc.target/i386/preserve-none-7.c: Likewise.\n\t* gcc.target/i386/no-caller-saved-1.c: New test.\n\t* gcc.target/i386/no-caller-saved-2.c: Likewise.\n\t* gcc.target/i386/no-caller-saved-3.c: Likewise.\n\t* gcc.target/i386/no-caller-saved-4.c: Likewise.\n\t* gcc.target/i386/no-caller-saved-5.c: Likewise.\n\t* gcc.target/i386/no-caller-saved-6.c: Likewise.\n\t* gcc.target/i386/no-caller-saved-7.c: Likewise.\n\nSigned-off-by: H.J. Lu <hjl.tools@gmail.com>\n---\n gcc/config/i386/i386.cc | 249 +++++++++++++++++-\n gcc/config/i386/i386.md | 18 +-\n .../gcc.target/i386/no-callee-saved-2.c | 10 +-\n .../gcc.target/i386/no-caller-saved-1.c | 46 ++++\n .../gcc.target/i386/no-caller-saved-2.c | 45 ++++\n .../gcc.target/i386/no-caller-saved-3.c | 44 ++++\n .../gcc.target/i386/no-caller-saved-4.c | 44 ++++\n .../gcc.target/i386/no-caller-saved-5.c | 34 +++\n .../gcc.target/i386/no-caller-saved-6.c | 34 +++\n .../gcc.target/i386/no-caller-saved-7.c | 49 ++++\n .../gcc.target/i386/preserve-none-7.c | 10 +-\n 11 files changed, 572 insertions(+), 11 deletions(-)\n create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-1.c\n create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-2.c\n create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-3.c\n create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-4.c\n create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-5.c\n create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-6.c\n create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-7.c\n\ndiff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc\nindex 01715f84e8a..428394985a1 100644\n--- a/gcc/config/i386/i386.cc\n+++ b/gcc/config/i386/i386.cc\n@@ -571,6 +571,11 @@ ix86_conditional_register_usage (void)\n for (i = FIRST_REX2_INT_REG; i <= LAST_REX2_INT_REG; i++)\n \tCLEAR_HARD_REG_BIT (accessible_reg_set, i);\n }\n+\n+ /* If a register is disabled, it can't be used for call. */\n+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)\n+ if (!TEST_HARD_REG_BIT (accessible_reg_set, i))\n+ call_used_regs[i] = 0;\n }\n \n /* Canonicalize a comparison from one we don't have to one we do have. */\n@@ -21719,6 +21724,214 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode)\n return false;\n }\n \n+/* Return the descriptor of no_callee_saved_registers function type.\n+ None of registers are preserved, except for frame register to\n+ mitigate PR target/114116. MMX and x87 registers are preserved\n+ if MMX and x87 aren't enabled. */\n+\n+static const predefined_function_abi &\n+ix86_no_callee_saved_abi (void)\n+{\n+ auto &no_callee_saved_abi = function_abis[ABI_NO_CALLEE_SAVED];\n+ if (!no_callee_saved_abi.initialized_p ())\n+ {\n+ HARD_REG_SET full_reg_clobbers = reg_class_contents[ALL_REGS];\n+ CLEAR_HARD_REG_BIT (full_reg_clobbers, HARD_FRAME_POINTER_REGNUM);\n+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)\n+\tif ((!TARGET_80387 && STACK_REGNO_P (i))\n+\t || (!TARGET_MMX && MMX_REGNO_P (i)))\n+\t CLEAR_HARD_REG_BIT (full_reg_clobbers, i);\n+ no_callee_saved_abi.initialize (ABI_NO_CALLEE_SAVED,\n+\t\t\t\t full_reg_clobbers);\n+ }\n+ return no_callee_saved_abi;\n+}\n+\n+/* Return the descriptor of no_caller_saved_registers function type.\n+ All registers are preserved, except for MMX and x87 registers\n+ which aren't supported when saving and restoring registers. */\n+\n+static const predefined_function_abi &\n+ix86_no_caller_saved_abi_void (void)\n+{\n+ auto &no_caller_saved_abi\n+ = function_abis[ABI_NO_CALLER_SAVED_RETURN_VOID];\n+ if (!no_caller_saved_abi.initialized_p ())\n+ {\n+ HARD_REG_SET full_reg_clobbers = {};\n+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)\n+\tif ((TARGET_80387 && STACK_REGNO_P (i))\n+\t || (TARGET_MMX && MMX_REGNO_P (i)))\n+\t SET_HARD_REG_BIT (full_reg_clobbers, i);\n+ no_caller_saved_abi.initialize\n+\t(ABI_NO_CALLER_SAVED_RETURN_VOID, full_reg_clobbers);\n+ }\n+ return no_caller_saved_abi;\n+}\n+\n+/* Return the descriptor of no_caller_saved_registers function type.\n+ All registers are preserved, except for AX used for return value,\n+ MMX and x87 registers which aren't supported when saving and\n+ restoring registers. */\n+\n+static const predefined_function_abi &\n+ix86_no_caller_saved_abi_ax (void)\n+{\n+ auto &no_caller_saved_abi\n+ = function_abis[ABI_NO_CALLER_SAVED_RETURN_AX];\n+ if (!no_caller_saved_abi.initialized_p ())\n+ {\n+ HARD_REG_SET full_reg_clobbers = {};\n+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)\n+\tif (i == AX_REG\n+\t || (TARGET_80387 && STACK_REGNO_P (i))\n+\t || (TARGET_MMX && MMX_REGNO_P (i)))\n+\t SET_HARD_REG_BIT (full_reg_clobbers, i);\n+ no_caller_saved_abi.initialize\n+\t(ABI_NO_CALLER_SAVED_RETURN_AX, full_reg_clobbers);\n+ }\n+ return no_caller_saved_abi;\n+}\n+\n+/* Return the descriptor of no_caller_saved_registers function type.\n+ All registers are preserved, except for AX/DX used for return value,\n+ MMX and x87 registers which aren't supported when saving and\n+ restoring registers. */\n+\n+static const predefined_function_abi &\n+ix86_no_caller_saved_abi_ax_dx (void)\n+{\n+ auto &no_caller_saved_abi\n+ = function_abis[ABI_NO_CALLER_SAVED_RETURN_AX_DX];\n+ if (!no_caller_saved_abi.initialized_p ())\n+ {\n+ HARD_REG_SET full_reg_clobbers = {};\n+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)\n+\tif (i == AX_REG\n+\t || i == DX_REG\n+\t || (TARGET_80387 && STACK_REGNO_P (i))\n+\t || (TARGET_MMX && MMX_REGNO_P (i)))\n+\t SET_HARD_REG_BIT (full_reg_clobbers, i);\n+ no_caller_saved_abi.initialize\n+\t(ABI_NO_CALLER_SAVED_RETURN_AX_DX, full_reg_clobbers);\n+ }\n+ return no_caller_saved_abi;\n+}\n+\n+/* Return the descriptor of no_caller_saved_registers function type.\n+ All registers are preserved, except for XMM0 used for return value,\n+ MMX and x87 registers which aren't supported when saving and\n+ restoring registers. */\n+\n+static const predefined_function_abi &\n+ix86_no_caller_saved_abi_xmm0 (void)\n+{\n+ auto &no_caller_saved_abi\n+ = function_abis[ABI_NO_CALLER_SAVED_RETURN_XMM0];\n+ if (!no_caller_saved_abi.initialized_p ())\n+ {\n+ HARD_REG_SET full_reg_clobbers = {};\n+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)\n+\tif (i == XMM0_REG\n+\t || (TARGET_80387 && STACK_REGNO_P (i))\n+\t || (TARGET_MMX && MMX_REGNO_P (i)))\n+\t SET_HARD_REG_BIT (full_reg_clobbers, i);\n+ no_caller_saved_abi.initialize\n+\t(ABI_NO_CALLER_SAVED_RETURN_XMM0, full_reg_clobbers);\n+ }\n+ return no_caller_saved_abi;\n+}\n+\n+/* Return the descriptor of no_caller_saved_registers function type.\n+ All registers are preserved, except for XMM0/XMM1 used for return\n+ value, MMX and x87 registers which aren't supported when saving and\n+ restoring registers. */\n+\n+static const predefined_function_abi &\n+ix86_no_caller_saved_abi_xmm0_xmm1 (void)\n+{\n+ auto &no_caller_saved_abi\n+ = function_abis[ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1];\n+ if (!no_caller_saved_abi.initialized_p ())\n+ {\n+ HARD_REG_SET full_reg_clobbers = {};\n+ for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)\n+\tif (i == XMM0_REG\n+\t || i == XMM1_REG\n+\t || (TARGET_80387 && STACK_REGNO_P (i))\n+\t || (TARGET_MMX && MMX_REGNO_P (i)))\n+\t SET_HARD_REG_BIT (full_reg_clobbers, i);\n+ no_caller_saved_abi.initialize\n+\t(ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1, full_reg_clobbers);\n+ }\n+ return no_caller_saved_abi;\n+}\n+\n+/* Implement TARGET_FNTYPE_ABI. */\n+\n+static const predefined_function_abi &\n+ix86_fntype_abi (const_tree fntype)\n+{\n+ if (lookup_attribute (\"no_callee_saved_registers\",\n+\t\t\tTYPE_ATTRIBUTES (fntype))\n+ || lookup_attribute (\"no_callee_saved_registers\",\n+\t\t\t TYPE_ATTRIBUTES (fntype)))\n+ return ix86_no_callee_saved_abi ();\n+\n+ if (lookup_attribute (\"no_caller_saved_registers\",\n+\t\t\tTYPE_ATTRIBUTES (fntype)))\n+ {\n+ tree type = TREE_TYPE (fntype);\n+ if (VOID_TYPE_P (type))\n+\treturn ix86_no_caller_saved_abi_void ();\n+ /* AX register contains the address of the return value location\n+\t passed in by the caller. */\n+ else if (ix86_return_in_memory (type, fntype))\n+\treturn ix86_no_caller_saved_abi_ax ();\n+ rtx ret = ix86_function_value (type, fntype, false);\n+ unsigned int nregs;\n+ if (REG_P (ret))\n+\t{\n+\t unsigned int regno = REGNO (ret);\n+\t if (STACK_REGNO_P (regno) || MMX_REGNO_P (regno))\n+\t return ix86_no_caller_saved_abi_void ();\n+\t else\n+\t switch (regno)\n+\t {\n+\t case AX_REG:\n+\t\tnregs = REG_NREGS (ret);\n+\t\tif (nregs == 1)\n+\t\t return ix86_no_caller_saved_abi_ax ();\n+\t\telse if (nregs == 2)\n+\t\t return ix86_no_caller_saved_abi_ax_dx ();\n+\t\tbreak;\n+\t case XMM0_REG:\n+\t\treturn ix86_no_caller_saved_abi_xmm0 ();\n+\t }\n+\t}\n+ else if (GET_CODE (ret) == PARALLEL && XVECLEN (ret, 0) == 2)\n+\t{\n+\t rtx x0 = XVECEXP (ret, 0, 0);\n+\t rtx x1 = XVECEXP (ret, 0, 1);\n+\t if (GET_CODE (x0) == EXPR_LIST\n+\t && GET_CODE (x1) == EXPR_LIST)\n+\t {\n+\t x0 = XEXP (x0, 0);\n+\t x1 = XEXP (x1, 0);\n+\t if (REG_P (x0)\n+\t\t && REGNO (x0) == XMM0_REG\n+\t\t && REG_P (x1)\n+\t\t && REGNO (x1) == XMM1_REG)\n+\t\treturn ix86_no_caller_saved_abi_xmm0_xmm1 ();\n+\t }\n+\t}\n+\n+ gcc_unreachable ();\n+ }\n+\n+ return default_function_abi;\n+}\n+\n /* Implement TARGET_INSN_CALLEE_ABI. */\n \n const predefined_function_abi &\n@@ -21769,12 +21982,41 @@ static bool\n ix86_hard_regno_call_part_clobbered (unsigned int abi_id, unsigned int regno,\n \t\t\t\t machine_mode mode)\n {\n- /* Special ABI for vzeroupper which only clobber higher part of sse regs. */\n- if (abi_id == ABI_VZEROUPPER)\n+ switch (abi_id)\n+ {\n+ case ABI_VZEROUPPER:\n+ /* Special ABI for vzeroupper which only clobbers higher part of\n+\t SSE registers. */\n return (GET_MODE_SIZE (mode) > 16\n \t && ((TARGET_64BIT && REX_SSE_REGNO_P (regno))\n \t\t || LEGACY_SSE_REGNO_P (regno)));\n \n+ case ABI_DEFAULT:\n+ case ABI_NO_CALLEE_SAVED:\n+ break;\n+\n+ case ABI_NO_CALLER_SAVED_RETURN_VOID:\n+ case ABI_NO_CALLER_SAVED_RETURN_AX:\n+ case ABI_NO_CALLER_SAVED_RETURN_AX_DX:\n+ /* These ABIs don't clobber SSE registers. */\n+ return false;\n+\n+ case ABI_NO_CALLER_SAVED_RETURN_XMM0:\n+ /* This ABI only clobbers XMM0. */\n+ if (regno != XMM0_REG)\n+\treturn false;\n+ break;\n+\n+ case ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1:\n+ /* This ABI only clobbers XMM0 and XMM1. */\n+ if (regno != XMM0_REG && regno != XMM1_REG)\n+\treturn false;\n+ break;\n+\n+ default:\n+ gcc_unreachable ();\n+ }\n+\n return SSE_REGNO_P (regno) && GET_MODE_SIZE (mode) > 16;\n }\n \n@@ -28642,6 +28884,9 @@ ix86_libgcc_floating_mode_supported_p\n #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \\\n ix86_hard_regno_call_part_clobbered\n \n+#undef TARGET_FNTYPE_ABI\n+#define TARGET_FNTYPE_ABI ix86_fntype_abi\n+\n #undef TARGET_INSN_CALLEE_ABI\n #define TARGET_INSN_CALLEE_ABI ix86_insn_callee_abi\n \ndiff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md\nindex c67b1c7183e..65367ea922d 100644\n--- a/gcc/config/i386/i386.md\n+++ b/gcc/config/i386/i386.md\n@@ -515,7 +515,23 @@ (define_constants\n (define_constants\n [(ABI_DEFAULT\t\t0)\n (ABI_VZEROUPPER\t1)\n- (ABI_UNKNOWN\t\t2)])\n+ (ABI_NO_CALLEE_SAVED 2)\n+ ;; Return void.\n+ (ABI_NO_CALLER_SAVED_RETURN_VOID 3)\n+ ;; Return char, short, int in 32-bit/64-bit.\n+ ;; Return int64 and _Complex int in 64-bit.\n+ ;; Return _Complex float in MS 32-bit/64-bit.\n+ (ABI_NO_CALLER_SAVED_RETURN_AX 4)\n+ ;; Return int64 and _Complex int in 32-bit.\n+ ;; Return _Complex int64 in 64-bit.\n+ (ABI_NO_CALLER_SAVED_RETURN_AX_DX 5)\n+ ;; Return float and double in 64-bit.\n+ ;; Return _Complex float in SYSV 64-bit.\n+ ;; Return int28, _Complex double in MS 64-bit.\n+ (ABI_NO_CALLER_SAVED_RETURN_XMM0 6)\n+ ;; Return _Complex double in SYSV 64-bit.\n+ (ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1 7)\n+ (ABI_UNKNOWN\t\t8)])\n \n ;; Insns whose names begin with \"x86_\" are emitted by gen_FOO calls\n ;; from i386.cc.\ndiff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-2.c b/gcc/testsuite/gcc.target/i386/no-callee-saved-2.c\nindex e074ca51df4..86864ea9bff 100644\n--- a/gcc/testsuite/gcc.target/i386/no-callee-saved-2.c\n+++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-2.c\n@@ -26,7 +26,9 @@ foo (void *frame)\n }\n }\n \n-/* { dg-final { scan-assembler-times \"push(?:l|q)\\[\\\\t \\]*%(?:e|r)bp\" 1 } } */\n-/* { dg-final { scan-assembler-times \"pop(?:l|q)\\[\\\\t \\]*%(?:e|r)bp\" 1 } } */\n-/* { dg-final { scan-assembler-times \"push(?:l|q)\\[\\\\t \\]*\" 1 } } */\n-/* { dg-final { scan-assembler-times \"pop(?:l|q)\\[\\\\t \\]*\" 1 } } */\n+/* { dg-final { scan-assembler-times \"push(?:l|q)\\[\\\\t \\]*%(?:e|r)bp\" 1 { target ia32 } } } */\n+/* { dg-final { scan-assembler-times \"pop(?:l|q)\\[\\\\t \\]*%(?:e|r)bp\" 1 { target ia32 } } } */\n+/* { dg-final { scan-assembler-times \"push(?:l|q)\\[\\\\t \\]*\" 1 { target ia32 } } } */\n+/* { dg-final { scan-assembler-times \"pop(?:l|q)\\[\\\\t \\]*\" 1 { target ia32 } } } */\n+/* { dg-final { scan-assembler-not \"push(?:l|q)\\[\\\\t \\]*\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"pop(?:l|q)\\[\\\\t \\]*\" { target { ! ia32 } } } } */\ndiff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-1.c b/gcc/testsuite/gcc.target/i386/no-caller-saved-1.c\nnew file mode 100644\nindex 00000000000..e675f4327cb\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-1.c\n@@ -0,0 +1,46 @@\n+/* PR target/124798 */\n+/* { dg-do compile } */\n+/* { dg-options \"-O2 -mtune=corei7 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer\" } */\n+\n+[[gnu::no_caller_saved_registers]] extern void foo (void);\n+\n+void\n+qux (void)\n+{\n+ int a, b, c, d, e, f;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t: \"=r\" (a), \"=r\" (b), \"=r\" (c), \"=r\" (d), \"=r\" (e), \"=r\" (f));\n+#ifdef __x86_64__\n+ int g, h, i, j, k, l, m, n, o, p;\n+ asm volatile (\"# %0 %1\"\n+\t\t: \"=r\" (g), \"=r\" (h));\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: \"=r\" (i), \"=r\" (j), \"=r\" (k), \"=r\" (l), \"=r\" (m), \"=r\" (n), \"=r\" (o), \"=r\" (p));\n+#endif\n+ foo ();\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t:: \"r\" (a), \"r\" (b), \"r\" (c), \"r\" (d), \"r\" (e), \"r\" (f));\n+#ifdef __x86_64__\n+ asm volatile (\"# %0 %1\"\n+\t\t:: \"r\" (g), \"r\" (h));\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: : \"r\" (i), \"r\" (j), \"r\" (k), \"r\" (l), \"r\" (m), \"r\" (n), \"r\" (o), \"r\" (p));\n+#endif\n+}\n+\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%ecx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%esi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edx\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %ecx\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %esi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r8d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r9d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r10d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r11d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r8d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r9d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r10d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r11d\" { target { ! ia32 } } } } */\ndiff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-2.c b/gcc/testsuite/gcc.target/i386/no-caller-saved-2.c\nnew file mode 100644\nindex 00000000000..0a7e443b3db\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-2.c\n@@ -0,0 +1,45 @@\n+/* PR target/124798 */\n+/* { dg-do compile } */\n+/* { dg-options \"-O2 -mtune=corei7 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer\" } */\n+\n+[[gnu::no_caller_saved_registers]] extern int foo (void);\n+\n+int\n+qux (void)\n+{\n+ int a, b, c, d, e, f;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t: \"=r\" (a), \"=r\" (b), \"=r\" (c), \"=r\" (d), \"=r\" (e), \"=r\" (f));\n+#ifdef __x86_64__\n+ int g, h, i, j, k, l, m, n, o, p;\n+ asm volatile (\"# %0 %1\"\n+\t\t: \"=r\" (g), \"=r\" (h));\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: \"=r\" (i), \"=r\" (j), \"=r\" (k), \"=r\" (l), \"=r\" (m), \"=r\" (n), \"=r\" (o), \"=r\" (p));\n+#endif\n+ int ret = foo ();\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t:: \"r\" (a), \"r\" (b), \"r\" (c), \"r\" (d), \"r\" (e), \"r\" (f));\n+#ifdef __x86_64__\n+ asm volatile (\"# %0 %1\"\n+\t\t:: \"r\" (g), \"r\" (h));\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: : \"r\" (i), \"r\" (j), \"r\" (k), \"r\" (l), \"r\" (m), \"r\" (n), \"r\" (o), \"r\" (p));\n+#endif\n+\n+ return ret;\n+}\n+\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%ecx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%esi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %ecx\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %esi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r8d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r9d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r10d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r11d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r8d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r9d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r11d\" { target { ! ia32 } } } } */\ndiff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-3.c b/gcc/testsuite/gcc.target/i386/no-caller-saved-3.c\nnew file mode 100644\nindex 00000000000..e940ee85cfe\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-3.c\n@@ -0,0 +1,44 @@\n+/* PR target/124798 */\n+/* { dg-do compile } */\n+/* { dg-options \"-O2 -mtune=corei7 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer\" } */\n+\n+[[gnu::no_caller_saved_registers]] extern long long foo (void);\n+\n+long long\n+qux (void)\n+{\n+ int a, b, c, d, e, f;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t: \"=r\" (a), \"=r\" (b), \"=r\" (c), \"=r\" (d), \"=r\" (e), \"=r\" (f));\n+#ifdef __x86_64__\n+ int g, h, i, j, k, l, m, n;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: \"=r\" (g), \"=r\" (h), \"=r\" (i), \"=r\" (j), \"=r\" (k), \"=r\" (l), \"=r\" (m), \"=r\" (n));\n+#endif\n+ long long ret = foo ();\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t:: \"r\" (a), \"r\" (b), \"r\" (c), \"r\" (d), \"r\" (e), \"r\" (f));\n+#ifdef __x86_64__\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: : \"r\" (g), \"r\" (h), \"r\" (i), \"r\" (j), \"r\" (k), \"r\" (l), \"r\" (m), \"r\" (n));\n+#endif\n+\n+ return ret;\n+}\n+\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%ecx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%esi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %ecx\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %esi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r8d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r9d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r10d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r11d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edx\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r8d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r9d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r10d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r11d\" { target { ! ia32 } } } } */\ndiff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-4.c b/gcc/testsuite/gcc.target/i386/no-caller-saved-4.c\nnew file mode 100644\nindex 00000000000..e52a0cd9c4b\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-4.c\n@@ -0,0 +1,44 @@\n+/* PR target/124798 */\n+/* { dg-do compile { target int128 } } */\n+/* { dg-options \"-O2 -mtune=corei7 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer\" } */\n+\n+[[gnu::no_caller_saved_registers]] extern __int128 foo (void);\n+\n+__int128\n+qux (void)\n+{\n+ int a, b, c, d, e, f;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t: \"=r\" (a), \"=r\" (b), \"=r\" (c), \"=r\" (d), \"=r\" (e), \"=r\" (f));\n+#ifdef __x86_64__\n+ int g, h, i, j, k, l, m, n;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: \"=r\" (g), \"=r\" (h), \"=r\" (i), \"=r\" (j), \"=r\" (k), \"=r\" (l), \"=r\" (m), \"=r\" (n));\n+#endif\n+ __int128 ret = foo ();\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t:: \"r\" (a), \"r\" (b), \"r\" (c), \"r\" (d), \"r\" (e), \"r\" (f));\n+#ifdef __x86_64__\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: : \"r\" (g), \"r\" (h), \"r\" (i), \"r\" (j), \"r\" (k), \"r\" (l), \"r\" (m), \"r\" (n));\n+#endif\n+\n+ return ret;\n+}\n+\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%ecx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%esi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edx\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %ecx\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %esi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r8d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r9d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r10d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r11d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r8d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r9d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r10d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r11d\" { target { ! ia32 } } } } */\ndiff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-5.c b/gcc/testsuite/gcc.target/i386/no-caller-saved-5.c\nnew file mode 100644\nindex 00000000000..98f58fe92f5\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-5.c\n@@ -0,0 +1,34 @@\n+/* PR target/124798 */\n+/* { dg-do compile } */\n+/* { dg-options \"-O2 -mtune=corei7 -msse2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer\" } */\n+\n+[[gnu::no_caller_saved_registers]] extern float foo (void);\n+\n+float\n+qux (void)\n+{\n+ float a, b, c, d, e, f;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t: \"=v\" (a), \"=v\" (b), \"=v\" (c), \"=v\" (d), \"=v\" (e), \"=v\" (f));\n+#ifdef __x86_64__\n+ float g, h, i, j, k, l, m, n, o, p;\n+ asm volatile (\"# %0 %1\"\n+\t\t: \"=v\" (g), \"=v\" (h));\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: \"=v\" (i), \"=v\" (j), \"=v\" (k), \"=v\" (l), \"=v\" (m), \"=v\" (n), \"=v\" (o), \"=v\" (p));\n+#endif\n+ float ret = foo ();\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t:: \"v\" (a), \"v\" (b), \"v\" (c), \"v\" (d), \"v\" (e), \"v\" (f));\n+#ifdef __x86_64__\n+ asm volatile (\"# %0 %1\"\n+\t\t:: \"v\" (g), \"v\" (h));\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: : \"v\" (i), \"v\" (j), \"v\" (k), \"v\" (l), \"v\" (m), \"v\" (n), \"v\" (o), \"v\" (p));\n+#endif\n+\n+ return ret;\n+}\n+\n+/* { dg-final { scan-assembler-not \"movss\\[ \\\\t\\]+%xmm\\[0-9\\]+, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %xmm\\[0-9\\]+\" } } */\ndiff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-6.c b/gcc/testsuite/gcc.target/i386/no-caller-saved-6.c\nnew file mode 100644\nindex 00000000000..5eb5b102843\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-6.c\n@@ -0,0 +1,34 @@\n+/* PR target/124798 */\n+/* { dg-do compile } */\n+/* { dg-options \"-O2 -mtune=corei7 -msse2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer\" } */\n+\n+[[gnu::no_caller_saved_registers]] extern _Complex double foo (void);\n+\n+_Complex double\n+qux (void)\n+{\n+ double a, b, c, d, e, f;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t: \"=v\" (a), \"=v\" (b), \"=v\" (c), \"=v\" (d), \"=v\" (e), \"=v\" (f));\n+#ifdef __x86_64__\n+ double g, h, i, j, k, l, m, n, o, p;\n+ asm volatile (\"# %0 %1\"\n+\t\t: \"=v\" (g), \"=v\" (h));\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: \"=v\" (i), \"=v\" (j), \"=v\" (k), \"=v\" (l), \"=v\" (m), \"=v\" (n), \"=v\" (o), \"=v\" (p));\n+#endif\n+ _Complex double ret = foo ();\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t:: \"v\" (a), \"v\" (b), \"v\" (c), \"v\" (d), \"v\" (e), \"v\" (f));\n+#ifdef __x86_64__\n+ asm volatile (\"# %0 %1\"\n+\t\t:: \"v\" (g), \"v\" (h));\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5 %6 %7\"\n+\t\t: : \"v\" (i), \"v\" (j), \"v\" (k), \"v\" (l), \"v\" (m), \"v\" (n), \"v\" (o), \"v\" (p));\n+#endif\n+\n+ return ret;\n+}\n+\n+/* { dg-final { scan-assembler-not \"movss\\[ \\\\t\\]+%xmm\\[0-9\\]+, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %xmm\\[0-9\\]+\" } } */\ndiff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-7.c b/gcc/testsuite/gcc.target/i386/no-caller-saved-7.c\nnew file mode 100644\nindex 00000000000..c8a99e950da\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-7.c\n@@ -0,0 +1,49 @@\n+/* PR target/124798 */\n+/* { dg-do compile } */\n+/* { dg-options \"-O2 -mtune=corei7 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer\" } */\n+\n+typedef struct\n+{\n+ double d[16];\n+} record;\n+\n+[[gnu::no_caller_saved_registers]] extern record foo (void);\n+\n+record\n+qux (void)\n+{\n+ int a, b, c, d, e, f;\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t: \"=r\" (a), \"=r\" (b), \"=r\" (c), \"=r\" (d), \"=r\" (e), \"=r\" (f));\n+#ifdef __x86_64__\n+ int g, h, i, j;\n+ asm volatile (\"# %0 %1 %2 %3\"\n+\t\t: \"=r\" (g), \"=r\" (h), \"=r\" (i), \"=r\" (j));\n+#endif\n+ record ret = foo ();\n+ asm volatile (\"# %0 %1 %2 %3 %4 %5\"\n+\t\t:: \"r\" (a), \"r\" (b), \"r\" (c), \"r\" (d), \"r\" (e), \"r\" (f));\n+#ifdef __x86_64__\n+ asm volatile (\"# %0 %1 %2 %3\"\n+\t\t:: \"r\" (g), \"r\" (h), \"r\" (i), \"r\" (j));\n+#endif\n+\n+ return ret;\n+}\n+\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%ecx, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%esi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%edi, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edx\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %ecx\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %esi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %edi\" } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r8d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r9d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r10d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+%r11d, \\[0-9\\]*\\\\(%\\[re\\]?sp\\\\)\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r8d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r9d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r10d\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"mov(l|q)\\[ \\\\t\\]+\\[0-9\\]*\\\\(%\\[re\\]?sp\\\\), %r11d\" { target { ! ia32 } } } } */\ndiff --git a/gcc/testsuite/gcc.target/i386/preserve-none-7.c b/gcc/testsuite/gcc.target/i386/preserve-none-7.c\nindex 2c80560887c..6f252ee50a4 100644\n--- a/gcc/testsuite/gcc.target/i386/preserve-none-7.c\n+++ b/gcc/testsuite/gcc.target/i386/preserve-none-7.c\n@@ -26,7 +26,9 @@ foo (void *frame)\n }\n }\n \n-/* { dg-final { scan-assembler-times \"push(?:l|q)\\[\\\\t \\]*%(?:e|r)bp\" 1 } } */\n-/* { dg-final { scan-assembler-times \"pop(?:l|q)\\[\\\\t \\]*%(?:e|r)bp\" 1 } } */\n-/* { dg-final { scan-assembler-times \"push(?:l|q)\\[\\\\t \\]*\" 1 } } */\n-/* { dg-final { scan-assembler-times \"pop(?:l|q)\\[\\\\t \\]*\" 1 } } */\n+/* { dg-final { scan-assembler-times \"push(?:l|q)\\[\\\\t \\]*%(?:e|r)bp\" 1 { target ia32 } } } */\n+/* { dg-final { scan-assembler-times \"pop(?:l|q)\\[\\\\t \\]*%(?:e|r)bp\" 1 { target ia32 } } } */\n+/* { dg-final { scan-assembler-times \"push(?:l|q)\\[\\\\t \\]*\" 1 { target ia32 } } } */\n+/* { dg-final { scan-assembler-times \"pop(?:l|q)\\[\\\\t \\]*\" 1 { target ia32 } } } */\n+/* { dg-final { scan-assembler-not \"push(?:l|q)\\[\\\\t \\]*\" { target { ! ia32 } } } } */\n+/* { dg-final { scan-assembler-not \"pop(?:l|q)\\[\\\\t \\]*\" { target { ! ia32 } } } } */\n-- \n2.53.0\n\n", "prefixes": [] }