From patchwork Wed Nov 6 13:50:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 2007563 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=aUQtDI6/; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Xk67Z2xppz1xyM for ; Thu, 7 Nov 2024 00:51:38 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9BAF73858C3A for ; Wed, 6 Nov 2024 13:51:36 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 726923858D3C for ; Wed, 6 Nov 2024 13:50:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 726923858D3C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 726923858D3C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730901043; cv=none; b=b8RmG76o2SsJJkmGYKd3MXXC6rd96bun5aGMXqVPVCpM0BTbksKdEEM97XV54PcTp553BVtxIjjhL1EQoA6mVHhW8lXkDPPOdXEsQGgX0sFFUAHwYb7OHcBZTLyPQR82uMcnmgNUXt2Sp4nQ8tVp13pJBOh6Vq5pGihBAqP51tI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730901043; c=relaxed/simple; bh=+39DmipObiTG18CdZtEJpmYr74ah8vn+/SAJUAbOTVU=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=tfmg0pGbCmj5SNGEUJmZADfRNjHEmraQAz1pPy6RMXSc8uLZcLzq/QU5+YuoiEWJKuIX76DcD9TX4llUWQpM0TOEoShb722mGKM2NSKR/EDWE+WszTueRratJhGy56qyTqRK+qfLameKStbqtKypKtA79D8jnatRobI5tg4Y87Q= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730901037; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=fo3rXuLfNza7MIIhy2/Hj2zmRnFcUjh7+oB36G/K/rY=; b=aUQtDI6/qa7uhhnNsFpXSW3+m6y62GH4DRUxrJyq8cHJGWuXfZeuspMTO9LiZCCnbQcrvx TTghgMIrQXHi1eUKnnDvAUZ0xgRsC4EAqm0fO9U2N1ZKePNztTU/S79Il7AKnkNIgy52te 23dbJdq6PBfgJ3vxgeD1DBhtj3sgY74= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-124-S6yeH1QLOOuMu4vi9ESVfA-1; Wed, 06 Nov 2024 08:50:33 -0500 X-MC-Unique: S6yeH1QLOOuMu4vi9ESVfA-1 X-Mimecast-MFC-AGG-ID: S6yeH1QLOOuMu4vi9ESVfA Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 852581955BFE; Wed, 6 Nov 2024 13:50:31 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.16]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CD15E1956088; Wed, 6 Nov 2024 13:50:30 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 4A6DoRJx821020 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Wed, 6 Nov 2024 14:50:27 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 4A6DoRlU821019; Wed, 6 Nov 2024 14:50:27 +0100 Date: Wed, 6 Nov 2024 14:50:27 +0100 From: Jakub Jelinek To: Uros Bizjak , Richard Biener , Jan Hubicka Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] inline-asm, i386: Add "redzone" clobber support Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 736aGXvM8bwe0mZR8tZsTC8-X-_Ds55vSMT_izJ_JRw_1730901032 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Hi! The following patch adds a "redzone" clobber (recognized just on targets which choose to recognize it, right now just x86), with which one can mark the rare case where inline asm pushes something on the stack or uses call instruction without taking red zone into account (i.e. addq $-128, %rsp; and addq $128, %rsp around that). 2024-11-06 Jakub Jelinek gcc/ * target.def (redzone_clobber): New target hook. * varasm.cc (decode_reg_name_and_count): Return -5 for "redzone". * cfgexpand.cc (expand_asm_stmt): Handle redzone clobber. * config/i386/i386.h (struct machine_function): Add asm_redzone_clobber_seen member. * config/i386/i386.cc (ix86_compute_frame_layout): Don't use red zone if cfun->machine->asm_redzone_clobber_seen. (ix86_redzone_clobber): New function. (TARGET_REDZONE_CLOBBER): Redefine. * doc/extend.texi (Clobbers and Scratch Registers): Document the "redzone" clobber. * doc/tm.texi.in: Add @hook TARGET_REDZONE_CLOBBER. * doc/tm.texi: Regenerate. gcc/testsuite/ * gcc.target/i386/asm-redzone-1.c: New test. Jakub --- gcc/target.def.jj 2024-10-25 10:00:29.525767041 +0200 +++ gcc/target.def 2024-11-06 13:32:39.376320955 +0100 @@ -3376,6 +3376,18 @@ to be used.", bool, (machine_mode mode), NULL) +DEFHOOK +(redzone_clobber, + "Define this to return some RTL for the @code{redzone} @code{asm} clobber\n\ +if target has a red zone and wants to support the @code{redzone} clobber\n\ +or return NULL if the clobber shouldn't be recognized or return\n\ +@code{pc_rtx} if the clobber should be recognized but should not be added\n\ +to the list of clobbers.\n\ +\n\ +The default is not to support the @code{redzone} clobber.", + rtx, (), + NULL) + /* Support for named address spaces. */ #undef HOOK_PREFIX #define HOOK_PREFIX "TARGET_ADDR_SPACE_" --- gcc/varasm.cc.jj 2024-11-06 10:23:21.215728007 +0100 +++ gcc/varasm.cc 2024-11-06 12:21:17.891908352 +0100 @@ -967,9 +967,11 @@ set_user_assembler_name (tree decl, cons /* Decode an `asm' spec for a declaration as a register name. Return the register number, or -1 if nothing specified, - or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized, + or -2 if the ASMSPEC is not `cc' or `memory' or `redzone' and is not + recognized, or -3 if ASMSPEC is `cc' and is not recognized, or -4 if ASMSPEC is `memory' and is not recognized. + or -5 if ASMSPEC is `redzone' and is not recognized. Accept an exact spelling or a decimal number. Prefixes such as % are optional. */ @@ -1036,6 +1038,9 @@ decode_reg_name_and_count (const char *a } #endif /* ADDITIONAL_REGISTER_NAMES */ + if (!strcmp (asmspec, "redzone")) + return -5; + if (!strcmp (asmspec, "memory")) return -4; --- gcc/cfgexpand.cc.jj 2024-11-05 08:55:41.610187084 +0100 +++ gcc/cfgexpand.cc 2024-11-06 14:26:07.684918717 +0100 @@ -3193,6 +3193,19 @@ expand_asm_stmt (gasm *stmt) j = decode_reg_name_and_count (regname, &nregs); if (j < 0) { + if (j == -5) + { + rtx x = NULL_RTX; + if (targetm.redzone_clobber) + x = targetm.redzone_clobber (); + if (x == pc_rtx) + /* Recognize it but don't add anything to + clobber_rvec. */; + else if (x) + clobber_rvec.safe_push (x); + else + j = -2; + } if (j == -2) { /* ??? Diagnose during gimplification? */ @@ -3208,8 +3221,9 @@ expand_asm_stmt (gasm *stmt) else { /* Otherwise we should have -1 == empty string - or -3 == cc, which is not a register. */ - gcc_assert (j == -1 || j == -3); + or -3 == cc, which is not a register or + -5 == redzone, ditto. */ + gcc_assert (j == -1 || j == -3 || j == -5); } } else --- gcc/config/i386/i386.h.jj 2024-11-05 08:55:41.663186325 +0100 +++ gcc/config/i386/i386.h 2024-11-06 14:11:42.893154474 +0100 @@ -2881,6 +2881,9 @@ struct GTY(()) machine_function { /* True if red zone is used. */ BOOL_BITFIELD red_zone_used : 1; + /* True if inline asm with redzone clobber has been seen. */ + BOOL_BITFIELD asm_redzone_clobber_seen : 1; + /* The largest alignment, in bytes, of stack slot actually used. */ unsigned int max_used_stack_alignment; --- gcc/config/i386/i386.cc.jj 2024-11-05 08:55:41.661186354 +0100 +++ gcc/config/i386/i386.cc 2024-11-06 14:12:52.560168428 +0100 @@ -7172,7 +7172,8 @@ ix86_compute_frame_layout (void) && crtl->sp_is_unchanging && crtl->is_leaf && !ix86_pc_thunk_call_expanded - && !ix86_current_function_calls_tls_descriptor) + && !ix86_current_function_calls_tls_descriptor + && !cfun->machine->asm_redzone_clobber_seen) { frame->red_zone_size = to_allocate; if (frame->save_regs_using_mov) @@ -26268,6 +26269,25 @@ ix86_mode_can_transfer_bits (machine_mod return true; } +/* Implement TARGET_REDZONE_CLOBBER. */ +static rtx +ix86_redzone_clobber () +{ + cfun->machine->asm_redzone_clobber_seen = true; + if (ix86_using_red_zone ()) + { + rtx base = plus_constant (Pmode, stack_pointer_rtx, + GEN_INT (-RED_ZONE_SIZE)); + rtx mem = gen_rtx_MEM (BLKmode, base); + set_mem_size (mem, RED_ZONE_SIZE); + return mem; + } + /* Otherwise accept it. We certainly don't want an error + on "redzone" clobber in e.g. -mno-red-zone compiled function, + and even 32-bit code can use -mred-zone. */ + return pc_rtx; +} + /* Target-specific selftests. */ #if CHECKING_P @@ -27121,6 +27141,9 @@ ix86_libgcc_floating_mode_supported_p #undef TARGET_MODE_CAN_TRANSFER_BITS #define TARGET_MODE_CAN_TRANSFER_BITS ix86_mode_can_transfer_bits +#undef TARGET_REDZONE_CLOBBER +#define TARGET_REDZONE_CLOBBER ix86_redzone_clobber + static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED) { --- gcc/doc/extend.texi.jj 2024-11-06 11:09:46.433407349 +0100 +++ gcc/doc/extend.texi 2024-11-06 14:37:01.426682958 +0100 @@ -11823,7 +11823,7 @@ asm volatile ("movc3 %0, %1, %2" : "r0", "r1", "r2", "r3", "r4", "r5", "memory"); @end example -Also, there are two special clobber arguments: +Also, there are three special clobber arguments: @table @code @item "cc" @@ -11851,6 +11851,18 @@ Note that this clobber does not prevent speculative reads past the @code{asm} statement. To prevent that, you need processor-specific fence instructions. +@item "redzone" +The @code{"redzone"} clobber tells the compiler that the assembly code +may write to the stack red zone, area below the stack pointer which on +some architectures in some calling conventions is guaranteed not to be +changed by signal handlers, interrupts or exceptions and so the compiler +can store there temporaries in leaf functions. The @code{"redzone"} +clobber may be used just on targets which do have a concept of a red zone +and should be used e.g.@: in case the assembly code uses call instructions +or pushes something to the stack without taking the red zone into account +by subtracting red zone size from the stack pointer first and restoring +it afterwards. + @end table Flushing registers to memory has performance implications and may be --- gcc/doc/tm.texi.in.jj 2024-09-24 11:31:48.701622348 +0200 +++ gcc/doc/tm.texi.in 2024-11-06 14:02:19.110134054 +0100 @@ -3464,6 +3464,8 @@ stack. @hook TARGET_MODE_CAN_TRANSFER_BITS +@hook TARGET_REDZONE_CLOBBER + @hook TARGET_TRANSLATE_MODE_ATTRIBUTE @hook TARGET_SCALAR_MODE_SUPPORTED_P --- gcc/doc/tm.texi.jj 2024-09-24 11:31:48.699622375 +0200 +++ gcc/doc/tm.texi 2024-11-06 14:07:09.391025522 +0100 @@ -4563,6 +4563,16 @@ The default is to assume modes with the to be used. @end deftypefn +@deftypefn {Target Hook} rtx TARGET_REDZONE_CLOBBER () +Define this to return some RTL for the @code{redzone} @code{asm} clobber +if target has a red zone and wants to support the @code{redzone} clobber +or return NULL if the clobber shouldn't be recognized or return +@code{pc_rtx} if the clobber should be recognized but should not be added +to the list of clobbers. + +The default is not to support the @code{redzone} clobber. +@end deftypefn + @deftypefn {Target Hook} machine_mode TARGET_TRANSLATE_MODE_ATTRIBUTE (machine_mode @var{mode}) Define this hook if during mode attribute processing, the port should translate machine_mode @var{mode} to another mode. For example, rs6000's --- gcc/testsuite/gcc.target/i386/asm-redzone-1.c.jj 2024-11-06 14:41:39.970752016 +0100 +++ gcc/testsuite/gcc.target/i386/asm-redzone-1.c 2024-11-06 14:42:18.625206505 +0100 @@ -0,0 +1,38 @@ +/* { dg-do run { target lp64 } } */ +/* { dg-options "-O2" } */ + +__attribute__((noipa)) int +foo (void) +{ + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + int h = 8; + int i = 9; + int j = 10; + int k = 11; + int l = 12; + int m = 13; + int n = 14; + asm volatile ("" : "+g" (a), "+g" (b), "+g" (c), "+g" (d), "+g" (e)); + asm volatile ("" : "+g" (f), "+g" (g), "+g" (h), "+g" (i), "+g" (j)); + asm volatile ("" : "+g" (k), "+g" (l), "+g" (m), "+g" (n)); + asm volatile ("{pushq %%rax; pushq %%rax; popq %%rax; popq %%rax" + "|push rax;push rax;pop rax;pop rax}" + : : : "ax", "si", "di", "r10", "r11", "redzone"); + asm volatile ("" : "+g" (a), "+g" (b), "+g" (c), "+g" (d), "+g" (e)); + asm volatile ("" : "+g" (f), "+g" (g), "+g" (h), "+g" (i), "+g" (j)); + asm volatile ("" : "+g" (k), "+g" (l), "+g" (m), "+g" (n)); + return a + b + c + d + e + f + g + h + i + j + k + l + m + n; +} + +int +main () +{ + if (foo () != 105) + __builtin_abort (); +}