From patchwork Fri Oct 31 08:07:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 405235 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 81D2D14007D for ; Fri, 31 Oct 2014 19:07:38 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:to:cc:subject:mime-version:content-type; q=dns; s=default; b=k/TaI8exB5VqXY20nR+u8uJqp+y+Mn61HwOaFuH2a8C JqPAVDyRF0KnXcIEcK3Ij1nspL1UWOHc9Pv+dQL4qvP+q60dAV2wVkSdSY3b5RRD dUtSp7H13oOb2xgK3TS3/nlZCVrYynEraNl+BybtUDX4VM0Fbzh23CYcD1InpRIc = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:to:cc:subject:mime-version:content-type; s=default; bh=RI997Ay0h47AGptDlAdwbpygBQI=; b=XUCuJMBiVEoLbqkBv Rg4BNgmp802WoyMnSrqu3/WpBSum8Gy5to55rdYXmrG4xBkdaHMXFR5lHKJnMqIe /23wOXmyy2zK43jj4aidxYJ2YiY1jx2dMp9g05oheaWerL2fyVHW0seN7ghnlkZz vXD6pv1i70PhIw4UB3Wd/TiR4c= Received: (qmail 8674 invoked by alias); 31 Oct 2014 08:07:29 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 8660 invoked by uid 89); 31 Oct 2014 08:07:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail.emea.novell.com Received: from mail.emea.novell.com (HELO mail.emea.novell.com) (130.57.118.101) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 31 Oct 2014 08:07:26 +0000 Received: from EMEA1-MTA by mail.emea.novell.com with Novell_GroupWise; Fri, 31 Oct 2014 08:07:23 +0000 Message-Id: <5453514B0200007800043D79@mail.emea.novell.com> Date: Fri, 31 Oct 2014 08:07:23 +0000 From: "Jan Beulich" To: Cc: , "Richard Henderson" , Subject: [PATCH] x86: allow to suppress default clobbers added to asm()s Mime-Version: 1.0 While it always seemed wrong to me that there's no way to avoid the default "flags" and "fpsr" clobbers, the regression the fix for PR/60663 introduced (see PR/63637) makes it even more desirable to have such a mechanism: This way, at least asm()s with a single output and no explicit clobbers can again be made subject to CSE. gcc: 2014-10-31 Jan Beulich * config/i386/i386.c (ix86_target_string): Add -mno-default-asm-clobbers. (ix86_valid_target_attribute_inner_p): Handle -m{,no-}default-asm-clobbers. (ix86_md_asm_clobbers): Handle "inverse" clobbers. * config/i386/i386.h (NOCC_REGNUM, NOFPSR_REGNUM): Define. (ADDITIONAL_REGISTER_NAMES): Add "cc", "!cc", "!flags", and "!fpsr". * config/i386/i386.opt: Add mdefault-asm-clobbers and mno-default-asm-clobbers. * varasm.c (decode_reg_name_and_count): Permit negative register numbers in ADDITIONAL_REGISTER_NAMES. gcc/testsuite: 2014-10-31 Jan Beulich * gcc.target/i386/20060218-1.c: Adjust expected error. * gcc.target/i386/invclbr[123].c: New. x86: allow to suppress default clobbers added to asm()s While it always seemed wrong to me that there's no way to avoid the default "flags" and "fpsr" clobbers, the regression the fix for PR/60663 introduced (see PR/63637) makes it even more desirable to have such a mechanism: This way, at least asm()s with a single output and no explicit clobbers can again be made subject to CSE. gcc: 2014-10-31 Jan Beulich * config/i386/i386.c (ix86_target_string): Add -mno-default-asm-clobbers. (ix86_valid_target_attribute_inner_p): Handle -m{,no-}default-asm-clobbers. (ix86_md_asm_clobbers): Handle "inverse" clobbers. * config/i386/i386.h (NOCC_REGNUM, NOFPSR_REGNUM): Define. (ADDITIONAL_REGISTER_NAMES): Add "cc", "!cc", "!flags", and "!fpsr". * config/i386/i386.opt: Add mdefault-asm-clobbers and mno-default-asm-clobbers. * varasm.c (decode_reg_name_and_count): Permit negative register numbers in ADDITIONAL_REGISTER_NAMES. gcc/testsuite: 2014-10-31 Jan Beulich * gcc.target/i386/20060218-1.c: Adjust expected error. * gcc.target/i386/invclbr[123].c: New. --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2664,6 +2664,7 @@ ix86_target_string (HOST_WIDE_INT isa, i { "-minline-stringops-dynamically", MASK_INLINE_STRINGOPS_DYNAMICALLY }, { "-mms-bitfields", MASK_MS_BITFIELD_LAYOUT }, { "-mno-align-stringops", MASK_NO_ALIGN_STRINGOPS }, + { "-mno-default-asm-clobbers", MASK_NO_DEFAULT_ASM_CLOBBERS }, { "-mno-fancy-math-387", MASK_NO_FANCY_MATH_387 }, { "-mno-push-args", MASK_NO_PUSH_ARGS }, { "-mno-red-zone", MASK_NO_RED_ZONE }, @@ -4649,6 +4650,10 @@ ix86_valid_target_attribute_inner_p (tre OPT_mno_align_stringops, MASK_NO_ALIGN_STRINGOPS), + IX86_ATTR_NO ("default-asm-clobbers", + OPT_mno_default_asm_clobbers, + MASK_NO_DEFAULT_ASM_CLOBBERS), + IX86_ATTR_YES ("recip", OPT_mrecip, MASK_RECIP), @@ -44165,10 +44170,31 @@ ix86_c_mode_for_suffix (char suffix) static tree ix86_md_asm_clobbers (tree, tree, tree clobbers) { - clobbers = tree_cons (NULL_TREE, build_string (5, "flags"), - clobbers); - clobbers = tree_cons (NULL_TREE, build_string (4, "fpsr"), - clobbers); + tree clobber; + bool flags_used = false, fpsr_used = false; + bool nocc_used = false, nofpsr_used = false; + + if (!TARGET_DEFAULT_ASM_CLOBBERS) + return clobbers; + + for (clobber = clobbers; clobber; clobber = TREE_CHAIN (clobber)) + switch (decode_reg_name (TREE_STRING_POINTER (TREE_VALUE (clobber)))) + { + case FLAGS_REG: flags_used = true; break; + case FPSR_REG: fpsr_used = true; break; + case NOCC_REGNUM: nocc_used = true; break; + case NOFPSR_REGNUM: nofpsr_used = true; break; + } + + if ((flags_used && nocc_used) || (fpsr_used && nofpsr_used)) + error ("conflicting clobbers in %"); + + if (!flags_used && !nocc_used) + clobbers = tree_cons (NULL_TREE, build_string (5, "flags"), + clobbers); + if (!fpsr_used && !nofpsr_used) + clobbers = tree_cons (NULL_TREE, build_string (4, "fpsr"), + clobbers); return clobbers; } --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1242,6 +1242,11 @@ extern const char *host_detect_local_cpu ? INVALID_REGNUM \ : REAL_PIC_OFFSET_TABLE_REGNUM) +/* Fake register numbers to be used as "inverse" asm() clobber specifiers. + Any negative numbers below the range used by decode_reg_name () will do. */ +#define NOCC_REGNUM (-127) +#define NOFPSR_REGNUM (-126) + #define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_" /* This is overridden by . */ @@ -2059,7 +2064,9 @@ do { \ { "zmm16", 53}, { "zmm17", 54}, { "zmm18", 55}, { "zmm19", 56}, \ { "zmm20", 57}, { "zmm21", 58}, { "zmm22", 59}, { "zmm23", 60}, \ { "zmm24", 61}, { "zmm25", 62}, { "zmm26", 63}, { "zmm27", 64}, \ - { "zmm28", 65}, { "zmm29", 66}, { "zmm30", 67}, { "zmm31", 68} } + { "zmm28", 65}, { "zmm29", 66}, { "zmm30", 67}, { "zmm31", 68}, \ + { "cc", FLAGS_REG }, { "!cc", NOCC_REGNUM }, \ + { "!flags", NOCC_REGNUM }, { "!fpsr", NOFPSR_REGNUM } } /* Note we are omitting these since currently I don't know how to get gcc to use these, since they want the same but different --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -287,6 +287,10 @@ Enum(pmode) String(long) Value(PMODE_DI) mcpu= Target RejectNegative Joined Undocumented Alias(mtune=) Warn(%<-mcpu=%> is deprecated; use %<-mtune=%> or %<-march=%> instead) +mdefault-asm-clobbers +Target RejectNegative Report InverseMask(NO_DEFAULT_ASM_CLOBBERS, DEFAULT_ASM_CLOBBERS) Undocumented Save +Attach compatibility clobbers (flags and fpsr) to every asm(). + mfancy-math-387 Target RejectNegative Report InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387) Save Generate sin, cos, sqrt for FPU @@ -355,6 +359,10 @@ Use native (MS) bitfield layout mno-align-stringops Target RejectNegative Report Mask(NO_ALIGN_STRINGOPS) Undocumented Save +mno-default-asm-clobbers +Target RejectNegative Report Mask(NO_DEFAULT_ASM_CLOBBERS) Save +Don't attach compatibility clobbers (flags and fpsr) to every asm(). + mno-fancy-math-387 Target RejectNegative Report Mask(NO_FANCY_MATH_387) Undocumented Save --- a/gcc/testsuite/gcc.target/i386/20060218-1.c +++ b/gcc/testsuite/gcc.target/i386/20060218-1.c @@ -3,6 +3,6 @@ void foo (void) { - register int cc __asm ("cc"); /* { dg-error "invalid register name" } */ + register int cc __asm ("cc"); /* { dg-error "register specified .* not general enough" } */ __asm ("" : : "r" (cc) : "cc"); } --- a/gcc/testsuite/gcc.target/i386/invclbr1.c +++ b/gcc/testsuite/gcc.target/i386/invclbr1.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void test(void) +{ + asm ("" ::: "cc" ); + asm ("" ::: "!cc" ); + asm ("" ::: "flags" ); + asm ("" ::: "!flags" ); + asm ("" ::: "fpsr" ); + asm ("" ::: "!fpsr" ); + + asm ("" ::: "cc", "!cc" ); /* { dg-error "conflicting clobbers" } */ + asm ("" ::: "flags", "!cc" ); /* { dg-error "conflicting clobbers" } */ + asm ("" ::: "cc", "!flags" ); /* { dg-error "conflicting clobbers" } */ + asm ("" ::: "flags", "!flags" ); /* { dg-error "conflicting clobbers" } */ + asm ("" ::: "fpsr", "!fpsr" ); /* { dg-error "conflicting clobbers" } */ + + asm ("" ::: "cc", "!fpsr" ); + asm ("" ::: "flags", "!fpsr" ); + asm ("" ::: "fpsr", "!flags" ); + asm ("" ::: "fpsr", "!cc" ); +} --- a/gcc/testsuite/gcc.target/i386/invclbr2.c +++ b/gcc/testsuite/gcc.target/i386/invclbr2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-rtl-expand" } */ + +void test(void) +{ + asm ("" ::: "!cc", "!fpsr" ); + asm ("" ::: "!fpsr", "!flags" ); +} + +/* { dg-final { scan-rtl-dump-not "clobber" "expand" } } */ +/* { dg-final { cleanup-rtl-dump "expand" } } */ --- a/gcc/testsuite/gcc.target/i386/invclbr3.c +++ b/gcc/testsuite/gcc.target/i386/invclbr3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-rtl-expand" } */ + +void test(void) +{ + asm ("" ::: "!cc"); + asm ("" ::: "!flags"); + asm ("" ::: "!fpsr"); +} + +/* { dg-final { scan-rtl-dump-times "\\(clobber \\(reg\[^()\]* fpsr\\)\\)" 2 "expand" } } */ +/* { dg-final { scan-rtl-dump-times "\\(clobber \\(reg\[^()\]* flags\\)\\)" 1 "expand" } } */ +/* { dg-final { cleanup-rtl-dump "expand" } } */ --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -936,7 +936,7 @@ decode_reg_name_and_count (const char *a for (i = 0; i < (int) ARRAY_SIZE (table); i++) if (table[i].name[0] && ! strcmp (asmspec, table[i].name) - && reg_names[table[i].number][0]) + && (table[i].number < 0 || reg_names[table[i].number][0])) return table[i].number; } #endif /* ADDITIONAL_REGISTER_NAMES */ --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2664,6 +2664,7 @@ ix86_target_string (HOST_WIDE_INT isa, i { "-minline-stringops-dynamically", MASK_INLINE_STRINGOPS_DYNAMICALLY }, { "-mms-bitfields", MASK_MS_BITFIELD_LAYOUT }, { "-mno-align-stringops", MASK_NO_ALIGN_STRINGOPS }, + { "-mno-default-asm-clobbers", MASK_NO_DEFAULT_ASM_CLOBBERS }, { "-mno-fancy-math-387", MASK_NO_FANCY_MATH_387 }, { "-mno-push-args", MASK_NO_PUSH_ARGS }, { "-mno-red-zone", MASK_NO_RED_ZONE }, @@ -4649,6 +4650,10 @@ ix86_valid_target_attribute_inner_p (tre OPT_mno_align_stringops, MASK_NO_ALIGN_STRINGOPS), + IX86_ATTR_NO ("default-asm-clobbers", + OPT_mno_default_asm_clobbers, + MASK_NO_DEFAULT_ASM_CLOBBERS), + IX86_ATTR_YES ("recip", OPT_mrecip, MASK_RECIP), @@ -44165,10 +44170,31 @@ ix86_c_mode_for_suffix (char suffix) static tree ix86_md_asm_clobbers (tree, tree, tree clobbers) { - clobbers = tree_cons (NULL_TREE, build_string (5, "flags"), - clobbers); - clobbers = tree_cons (NULL_TREE, build_string (4, "fpsr"), - clobbers); + tree clobber; + bool flags_used = false, fpsr_used = false; + bool nocc_used = false, nofpsr_used = false; + + if (!TARGET_DEFAULT_ASM_CLOBBERS) + return clobbers; + + for (clobber = clobbers; clobber; clobber = TREE_CHAIN (clobber)) + switch (decode_reg_name (TREE_STRING_POINTER (TREE_VALUE (clobber)))) + { + case FLAGS_REG: flags_used = true; break; + case FPSR_REG: fpsr_used = true; break; + case NOCC_REGNUM: nocc_used = true; break; + case NOFPSR_REGNUM: nofpsr_used = true; break; + } + + if ((flags_used && nocc_used) || (fpsr_used && nofpsr_used)) + error ("conflicting clobbers in %"); + + if (!flags_used && !nocc_used) + clobbers = tree_cons (NULL_TREE, build_string (5, "flags"), + clobbers); + if (!fpsr_used && !nofpsr_used) + clobbers = tree_cons (NULL_TREE, build_string (4, "fpsr"), + clobbers); return clobbers; } --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1242,6 +1242,11 @@ extern const char *host_detect_local_cpu ? INVALID_REGNUM \ : REAL_PIC_OFFSET_TABLE_REGNUM) +/* Fake register numbers to be used as "inverse" asm() clobber specifiers. + Any negative numbers below the range used by decode_reg_name () will do. */ +#define NOCC_REGNUM (-127) +#define NOFPSR_REGNUM (-126) + #define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_" /* This is overridden by . */ @@ -2059,7 +2064,9 @@ do { \ { "zmm16", 53}, { "zmm17", 54}, { "zmm18", 55}, { "zmm19", 56}, \ { "zmm20", 57}, { "zmm21", 58}, { "zmm22", 59}, { "zmm23", 60}, \ { "zmm24", 61}, { "zmm25", 62}, { "zmm26", 63}, { "zmm27", 64}, \ - { "zmm28", 65}, { "zmm29", 66}, { "zmm30", 67}, { "zmm31", 68} } + { "zmm28", 65}, { "zmm29", 66}, { "zmm30", 67}, { "zmm31", 68}, \ + { "cc", FLAGS_REG }, { "!cc", NOCC_REGNUM }, \ + { "!flags", NOCC_REGNUM }, { "!fpsr", NOFPSR_REGNUM } } /* Note we are omitting these since currently I don't know how to get gcc to use these, since they want the same but different --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -287,6 +287,10 @@ Enum(pmode) String(long) Value(PMODE_DI) mcpu= Target RejectNegative Joined Undocumented Alias(mtune=) Warn(%<-mcpu=%> is deprecated; use %<-mtune=%> or %<-march=%> instead) +mdefault-asm-clobbers +Target RejectNegative Report InverseMask(NO_DEFAULT_ASM_CLOBBERS, DEFAULT_ASM_CLOBBERS) Undocumented Save +Attach compatibility clobbers (flags and fpsr) to every asm(). + mfancy-math-387 Target RejectNegative Report InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387) Save Generate sin, cos, sqrt for FPU @@ -355,6 +359,10 @@ Use native (MS) bitfield layout mno-align-stringops Target RejectNegative Report Mask(NO_ALIGN_STRINGOPS) Undocumented Save +mno-default-asm-clobbers +Target RejectNegative Report Mask(NO_DEFAULT_ASM_CLOBBERS) Save +Don't attach compatibility clobbers (flags and fpsr) to every asm(). + mno-fancy-math-387 Target RejectNegative Report Mask(NO_FANCY_MATH_387) Undocumented Save --- a/gcc/testsuite/gcc.target/i386/20060218-1.c +++ b/gcc/testsuite/gcc.target/i386/20060218-1.c @@ -3,6 +3,6 @@ void foo (void) { - register int cc __asm ("cc"); /* { dg-error "invalid register name" } */ + register int cc __asm ("cc"); /* { dg-error "register specified .* not general enough" } */ __asm ("" : : "r" (cc) : "cc"); } --- a/gcc/testsuite/gcc.target/i386/invclbr1.c +++ b/gcc/testsuite/gcc.target/i386/invclbr1.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void test(void) +{ + asm ("" ::: "cc" ); + asm ("" ::: "!cc" ); + asm ("" ::: "flags" ); + asm ("" ::: "!flags" ); + asm ("" ::: "fpsr" ); + asm ("" ::: "!fpsr" ); + + asm ("" ::: "cc", "!cc" ); /* { dg-error "conflicting clobbers" } */ + asm ("" ::: "flags", "!cc" ); /* { dg-error "conflicting clobbers" } */ + asm ("" ::: "cc", "!flags" ); /* { dg-error "conflicting clobbers" } */ + asm ("" ::: "flags", "!flags" ); /* { dg-error "conflicting clobbers" } */ + asm ("" ::: "fpsr", "!fpsr" ); /* { dg-error "conflicting clobbers" } */ + + asm ("" ::: "cc", "!fpsr" ); + asm ("" ::: "flags", "!fpsr" ); + asm ("" ::: "fpsr", "!flags" ); + asm ("" ::: "fpsr", "!cc" ); +} --- a/gcc/testsuite/gcc.target/i386/invclbr2.c +++ b/gcc/testsuite/gcc.target/i386/invclbr2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-rtl-expand" } */ + +void test(void) +{ + asm ("" ::: "!cc", "!fpsr" ); + asm ("" ::: "!fpsr", "!flags" ); +} + +/* { dg-final { scan-rtl-dump-not "clobber" "expand" } } */ +/* { dg-final { cleanup-rtl-dump "expand" } } */ --- a/gcc/testsuite/gcc.target/i386/invclbr3.c +++ b/gcc/testsuite/gcc.target/i386/invclbr3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-rtl-expand" } */ + +void test(void) +{ + asm ("" ::: "!cc"); + asm ("" ::: "!flags"); + asm ("" ::: "!fpsr"); +} + +/* { dg-final { scan-rtl-dump-times "\\(clobber \\(reg\[^()\]* fpsr\\)\\)" 2 "expand" } } */ +/* { dg-final { scan-rtl-dump-times "\\(clobber \\(reg\[^()\]* flags\\)\\)" 1 "expand" } } */ +/* { dg-final { cleanup-rtl-dump "expand" } } */ --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -936,7 +936,7 @@ decode_reg_name_and_count (const char *a for (i = 0; i < (int) ARRAY_SIZE (table); i++) if (table[i].name[0] && ! strcmp (asmspec, table[i].name) - && reg_names[table[i].number][0]) + && (table[i].number < 0 || reg_names[table[i].number][0])) return table[i].number; } #endif /* ADDITIONAL_REGISTER_NAMES */