diff options
author | Alexandre Oliva <oliva@adacore.com> | 2024-12-12 11:43:03 -0300 |
---|---|---|
committer | Alexandre Oliva <oliva@gnu.org> | 2024-12-12 11:43:03 -0300 |
commit | e8febb641415fd80eabce1c4fdf2d4a4b411213b (patch) | |
tree | fa0348850f86ba612b15272e14ddda8854e79098 /gcc/fold-const.h | |
parent | bc565843ea20a616dd376226416777a4ea1959d6 (diff) | |
download | gcc-e8febb641415fd80eabce1c4fdf2d4a4b411213b.zip gcc-e8febb641415fd80eabce1c4fdf2d4a4b411213b.tar.gz gcc-e8febb641415fd80eabce1c4fdf2d4a4b411213b.tar.bz2 |
fold fold_truth_andor field merging into ifcombine
This patch introduces various improvements to the logic that merges
field compares, while moving it into ifcombine.
Before the patch, we could merge:
(a.x1 EQNE b.x1) ANDOR (a.y1 EQNE b.y1)
into something like:
(((type *)&a)[Na] & MASK) EQNE (((type *)&b)[Nb] & MASK)
if both of A's fields live within the same alignment boundaries, and
so do B's, at the same relative positions. Constants may be used
instead of the object B.
The initial goal of this patch was to enable such combinations when a
field crossed alignment boundaries, e.g. for packed types. We can't
generally access such fields with a single memory access, so when we
come across such a compare, we will attempt to combine each access
separately.
Some merging opportunities were missed because of right-shifts,
compares expressed as e.g. ((a.x1 ^ b.x1) & MASK) EQNE 0, and
narrowing conversions, especially after earlier merges. This patch
introduces handlers for several cases involving these.
The merging of multiple field accesses into wider bitfield-like
accesses is undesirable to do too early in compilation, so we move it
from folding to ifcombine, and guard its warnings with
-Wtautological-compare, turned into a common flag.
When the second of a noncontiguous pair of compares is the first that
accesses a word, we may merge the first compare with part of the
second compare that refers to the same word, keeping the compare of
the remaining bits at the spot where the second compare used to be.
Handling compares with non-constant fields was somewhat generalized
from what fold used to do, now handling non-adjacent fields, even if a
field of one object crosses an alignment boundary but the other
doesn't.
for gcc/ChangeLog
* fold-const.cc (make_bit_field): Export.
(unextend, all_ones_mask_p): Drop.
(decode_field_reference, fold_truth_andor_1): Move
field compare merging logic...
* gimple-fold.cc: (fold_truth_andor_for_ifcombine) ... here,
with -Wtautological-compare warning guards, and...
(decode_field_reference): ... here. Rework for gimple.
(gimple_convert_def_p, gimple_binop_def_p): New.
(compute_split_boundary_from_align): New.
(make_bit_field_load, build_split_load): New.
(reuse_split_load): New.
* fold-const.h: (make_bit_field_ref): Declare
(fold_truth_andor_for_ifcombine): Declare.
* tree-ssa-ifcombine.cc (ifcombine_ifandif): Try
fold_truth_andor_for_ifcombine.
* common.opt (Wtautological-compare): Move here.
for gcc/c-family/ChangeLog
* c.opt (Wtautological-compare): Move to ../common.opt.
for gcc/testsuite/ChangeLog
* gcc.dg/field-merge-1.c: New.
* gcc.dg/field-merge-2.c: New.
* gcc.dg/field-merge-3.c: New.
* gcc.dg/field-merge-4.c: New.
* gcc.dg/field-merge-5.c: New.
* gcc.dg/field-merge-6.c: New.
* gcc.dg/field-merge-7.c: New.
* gcc.dg/field-merge-8.c: New.
* gcc.dg/field-merge-9.c: New.
* gcc.dg/field-merge-10.c: New.
* gcc.dg/field-merge-11.c: New.
* gcc.dg/field-merge-12.c: New.
* gcc.target/aarch64/long_branch_1.c: Disable ifcombine.
Diffstat (limited to 'gcc/fold-const.h')
-rw-r--r-- | gcc/fold-const.h | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/gcc/fold-const.h b/gcc/fold-const.h index 48f0648..04a9457 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -253,11 +253,21 @@ extern tree fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE extern tree_code minmax_from_comparison (tree_code, tree, tree, tree, tree); +extern tree make_bit_field_ref (location_t, tree, tree, tree, + HOST_WIDE_INT, poly_int64, int, int); + /* In gimple-fold.cc. */ extern void clear_type_padding_in_mask (tree, unsigned char *); extern bool clear_padding_type_may_have_padding_p (tree); extern bool arith_overflowed_p (enum tree_code, const_tree, const_tree, const_tree); +extern tree fold_truth_andor_for_ifcombine (enum tree_code, tree, + location_t, enum tree_code, + tree, tree, + location_t, enum tree_code, + tree, tree, + tree *); + /* Class used to compare gimple operands. */ |