diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-12-09 08:43:50 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-12-09 08:43:50 +0000 |
commit | b449f0f62d0f5bca66a63b7cf568a154e5875c7f (patch) | |
tree | 2865911f6be9230d5926e0a1ba4cdc57364804fb | |
parent | 4b844fc9297c7ea82ff46d86547e9bee5182025a (diff) | |
download | gcc-b449f0f62d0f5bca66a63b7cf568a154e5875c7f.tar.gz |
2016-12-09 Richard Biener <rguenther@suse.de>
Backport from mainline
2016-11-28 Richard Biener <rguenther@suse.de>
PR tree-optimization/78542
* tree-ssa-ccp.c (evaluate_stmt): Only valueize simplification
if allowed.
* gcc.dg/torture/pr78542.c: New testcase.
2016-11-23 Richard Biener <rguenther@suse.de>
PR tree-optimization/78482
* tree-cfgcleanup.c: Include tree-ssa-loop-niter.h.
(remove_forwarder_block_with_phi): When merging with a loop
header creates a new latch reset number of iteration information
of the loop.
* gcc.dg/torture/pr78482.c: New testcase.
2016-11-23 Richard Biener <rguenther@suse.de>
PR middle-end/71762
* match.pd ((~X & Y) -> X < Y, (X & ~Y) -> Y < X,
(~X | Y) -> X <= Y, (X | ~Y) -> Y <= X): Remove.
* gcc.dg/torture/pr71762-1.c: New testcase.
* gcc.dg/torture/pr71762-2.c: Likewise.
* gcc.dg/torture/pr71762-3.c: Likewise.
* gcc.dg/tree-ssa/forwprop-28.c: XFAIL.
2016-11-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/71575
* graphite-isl-ast-to-gimple.c (copy_cond_phi_nodes): Remove
bogus assert.
* gcc.dg/graphite/pr71575-1.c: New testcase.
* gcc.dg/graphite/pr71575-2.c: Likewise.
2016-11-07 Richard Biener <rguenther@suse.de>
PR tree-optimization/78224
* tree-call-cdce.c (shrink_wrap_one_built_in_call_with_conds):
Split the fallthru edge in case its successor may have PHIs.
* g++.dg/torture/pr78224.C: New testcase.
2016-11-05 David Edelsohn <dje.gcc@gmail.com>
Richard Biener <rguenther@suse.de>
PR bootstrap/78188
PR c++/71848
* ipa-comdats.c (pass_ipa_comdats::gate): Require HAVE_COMDAT_GROUP.
* g++.dg/ipa/pr78188.C: New test.
2016-09-20 Richard Biener <rguenther@suse.de>
PR tree-optimization/77646
* tree-ssa-sccvn.c (visit_reference_op_call): Always value-number
a VDEF.
* gcc.dg/torture/pr77646.c: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-6-branch@243475 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 48 | ||||
-rw-r--r-- | gcc/graphite-isl-ast-to-gimple.c | 3 | ||||
-rw-r--r-- | gcc/ipa-comdats.c | 2 | ||||
-rw-r--r-- | gcc/match.pd | 27 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 44 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/pr78188.C | 20 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr78224.C | 51 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/graphite/pr71575-1.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/graphite/pr71575-2.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr71762-1.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr71762-2.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr71762-3.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr77646.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr78482.c | 46 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr78542.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c | 4 | ||||
-rw-r--r-- | gcc/tree-call-cdce.c | 12 | ||||
-rw-r--r-- | gcc/tree-cfgcleanup.c | 13 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 7 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 4 |
20 files changed, 384 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0c1ad90e1a8..a46f1e87461 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,51 @@ +2016-12-09 Richard Biener <rguenther@suse.de> + + Backport from mainline + 2016-11-28 Richard Biener <rguenther@suse.de> + + PR tree-optimization/78542 + * tree-ssa-ccp.c (evaluate_stmt): Only valueize simplification + if allowed. + + 2016-11-23 Richard Biener <rguenther@suse.de> + + PR tree-optimization/78482 + * tree-cfgcleanup.c: Include tree-ssa-loop-niter.h. + (remove_forwarder_block_with_phi): When merging with a loop + header creates a new latch reset number of iteration information + of the loop. + + 2016-11-23 Richard Biener <rguenther@suse.de> + + PR middle-end/71762 + * match.pd ((~X & Y) -> X < Y, (X & ~Y) -> Y < X, + (~X | Y) -> X <= Y, (X | ~Y) -> Y <= X): Remove. + + 2016-11-11 Richard Biener <rguenther@suse.de> + + PR tree-optimization/71575 + * graphite-isl-ast-to-gimple.c (copy_cond_phi_nodes): Remove + bogus assert. + + 2016-11-07 Richard Biener <rguenther@suse.de> + + PR tree-optimization/78224 + * tree-call-cdce.c (shrink_wrap_one_built_in_call_with_conds): + Split the fallthru edge in case its successor may have PHIs. + + 2016-11-05 David Edelsohn <dje.gcc@gmail.com> + Richard Biener <rguenther@suse.de> + + PR bootstrap/78188 + PR c++/71848 + * ipa-comdats.c (pass_ipa_comdats::gate): Require HAVE_COMDAT_GROUP. + + 2016-09-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/77646 + * tree-ssa-sccvn.c (visit_reference_op_call): Always value-number + a VDEF. + 2016-12-07 Segher Boessenkool <segher@kernel.crashing.org> Backport from mainline diff --git a/gcc/graphite-isl-ast-to-gimple.c b/gcc/graphite-isl-ast-to-gimple.c index fb9c8468ebc..fba6cfb1851 100644 --- a/gcc/graphite-isl-ast-to-gimple.c +++ b/gcc/graphite-isl-ast-to-gimple.c @@ -2493,9 +2493,6 @@ copy_cond_phi_nodes (basic_block bb, basic_block new_bb, vec<tree> iv_map) tree res = gimple_phi_result (phi); if (virtual_operand_p (res)) continue; - if (is_gimple_reg (res) && scev_analyzable_p (res, region->region)) - /* Cond phi nodes should not be scev_analyzable_p. */ - gcc_unreachable (); gphi *new_phi = create_phi_node (SSA_NAME_VAR (res), new_bb); tree new_res = create_new_def_for (res, new_phi, diff --git a/gcc/ipa-comdats.c b/gcc/ipa-comdats.c index 6e0f7622366..321bc0fc788 100644 --- a/gcc/ipa-comdats.c +++ b/gcc/ipa-comdats.c @@ -416,7 +416,7 @@ public: bool pass_ipa_comdats::gate (function *) { - return optimize; + return HAVE_COMDAT_GROUP && optimize; } } // anon namespace diff --git a/gcc/match.pd b/gcc/match.pd index e2e33ed012f..c579781e4c5 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -828,33 +828,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (op:c truth_valued_p@0 (logical_inverted_value @0)) { constant_boolean_node (op == NE_EXPR ? true : false, type); })) -/* If arg1 and arg2 are booleans (or any single bit type) - then try to simplify: - - (~X & Y) -> X < Y - (X & ~Y) -> Y < X - (~X | Y) -> X <= Y - (X | ~Y) -> Y <= X - - But only do this if our result feeds into a comparison as - this transformation is not always a win, particularly on - targets with and-not instructions. - -> simplify_bitwise_binary_boolean */ -(simplify - (ne (bit_and:c (bit_not @0) @1) integer_zerop) - (if (INTEGRAL_TYPE_P (TREE_TYPE (@1)) - && TYPE_PRECISION (TREE_TYPE (@1)) == 1) - (if (TYPE_UNSIGNED (TREE_TYPE (@1))) - (lt @0 @1) - (gt @0 @1)))) -(simplify - (ne (bit_ior:c (bit_not @0) @1) integer_zerop) - (if (INTEGRAL_TYPE_P (TREE_TYPE (@1)) - && TYPE_PRECISION (TREE_TYPE (@1)) == 1) - (if (TYPE_UNSIGNED (TREE_TYPE (@1))) - (le @0 @1) - (ge @0 @1)))) - /* ~~x -> x */ (simplify (bit_not (bit_not @0)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b70803ca0b1..35ef73ad484 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,47 @@ +2016-12-09 Richard Biener <rguenther@suse.de> + + Backport from mainline + 2016-11-28 Richard Biener <rguenther@suse.de> + + PR tree-optimization/78542 + * gcc.dg/torture/pr78542.c: New testcase. + + 2016-11-23 Richard Biener <rguenther@suse.de> + + PR tree-optimization/78482 + * gcc.dg/torture/pr78482.c: New testcase. + + 2016-11-23 Richard Biener <rguenther@suse.de> + + PR middle-end/71762 + * gcc.dg/torture/pr71762-1.c: New testcase. + * gcc.dg/torture/pr71762-2.c: Likewise. + * gcc.dg/torture/pr71762-3.c: Likewise. + * gcc.dg/tree-ssa/forwprop-28.c: XFAIL. + + 2016-11-11 Richard Biener <rguenther@suse.de> + + PR tree-optimization/71575 + * gcc.dg/graphite/pr71575-1.c: New testcase. + * gcc.dg/graphite/pr71575-2.c: Likewise. + + 2016-11-07 Richard Biener <rguenther@suse.de> + + PR tree-optimization/78224 + * g++.dg/torture/pr78224.C: New testcase. + + 2016-11-05 David Edelsohn <dje.gcc@gmail.com> + Richard Biener <rguenther@suse.de> + + PR bootstrap/78188 + PR c++/71848 + * g++.dg/ipa/pr78188.C: New test. + + 2016-09-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/77646 + * gcc.dg/torture/pr77646.c: New testcase. + 2016-12-08 Nathan Sidwell <nathan@acm.org> PR c++/78551 diff --git a/gcc/testsuite/g++.dg/ipa/pr78188.C b/gcc/testsuite/g++.dg/ipa/pr78188.C new file mode 100644 index 00000000000..f6ee654471e --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr78188.C @@ -0,0 +1,20 @@ +// { dg-do compile } +// { dg-options "-O2 -fno-exceptions" } + +int a; +static void __attribute__((noinline)) foo () { a = 1; } +static void __attribute__((noinline)) foo2 () { a = 2; } + +struct X +{ + virtual void bar (int i) { if (!i) { foo (); __builtin_abort (); } } +}; + +void baz (int i) +{ + if (!i) + { foo2 (); __builtin_abort (); } +} + +X xx; + diff --git a/gcc/testsuite/g++.dg/torture/pr78224.C b/gcc/testsuite/g++.dg/torture/pr78224.C new file mode 100644 index 00000000000..bb85339e8f8 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr78224.C @@ -0,0 +1,51 @@ +// { dg-do compile } + +extern "C"{ + float sqrtf(float); +} + +inline float squareroot(const float f) +{ + return sqrtf(f); +} + +inline int squareroot(const int f) +{ + return static_cast<int>(sqrtf(static_cast<float>(f))); +} + +template <class T> +class vector2d +{ +public: + vector2d(T nx, T ny) : X(nx), Y(ny) {} + T getLength() const { return squareroot( X*X + Y*Y ); } + T X; + T Y; +}; + +vector2d<int> getMousePos(); + +class Client +{ +public: + Client(); + ~Client(); +}; + +void the_game(float turn_amount) +{ + Client client; + bool first = true; + + while (1) { + if (first) { + first = false; + } else { + int dx = getMousePos().X; + int dy = getMousePos().Y; + + turn_amount = vector2d<float>(dx, dy).getLength(); + } + } +} diff --git a/gcc/testsuite/gcc.dg/graphite/pr71575-1.c b/gcc/testsuite/gcc.dg/graphite/pr71575-1.c new file mode 100644 index 00000000000..4a8623e3c04 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr71575-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -floop-nest-optimize" } */ + +void w(int x, double *y) +{ + int i, j; + double a; + double c[32]; + + for (i = 0; i < x; i++) { + for (j = 0; j < x - i; j++) { + c[j] = y[i]; + } + y[i] = a; + a += c[0] + y[i]; + } +} + +void v(int x, double *y) +{ + w(x, y); +} diff --git a/gcc/testsuite/gcc.dg/graphite/pr71575-2.c b/gcc/testsuite/gcc.dg/graphite/pr71575-2.c new file mode 100644 index 00000000000..24bc957b2d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr71575-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast -floop-nest-optimize" } */ + +int *a; +int b, c, d, e, g; +char f; + +void fn1() { + for (; c;) { + b = 0; + for (; b <= 2; b++) { + unsigned **h = (unsigned **) &a[b]; + *h = (unsigned *)(__UINTPTR_TYPE__)((g && (e = d)) != f++); + } + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr71762-1.c b/gcc/testsuite/gcc.dg/torture/pr71762-1.c new file mode 100644 index 00000000000..d20cbc32c97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr71762-1.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-additional-options "-fdisable-rtl-init-regs" } */ + +static _Bool +foo (_Bool a, _Bool b) +{ + int x = a && ! b; + return x != 0; +} + +int y = 1; +int main() +{ + _Bool x; + if (foo (x, y)) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr71762-2.c b/gcc/testsuite/gcc.dg/torture/pr71762-2.c new file mode 100644 index 00000000000..65047cb4fb3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr71762-2.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ + +static _Bool +foo (_Bool a, _Bool b) +{ + int x = a && ! b; + return x != 0; +} + +int y = 1; +int main() +{ + _Bool x[32]; + if (foo (x[1], y)) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr71762-3.c b/gcc/testsuite/gcc.dg/torture/pr71762-3.c new file mode 100644 index 00000000000..4fd5f98da87 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr71762-3.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ + +static _Bool +foo (_Bool a, _Bool b) +{ + int x = a && ! b; + return x != 0; +} + +int y = 1; +int main() +{ + register _Bool x + /* Add register spec for the argv parameter to main. */ +#if __i386__ || __x86_64__ + __asm__("%esi") +#endif + ; + if (foo (x, y)) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr77646.c b/gcc/testsuite/gcc.dg/torture/pr77646.c new file mode 100644 index 00000000000..1b1990037bf --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr77646.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +struct e { + int (*f)(); + void (*g)(); +} * c; +int a; +void *h(); +typedef struct { struct e j; } k; +int l() { return a; } +const struct e b = {l}; +void m() +{ + k *d = h(); + d->j = b; + c = (struct e *)d; + struct e *i = c; + if (i->f(c)) + while (i->f(c)) + i->g(); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr78482.c b/gcc/testsuite/gcc.dg/torture/pr78482.c new file mode 100644 index 00000000000..cbf4d19d721 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr78482.c @@ -0,0 +1,46 @@ +/* PR tree-optimization/78482 */ +/* { dg-do run } */ + +short a = 65531; +int b = 3, f; +signed char c, d; +static void fn1(int p1) +{ + short e; + b = f; + if (f > p1 && p1) + L: + for (e = 0; 0;) + ; + else if (d) b = 0 >= b; + for (; e <= 3; e++) + { + if (b) + continue; + b = 3; + goto L; + } +} + +__attribute__((noinline, noclone)) +int bar (const char *x, int y) +{ + asm volatile ("" : "+g" (x), "+g" (y) : : "memory"); + if (y == 2) + __builtin_abort (); + return 0; +} + +int main() +{ + for (; c >= 0; c--) + { + if (!b) + { + bar("%d\n", 2); + continue; + } + fn1(a); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr78542.c b/gcc/testsuite/gcc.dg/torture/pr78542.c new file mode 100644 index 00000000000..bae42b65333 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr78542.c @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-additional-options "-w -Wno-psabi" } */ + +typedef unsigned V __attribute__ ((vector_size (16))); + +V +foo (unsigned x, V v) +{ + do { + v %= x; + x = 1; + } while (v[1]); + return v; +} + +int +main () +{ + V x = foo (5, (V) { 0, 1 }); + if (x[0] || x[1] || x[2] || x[3]) + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c index a566f1ee6a4..35dedfc3c16 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c @@ -83,6 +83,8 @@ test_8 (int code) to a ordered compare. But the transform does not trigger if we transform the negated code == 22 compare to code != 22 first. It turns out if we do that we even generate better code on x86 at least. */ +/* ??? As PR71762 notices this transform causes wrong-code issues in RTL + with one uninitialized operand, thus it has been disabled. */ -/* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* <" 4 "forwprop1"} } */ +/* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* <" 4 "forwprop1" { xfail *-*-* } } } */ diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c index 647be3937a3..6bbe0c36611 100644 --- a/gcc/tree-call-cdce.c +++ b/gcc/tree-call-cdce.c @@ -801,14 +801,20 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds, if (join_tgt_in_edge_from_call == NULL) return false; free_dominance_info (CDI_DOMINATORS); + /* We don't want to handle PHIs. */ + if (EDGE_COUNT (join_tgt_in_edge_from_call->dest->preds) > 1) + join_tgt_bb = split_edge (join_tgt_in_edge_from_call); + else + join_tgt_bb = join_tgt_in_edge_from_call->dest; } else - join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call); + { + join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call); + join_tgt_bb = join_tgt_in_edge_from_call->dest; + } bi_call_bsi = gsi_for_stmt (bi_call); - join_tgt_bb = join_tgt_in_edge_from_call->dest; - /* Now it is time to insert the first conditional expression into bi_call_bb and split this bb so that bi_call is shrink-wrapped. */ diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index be376ee8273..357cff0022a 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-scalar-evolution.h" #include "gimple-match.h" #include "gimple-fold.h" +#include "tree-ssa-loop-niter.h" /* The set of blocks in that at least one of the following changes happened: @@ -878,6 +879,18 @@ remove_forwarder_block_with_phi (basic_block bb) DEST. */ e = single_succ_edge (split_edge (e)); } + else + { + /* If we merge the forwarder into a loop header verify if we + are creating another loop latch edge. If so, reset + number of iteration information of the loop. */ + if (dest->loop_father->header == dest + && dominated_by_p (CDI_DOMINATORS, e->src, dest)) + { + dest->loop_father->any_upper_bound = false; + free_numbers_of_iterations_estimates_loop (dest->loop_father); + } + } s = redirect_edge_and_branch (e, dest); diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index a501d2cf03f..8dcd46deb6d 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -1732,7 +1732,12 @@ evaluate_stmt (gimple *stmt) { fold_defer_overflow_warnings (); simplified = ccp_fold (stmt); - if (simplified && TREE_CODE (simplified) == SSA_NAME) + if (simplified + && TREE_CODE (simplified) == SSA_NAME + /* We may not use values of something that may be simulated again, + see valueize_op_1. */ + && (SSA_NAME_IS_DEFAULT_DEF (simplified) + || ! prop_simulate_again_p (SSA_NAME_DEF_STMT (simplified)))) { val = *get_value (simplified); if (val.lattice_val != VARYING) diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 0d78f6db43b..038d21f28fe 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -3329,6 +3329,10 @@ visit_reference_op_call (tree lhs, gcall *stmt) { if (vnresult->result_vdef && vdef) changed |= set_ssa_val_to (vdef, vnresult->result_vdef); + else if (vdef) + /* If the call was discovered to be pure or const reflect + that as far as possible. */ + changed |= set_ssa_val_to (vdef, vuse_ssa_val (gimple_vuse (stmt))); if (!vnresult->result && lhs) vnresult->result = lhs; |