https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93582
--- Comment #35 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Unfortunately, it breaks miserably, e.g. miscompiles libcpp/macro.c. Reduced testcase from that: --- gcc/testsuite/gcc.c-torture/execute/pr93582.c.jj 2020-02-28 12:27:51.280925113 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr93582.c 2020-02-28 12:26:17.272332573 +0100 @@ -0,0 +1,22 @@ +/* PR tree-optimization/93582 */ + +short a; +int b, c; + +__attribute__((noipa)) void +foo (void) +{ + b = c; + a &= 7; +} + +int +main () +{ + c = 27; + a = 14; + foo (); + if (b != 27 || a != 6) + __builtin_abort (); + return 0; +} I believe the thing is that for the case with mask we need to completely avoid the vn_reference_lookup_or_insert_for_pieces calls that finish method does, and vn_reference_insert call visit_reference_op_load does. Probably instead of that we should call vn_nary_op_insert_stmt. Now, I wonder if e.g. finish couldn't for the masked case just return the tree itself rather than anything else, and let visit_reference_op_load not call visit_reference_op_load if mask is non-NULL.