[gcc r15-6253] warn-access: Fix up matching_alloc_calls_p [PR118024]

2024-12-14 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:9537ca5ad9bc23d7e9c446b4a7cbb98f63bddb6a

commit r15-6253-g9537ca5ad9bc23d7e9c446b4a7cbb98f63bddb6a
Author: Jakub Jelinek 
Date:   Sat Dec 14 11:27:20 2024 +0100

warn-access: Fix up matching_alloc_calls_p [PR118024]

The following testcase ICEs because of a bug in matching_alloc_calls_p.
The loop was apparently meant to be walking the two attribute chains
in lock-step, but doesn't really do that.  If the first lookup_attribute
returns non-NULL, the second one is not done, so rmats in that case can
be some random unrelated attribute rather than "malloc" attribute; the
body assumes even rmats if non-NULL is "malloc" attribute and relies
on its argument to be a "malloc" argument and if it is some other
attribute with incompatible attribute, it just crashes.

Now, fixing that in the obvious way, instead of doing
(amats = lookup_attribute ("malloc", amats))
 || (rmats = lookup_attribute ("malloc", rmats))
in the condition do
((amats = lookup_attribute ("malloc", amats)),
 (rmats = lookup_attribute ("malloc", rmats)),
 (amats || rmats))
fixes the testcase but regresses Wmismatched-dealloc-{2,3}.c tests.
The problem is that walking the attribute lists in a lock-step is obviously
a very bad idea, there is no requirement that the same deallocators are
present in the same order on both decls, e.g. there could be an extra malloc
attribute without argument in just one of the lists, or the order of say
free/realloc could be swapped, etc.  We don't generally document nor enforce
any particular ordering of attributes (even when for some attributes we just
handle the first one rather than all).

So, this patch instead simply splits it into two loops, the first one walks
alloc_decl attributes, the second one walks dealloc_decl attributes.
If the malloc attribute argument is a built-in, that doesn't change
anything, and otherwise we have the chance to populate the whole
common_deallocs hash_set in the first loop and then can check it in the
second one (and don't need to use more expensive add method on it, can just
check contains there).  Not to mention that it also fixes the case when
the function would incorrectly return true if there wasn't a common
deallocator between the two, but dealloc_decl had 2 malloc attributes with
the same deallocator.

2024-12-14  Jakub Jelinek  

PR middle-end/118024
* gimple-ssa-warn-access.cc (matching_alloc_calls_p): Walk malloc
attributes of alloc_decl and dealloc_decl in separate loops rather
than in lock-step.  Use common_deallocs.contains rather than
common_deallocs.add in the second loop.

* gcc.dg/pr118024.c: New test.

Diff:
---
 gcc/gimple-ssa-warn-access.cc   | 85 -
 gcc/testsuite/gcc.dg/pr118024.c | 15 
 2 files changed, 56 insertions(+), 44 deletions(-)

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 12c9ddb292dd..820f23825254 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -1935,52 +1935,49 @@ matching_alloc_calls_p (tree alloc_decl, tree 
dealloc_decl)
  headers.
  With AMATS set to the Allocator's Malloc ATtributes,
  and  RMATS set to Reallocator's Malloc ATtributes...  */
-  for (tree amats = DECL_ATTRIBUTES (alloc_decl),
-rmats = DECL_ATTRIBUTES (dealloc_decl);
-   (amats = lookup_attribute ("malloc", amats))
-|| (rmats = lookup_attribute ("malloc", rmats));
-   amats = amats ? TREE_CHAIN (amats) : NULL_TREE,
-rmats = rmats ? TREE_CHAIN (rmats) : NULL_TREE)
-{
-  if (tree args = amats ? TREE_VALUE (amats) : NULL_TREE)
-   if (tree adealloc = TREE_VALUE (args))
- {
-   if (DECL_P (adealloc)
-   && fndecl_built_in_p (adealloc, BUILT_IN_NORMAL))
- {
-   built_in_function fncode = DECL_FUNCTION_CODE (adealloc);
-   if (fncode == BUILT_IN_FREE || fncode == BUILT_IN_REALLOC)
- {
-   if (realloc_kind == alloc_kind_t::builtin)
- return true;
-   alloc_dealloc_kind = alloc_kind_t::builtin;
- }
-   continue;
- }
-
-   common_deallocs.add (adealloc);
- }
+  for (tree amats = DECL_ATTRIBUTES (alloc_decl);
+   (amats = lookup_attribute ("malloc", amats));
+   amats = amats ? TREE_CHAIN (amats) : NULL_TREE)
+if (tree args = amats ? TREE_VALUE (amats) : NULL_TREE)
+  if (tree adealloc = TREE_VALUE (args))
+   {
+ if (DECL_P (adealloc)
+ && fndecl_built_in_p (adealloc, BUILT_IN_NORMAL))
+   {
+ built_in_function fncode = DECL_FUNCTION_CODE (adealloc);
+ if (fncode == BUILT_IN_FREE || fncode == BUILT_IN_REALLOC)

[gcc r15-6254] gimple-fold: Fix the recent ifcombine optimization for _BitInt [PR118023]

2024-12-14 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:7f4e85a954d24cc30bf85f4040fcd204bd5e23fd

commit r15-6254-g7f4e85a954d24cc30bf85f4040fcd204bd5e23fd
Author: Jakub Jelinek 
Date:   Sat Dec 14 11:28:25 2024 +0100

gimple-fold: Fix the recent ifcombine optimization for _BitInt [PR118023]

The BIT_FIELD_REF verifier has:
  if (INTEGRAL_TYPE_P (TREE_TYPE (op))
  && !type_has_mode_precision_p (TREE_TYPE (op)))
{
  error ("%qs of non-mode-precision operand", code_name);
  return true;
}
check among other things, so one can't extract something out of say
_BitInt(63) or _BitInt(4096).
The new ifcombine optimization happily creates such BIT_FIELD_REFs
and ICEs during their verification.

The following patch fixes that by rejecting those in decode_field_reference.

2024-12-14  Jakub Jelinek  

PR tree-optimization/118023
* gimple-fold.cc (decode_field_reference): Return NULL_TREE if
inner has non-type_has_mode_precision_p integral type.

* gcc.dg/bitint-119.c: New test.

Diff:
---
 gcc/gimple-fold.cc|  4 +++-
 gcc/testsuite/gcc.dg/bitint-119.c | 11 +++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index e1b4b65dd662..6c11654a2c65 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -7643,7 +7643,9 @@ decode_field_reference (tree *pexp, HOST_WIDE_INT 
*pbitsize,
   /* Reject out-of-bound accesses (PR79731).  */
   || (! AGGREGATE_TYPE_P (TREE_TYPE (inner))
  && compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)),
-  bp + bs) < 0))
+  bp + bs) < 0)
+  || (INTEGRAL_TYPE_P (TREE_TYPE (inner))
+ && !type_has_mode_precision_p (TREE_TYPE (inner
 return NULL_TREE;
 
   *pbitsize = bs;
diff --git a/gcc/testsuite/gcc.dg/bitint-119.c 
b/gcc/testsuite/gcc.dg/bitint-119.c
new file mode 100644
index ..8283d50b3a68
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-119.c
@@ -0,0 +1,11 @@
+/* PR tree-optimization/118023 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-O2" } */
+
+_BitInt(63) b;
+
+int
+foo (void)
+{
+  return !*(_Complex char *) &b;
+}


[gcc r15-6255] doc: Fix typos for --enable-host-pie docs in install.texi

2024-12-14 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:a7df4961d171ef071bd0972335d6f116d420eb13

commit r15-6255-ga7df4961d171ef071bd0972335d6f116d420eb13
Author: Heiko Eißfeldt 
Date:   Sat Dec 14 12:31:58 2024 +

doc: Fix typos for --enable-host-pie docs in install.texi

gcc/ChangeLog:

* doc/install.texi (Configuration): Fix typos in documentation
for --enable-host-pie.

Diff:
---
 gcc/doc/install.texi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index feabf4cbe20b..9109c172039c 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1119,7 +1119,7 @@ yielding a slightly slower compiler (but faster than
 at random addresses each time they are executed, therefore provide additional
 protection against Return Oriented Programming (ROP) attacks.
 
-@option{--enable-host-pie}) may be used with @option{--enable-host-shared}),
+@option{--enable-host-pie} may be used with @option{--enable-host-shared},
 in which case @option{-fPIC} is used when compiling, and @option{-pie} when
 linking.


[gcc r14-11089] [PATCH] PR modula2/117120: case ch with a nul char constant causes ICE

2024-12-14 Thread Gaius Mulley via Gcc-cvs
https://gcc.gnu.org/g:cfe21668f3a7a0f07fa1e79ef2561a107a09a67d

commit r14-11089-gcfe21668f3a7a0f07fa1e79ef2561a107a09a67d
Author: Gaius Mulley 
Date:   Sat Dec 14 11:46:57 2024 +

[PATCH] PR modula2/117120: case ch with a nul char constant causes ICE

This patch fixes the ICE caused when a case clause contains
a character constant ''.  The fix was to walk the caselist and
convert any 0 length string into a char constant of value 0.

gcc/m2/ChangeLog:

PR modula2/117120
* gm2-compiler/M2CaseList.mod (CaseBoundsResolved): Rewrite.
(ConvertNulStr2NulChar): New procedure function.
(NulStr2NulChar): Ditto.
(GetCaseExpression): Ditto.
(OverlappingCaseBound): Rewrite.
* gm2-compiler/M2GCCDeclare.mod (CheckResolveSubrange): Allow
'' to be used as the subrange low limit.
* gm2-compiler/M2GenGCC.mod (FoldConvert): Rewrite.
(PopKindTree): Ditto.
(BuildHighFromString): Reformat.
* gm2-compiler/SymbolTable.mod (PushConstString): Add test for
length 0 and PushChar (nul).

gcc/testsuite/ChangeLog:

PR modula2/117120
* gm2/pim/pass/forloopnulchar.mod: New test.
* gm2/pim/pass/nulcharcase.mod: New test.
* gm2/pim/pass/nulcharvar.mod: New test.

(cherry picked from commit e0ab8816ea53e2a343f7e945f4718172bff5ce95)

Signed-off-by: Gaius Mulley 

Diff:
---
 gcc/m2/gm2-compiler/M2CaseList.mod| 150 +-
 gcc/m2/gm2-compiler/M2GCCDeclare.mod  |   4 +-
 gcc/m2/gm2-compiler/M2GenGCC.mod  | 130 +++---
 gcc/m2/gm2-compiler/SymbolTable.mod   |   8 +-
 gcc/testsuite/gm2/pim/pass/forloopnulchar.mod |   8 ++
 gcc/testsuite/gm2/pim/pass/nulcharcase.mod|  16 +++
 gcc/testsuite/gm2/pim/pass/nulcharvar.mod |   7 ++
 7 files changed, 231 insertions(+), 92 deletions(-)

diff --git a/gcc/m2/gm2-compiler/M2CaseList.mod 
b/gcc/m2/gm2-compiler/M2CaseList.mod
index 7a889bd5d8bf..7fcfe1b40722 100644
--- a/gcc/m2/gm2-compiler/M2CaseList.mod
+++ b/gcc/m2/gm2-compiler/M2CaseList.mod
@@ -27,10 +27,10 @@ FROM M2GCCDeclare IMPORT TryDeclareConstant, GetTypeMin, 
GetTypeMax ;
 FROM M2MetaError IMPORT MetaError1, MetaError2, MetaErrorT0, MetaErrorT1, 
MetaErrorT2, MetaErrorT3, MetaErrorT4, MetaErrorStringT0, MetaErrorString1 ;
 FROM M2Error IMPORT InternalError ;
 FROM M2Range IMPORT OverlapsRange, IsEqual, IsGreater ;
-FROM M2ALU IMPORT PushIntegerTree, PopIntegerTree, Addn, Sub, PushInt ;
+FROM M2ALU IMPORT PushIntegerTree, PopIntegerTree, Addn, Sub, PushInt, 
PushCard ;
 FROM Indexing IMPORT Index, InitIndex, PutIndice, GetIndice, 
ForeachIndiceInIndexDo, HighIndice ;
 FROM Lists IMPORT InitList, IncludeItemIntoList, RemoveItemFromList, 
NoOfItemsInList, GetItemFromList ;
-FROM NameKey IMPORT KeyToCharStar ;
+FROM NameKey IMPORT NulName, KeyToCharStar ;
 FROM SymbolConversion IMPORT GccKnowsAbout, Mod2Gcc, AddModGcc ;
 FROM DynamicStrings IMPORT InitString, InitStringCharStar, InitStringChar, 
ConCat, Mark, KillString ;
 FROM gcctypes IMPORT tree ;
@@ -44,7 +44,8 @@ FROM NumberIO IMPORT WriteCard ;
 
 FROM SymbolTable IMPORT NulSym, IsConst, IsFieldVarient, IsRecord, 
IsRecordField, GetVarientTag, GetType,
 ForeachLocalSymDo, GetSymName, IsEnumeration, 
SkipType, NoOfElements, GetNth,
-IsSubrange ;
+IsSubrange, MakeConstLit, IsConstString, 
GetStringLength, MakeConstVar, PutConst,
+PopValue ;
 
 TYPE
RangePair = POINTER TO RECORD
@@ -64,6 +65,7 @@ TYPE
   END ;
 
CaseDescriptor = POINTER TO RECORD
+   resolved : BOOLEAN ;
elseClause   : BOOLEAN ;
elseField: CARDINAL ;
record   : CARDINAL ;
@@ -110,6 +112,7 @@ BEGIN
   InternalError ('out of memory error')
ELSE
   WITH c^ DO
+ resolved := FALSE ;
  elseClause := FALSE ;
  elseField := NulSym ;
  record := rec ;
@@ -244,7 +247,30 @@ END GetVariantTagType ;
 
 PROCEDURE CaseBoundsResolved (tokenno: CARDINAL; c: CARDINAL) : BOOLEAN ;
 VAR
-   resolved: BOOLEAN ;
+   p: CaseDescriptor ;
+BEGIN
+   p := GetIndice (caseArray, c) ;
+   IF p^.resolved
+   THEN
+  RETURN TRUE
+   ELSE
+  IF CheckCaseBoundsResolved (tokenno, c)
+  THEN
+ ConvertNulStr2NulChar (tokenno, c) ;
+ RETURN TRUE
+  ELSE
+ RETURN FALSE
+  END
+   END
+END CaseBoundsResolved ;
+
+
+(*
+   CheckCaseBoundsResolved - return TRUE if all constants in the case list c 
are known to GCC.
+*)
+
+PROCEDURE CheckCaseBoundsResolved (tokenno: CARDINAL; c: CARDINAL) : BOOLEAN ;
+VAR
p   : CaseDescriptor ;
q   : CaseList ;
r   : RangePair ;
@@ -327,7 +353,62 @@ BEGIN
   END

[gcc r15-6252] opts: Use OPTION_SET_P instead of magic value 2 for -fshort-enums default [PR118011]

2024-12-14 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:18f0b7d5f370c47633837e935f8a6e1b8616b56b

commit r15-6252-g18f0b7d5f370c47633837e935f8a6e1b8616b56b
Author: Jakub Jelinek 
Date:   Sat Dec 14 11:25:08 2024 +0100

opts: Use OPTION_SET_P instead of magic value 2 for -fshort-enums default 
[PR118011]

The magic values for default (usually -1 or sometimes 2) for some options
are from times we haven't global_options_set, I think we should eventually
get rid of all of those.

The PR is about gcc -Q --help=optimizers reporting -fshort-enums as
[enabled] when it is disabled.
For this the following patch is just partial fix; with explicit
gcc -Q --help=optimizers -fshort-enums
or
gcc -Q --help=optimizers -fno-short-enums
it already worked correctly before, with this patch it will report
even with just
gcc -Q --help=optimizers
correct value on most targets, except 32-bit arm with some options or
defaults, so I think it is a step in the right direction.

But, as I wrote in the PR, process_options isn't done before --help=
and even shouldn't be in its current form where it warns on some option
combinations or errors or emits sorry on others, so I think ideally
process_options should have some bool argument whether it is done for
--help= purposes or not, if yes, not emit warnings and just adjust the
options, otherwise do what it currently does.

2024-12-14  Jakub Jelinek  

PR c/118011
gcc/
* opts.cc (init_options_struct): Don't set opts->x_flag_short_enums 
to
2.
* toplev.cc (process_options): Test !OPTION_SET_P (flag_short_enums)
rather than flag_short_enums == 2.
gcc/ada/
* gcc-interface/misc.cc (gnat_post_options): Test
!OPTION_SET_P (flag_short_enums) rather than flag_short_enums == 2.

Diff:
---
 gcc/ada/gcc-interface/misc.cc | 2 +-
 gcc/opts.cc   | 3 ---
 gcc/toplev.cc | 2 +-
 3 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/gcc/ada/gcc-interface/misc.cc b/gcc/ada/gcc-interface/misc.cc
index c7c735e57639..d3f8ffa8692c 100644
--- a/gcc/ada/gcc-interface/misc.cc
+++ b/gcc/ada/gcc-interface/misc.cc
@@ -283,7 +283,7 @@ gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED)
   /* Unfortunately the post_options hook is called before the value of
  flag_short_enums is autodetected, if need be.  Mimic the process
  for our private flag_short_enums.  */
-  if (flag_short_enums == 2)
+  if (!OPTION_SET_P (flag_short_enums))
 flag_short_enums = targetm.default_short_enums ();
 
   return false;
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 9909d4a4fc50..fa64bb7734a9 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -444,9 +444,6 @@ init_options_struct (struct gcc_options *opts, struct 
gcc_options *opts_set)
 
   /* Initialize whether `char' is signed.  */
   opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR;
-  /* Set this to a special "uninitialized" value.  The actual default
- is set after target options have been processed.  */
-  opts->x_flag_short_enums = 2;
 
   /* Initialize target_flags before default_options_optimization
  so the latter can modify it.  */
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 370d7f39f218..5f19ebb5cf2a 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -1300,7 +1300,7 @@ process_options ()
   flag_section_anchors = 0;
 }
 
-  if (flag_short_enums == 2)
+  if (!OPTION_SET_P (flag_short_enums))
 flag_short_enums = targetm.default_short_enums ();
 
   /* Set aux_base_name if not already set.  */


[gcc r15-6256] bpf: fix build adding new required arg to RESOLVE_OVERLOADED_BUILTIN

2024-12-14 Thread Jose E. Marchesi via Gcc-cvs
https://gcc.gnu.org/g:6866547e2421cc40606c13c2c3621a3d9121e893

commit r15-6256-g6866547e2421cc40606c13c2c3621a3d9121e893
Author: Jose E. Marchesi 
Date:   Sat Dec 14 19:15:34 2024 +0100

bpf: fix build adding new required arg to RESOLVE_OVERLOADED_BUILTIN

gcc/ChangeLog

* config/bpf/bpf.cc (bpf_resolve_overloaded_builtin): Add argument
`complain'.

Diff:
---
 gcc/config/bpf/bpf.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index fd913ecdb655..9a927e3a6ff1 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -1084,7 +1084,8 @@ bpf_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
 #define TARGET_EXPAND_BUILTIN bpf_expand_builtin
 
 static tree
-bpf_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist)
+bpf_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist,
+   bool complain ATTRIBUTE_UNUSED)
 {
   int code = DECL_MD_FUNCTION_CODE (fndecl);
   if (code > BPF_CORE_BUILTINS_MARKER)


[gcc r15-6258] libbacktrace: don't use ZSTD_CLEVEL_DEFAULT

2024-12-14 Thread Ian Lance Taylor via Gcc-cvs
https://gcc.gnu.org/g:3e343ef7f0ac0eb9e526b4f6d3bf3f69be3f0684

commit r15-6258-g3e343ef7f0ac0eb9e526b4f6d3bf3f69be3f0684
Author: Ian Lance Taylor 
Date:   Sat Dec 14 14:32:11 2024 -0800

libbacktrace: don't use ZSTD_CLEVEL_DEFAULT

PR 117812 reports that testing GCC with zstd 1.3.4 fails because
ZSTD_CLEVEL_DEFAULT is not defined, so avoid using it.

PR libbacktrace/117812
* zstdtest.c (test_large): Use 3 rather than ZSTD_CLEVEL_DEFAULT

Diff:
---
 libbacktrace/zstdtest.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libbacktrace/zstdtest.c b/libbacktrace/zstdtest.c
index b9552ab1b882..eb572a24e52f 100644
--- a/libbacktrace/zstdtest.c
+++ b/libbacktrace/zstdtest.c
@@ -379,8 +379,7 @@ test_large (struct backtrace_state *state ATTRIBUTE_UNUSED)
 }
 
   r = ZSTD_compress (compressed_buf, compressed_bufsize,
-orig_buf, orig_bufsize,
-ZSTD_CLEVEL_DEFAULT);
+orig_buf, orig_bufsize, 3);
   if (ZSTD_isError (r))
 {
   fprintf (stderr, "zstd compress failed: %s\n", ZSTD_getErrorName (r));


[gcc r15-6257] [PATCH v3] match.pd: Add pattern to simplify `(a - 1) & -a` to `0`

2024-12-14 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:ad519f46194a7ab1671470a236c67ae17cb98ead

commit r15-6257-gad519f46194a7ab1671470a236c67ae17cb98ead
Author: Jovan Vukic 
Date:   Sat Dec 14 14:47:35 2024 -0700

[PATCH v3] match.pd: Add pattern to simplify `(a - 1) & -a` to `0`

Thank you for the feedback. I have made the minor changes that were 
requested.
Additionally, I extracted the repetitive code into a reusable helper 
function,
match_plus_neg_pattern, making the code much more readable. Furthermore, the
logic, code, and tests remain the same as in version 2 of the patch.

gcc/ChangeLog:

* match.pd: New pattern.
* simplify-rtx.cc (match_plus_neg_pattern): New helper function.
(simplify_context::simplify_binary_operation_1): New
code to handle (a - 1) & -a, (a - 1) | -a and (a - 1) ^ -a.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/bitops-11.c: New test.

Diff:
---
 gcc/match.pd  |  16 
 gcc/simplify-rtx.cc   |  41 +++
 gcc/testsuite/gcc.dg/tree-ssa/bitops-11.c | 117 ++
 3 files changed, 174 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index 4587658aa0a4..c43e51c96b7c 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1472,6 +1472,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (bit_and:c @0 (bit_not (bit_xor:c @0 @1)))
  (bit_and @0 @1))
 
+/* Transform:
+   (a - 1) & -a ->  0.
+   (a - 1) | -a -> -1.
+   (a - 1) ^ -a -> -1.  */
+(for bit_op (bit_ior bit_xor bit_and)
+ (simplify
+  (bit_op:c (plus @0 integer_minus_onep) (negate @0))
+  (if (bit_op == BIT_AND_EXPR)
+{ build_zero_cst (type); }
+{ build_minus_one_cst (type); }))
+ (simplify
+  (bit_op:c (minus @0 integer_onep) (negate @0))
+  (if (bit_op == BIT_AND_EXPR)
+{ build_zero_cst (type); }
+{ build_minus_one_cst (type); })))
+
 /* a & (a == b)  -->  a & b (boolean version of the above). */
 (simplify
  (bit_and:c @0 (nop_convert? (eq:c @0 @1)))
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 86b3f3319285..223a00959786 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -2941,6 +2941,35 @@ simplify_rotate_op (rtx op0, rtx op1, machine_mode mode)
   return NULL_RTX;
 }
 
+/* Returns true if OP0 and OP1 match the pattern (OP (plus (A - 1)) (neg A)),
+   and the pattern can be simplified (there are no side effects).  */
+
+static bool
+match_plus_neg_pattern (rtx op0, rtx op1, machine_mode mode)
+{
+  /* Remove SUBREG from OP0 and OP1, if needed.  */
+  if (GET_CODE (op0) == SUBREG
+  && GET_CODE (op1) == SUBREG
+  && subreg_lowpart_p (op0)
+  && subreg_lowpart_p (op1))
+{
+  op0 = XEXP (op0, 0);
+  op1 = XEXP (op1, 0);
+}
+
+  /* Check for the pattern (OP (plus (A - 1)) (neg A)).  */
+  if (((GET_CODE (op1) == NEG
+   && GET_CODE (op0) == PLUS
+   && XEXP (op0, 1) == CONSTM1_RTX (mode))
+   || (GET_CODE (op0) == NEG
+  && GET_CODE (op1) == PLUS
+  && XEXP (op1, 1) == CONSTM1_RTX (mode)))
+  && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
+  && !side_effects_p (XEXP (op0, 0)))
+return true;
+  return false;
+}
+
 /* Subroutine of simplify_binary_operation.  Simplify a binary operation
CODE with result mode MODE, operating on OP0 and OP1.  If OP0 and/or
OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the
@@ -3553,6 +3582,10 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
  && GET_MODE_CLASS (mode) != MODE_CC)
return CONSTM1_RTX (mode);
 
+  /* Convert (ior (plus (A - 1)) (neg A)) to -1.  */
+  if (match_plus_neg_pattern (op0, op1, mode))
+   return CONSTM1_RTX (mode);
+
   /* (ior A C) is C if all bits of A that might be nonzero are on in C.  */
   if (CONST_INT_P (op1)
  && HWI_COMPUTABLE_MODE_P (mode)
@@ -3714,6 +3747,10 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
  & nonzero_bits (op1, mode)) == 0)
return (simplify_gen_binary (IOR, mode, op0, op1));
 
+  /* Convert (xor (plus (A - 1)) (neg A)) to -1.  */
+  if (match_plus_neg_pattern (op0, op1, mode))
+   return CONSTM1_RTX (mode);
+
   /* Convert (XOR (NOT x) (NOT y)) to (XOR x y).
 Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for
 (NOT y).  */
@@ -3981,6 +4018,10 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
  && GET_MODE_CLASS (mode) != MODE_CC)
return CONST0_RTX (mode);
 
+  /* Convert (and (plus (A - 1)) (neg A)) to 0.  */
+  if (match_plus_neg_pattern (op0, op1, mode))
+   return CONST0_RTX (mode);
+
   /* Transform (and (extend X) C) into (zero_extend (and X C)) if
 there are no nonzero bits of C outside of X's mode.  */
   if ((GET_CODE (op0) == SIGN_EXTEND
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitops-11.c 
b/gcc/testsuite/gcc.dg/tree-ssa/bitops-11.c
new file mode 100644
inde