aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2019-07-05 12:50:45 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2019-07-05 12:50:45 +0000
commitfb4697e30bd0cd4bda66932e21c183273a5d1e63 (patch)
tree392c65691fc7f7d8fd6d1dce0b8283095de689d5
parent75fad0a98919da8212be4efc479d098499f4f1c3 (diff)
downloadgcc-fb4697e30bd0cd4bda66932e21c183273a5d1e63.zip
gcc-fb4697e30bd0cd4bda66932e21c183273a5d1e63.tar.gz
gcc-fb4697e30bd0cd4bda66932e21c183273a5d1e63.tar.bz2
re PR tree-optimization/91091 ([missed optimization] Missing optimization in unaliased pointers)
2019-07-05 Richard Biener <rguenther@suse.de> PR tree-optimization/91091 * tree-ssa-alias.h (get_continuation_for_phi): Add tbaa_p parameter. (walk_non_aliased_vuses): Likewise. * tree-ssa-alias.c (maybe_skip_until): Pass down tbaa_p. (get_continuation_for_phi): New tbaa_p parameter and pass it down. (walk_non_aliased_vuses): Likewise. * ipa-prop.c (determine_known_aggregate_parts): Adjust. * tree-ssa-pre.c (translate_vuse_through_block): Likewise. * tree-ssa-scopedtables.c (avail_exprs_stack::lookup_avail_expr): Likewise. * tree-ssa-sccvn.c (struct vn_walk_cb_data): Add tbaa_p flag. (adjust_offsets_for_equal_base_address): New function. (vn_reference_lookup_3): Use it to catch more base equivalences. Handle and pass down tbaa_p flag. (vn_reference_lookup_pieces): Adjust. (vn_reference_lookup): Remove alias-set altering, instead pass down false as tbaa_p. * gcc.dg/tree-ssa/pr91091-2.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-70.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-71.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-72.c: Likewise. From-SVN: r273135
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/ipa-prop.c3
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c14
-rw-r--r--gcc/tree-ssa-alias.c19
-rw-r--r--gcc/tree-ssa-alias.h4
-rw-r--r--gcc/tree-ssa-pre.c4
-rw-r--r--gcc/tree-ssa-sccvn.c79
-rw-r--r--gcc/tree-ssa-scopedtables.c2
12 files changed, 163 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 25e539f..6dd97ab 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,27 @@
2019-07-05 Richard Biener <rguenther@suse.de>
PR tree-optimization/91091
+ * tree-ssa-alias.h (get_continuation_for_phi): Add tbaa_p parameter.
+ (walk_non_aliased_vuses): Likewise.
+ * tree-ssa-alias.c (maybe_skip_until): Pass down tbaa_p.
+ (get_continuation_for_phi): New tbaa_p parameter and pass
+ it down.
+ (walk_non_aliased_vuses): Likewise.
+ * ipa-prop.c (determine_known_aggregate_parts): Adjust.
+ * tree-ssa-pre.c (translate_vuse_through_block): Likewise.
+ * tree-ssa-scopedtables.c (avail_exprs_stack::lookup_avail_expr):
+ Likewise.
+ * tree-ssa-sccvn.c (struct vn_walk_cb_data): Add tbaa_p flag.
+ (adjust_offsets_for_equal_base_address): New function.
+ (vn_reference_lookup_3): Use it to catch more base equivalences.
+ Handle and pass down tbaa_p flag.
+ (vn_reference_lookup_pieces): Adjust.
+ (vn_reference_lookup): Remove alias-set altering, instead pass
+ down false as tbaa_p.
+
+2019-07-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/91091
* tree-ssa-sccvn.c (vn_reference_lookup_3): Overlap of
accesses can happen with -fno-strict-aliasing.
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index a53a6ec..f5f8c75 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -1678,7 +1678,8 @@ determine_known_aggregate_parts (gcall *call, tree arg,
if (gimple_code (stmt) == GIMPLE_PHI)
{
- dom_vuse = get_continuation_for_phi (stmt, &r, *aa_walk_budget_p,
+ dom_vuse = get_continuation_for_phi (stmt, &r, true,
+ *aa_walk_budget_p,
&visited, false, NULL, NULL);
continue;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6c049d0..5656a5b2e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,14 @@
2019-07-05 Richard Biener <rguenther@suse.de>
PR tree-optimization/91091
+ * gcc.dg/tree-ssa/pr91091-2.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-fre-70.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-fre-71.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-fre-72.c: Likewise.
+
+2019-07-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/91091
* gcc.dg/tree-ssa/pr91091-1.c: New testcase.
* gcc.dg/tree-ssa/ssa-fre-61.c: Adjust.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c
new file mode 100644
index 0000000..b578de7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre1" } */
+
+struct s { int x; };
+struct t { int x; };
+
+void swap(struct s* p, struct t* q)
+{
+ p->x = q->x;
+ q->x = p->x;
+}
+
+/* The second statement is redundant. */
+/* { dg-final { scan-tree-dump-times "x = " 1 "fre1" } } */
+/* { dg-final { scan-tree-dump-times " = \[^;\]*x;" 1 "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c
new file mode 100644
index 0000000..612d753
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -fdump-tree-fre1" } */
+
+__GIMPLE (ssa, startwith("fre")) char foo(char *p)
+{
+ char _1;
+
+__BB(2):
+ __MEM <char[4]> (p) = _Literal (char[4]) {};
+ _1 = __MEM <char> (p + 1);
+ return _1;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c
new file mode 100644
index 0000000..edc8899
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -fdump-tree-fre1-details" } */
+
+__GIMPLE (ssa, startwith("fre")) char foo(char *p)
+{
+ char _1;
+
+__BB(2):
+ __MEM <int> (p) = 0;
+ _1 = __MEM <char> (p + 1);
+ return _1;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c
new file mode 100644
index 0000000..b95709f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -fdump-tree-fre1" } */
+
+__GIMPLE (ssa,startwith("fre")) char foo(char *p, int i)
+{
+ char _1;
+
+__BB(2):
+ __MEM <int> (p) = i_2(D);
+ _1 = __MEM <char> (p + 1);
+ return _1;
+}
+
+/* { dg-final { scan-tree-dump "BIT_FIELD_REF" "fre1" } } */
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index d52d47c..b5e980d 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -3054,8 +3054,8 @@ stmt_kills_ref_p (gimple *stmt, tree ref)
static bool
maybe_skip_until (gimple *phi, tree &target, basic_block target_bb,
- ao_ref *ref, tree vuse, unsigned int &limit, bitmap *visited,
- bool abort_on_visited,
+ ao_ref *ref, tree vuse, bool tbaa_p, unsigned int &limit,
+ bitmap *visited, bool abort_on_visited,
void *(*translate)(ao_ref *, tree, void *, bool *),
void *data)
{
@@ -3089,7 +3089,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb,
/* An already visited PHI node ends the walk successfully. */
if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
return !abort_on_visited;
- vuse = get_continuation_for_phi (def_stmt, ref, limit,
+ vuse = get_continuation_for_phi (def_stmt, ref, tbaa_p, limit,
visited, abort_on_visited,
translate, data);
if (!vuse)
@@ -3104,7 +3104,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb,
if ((int)limit <= 0)
return false;
--limit;
- if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
+ if (stmt_may_clobber_ref_p_1 (def_stmt, ref, tbaa_p))
{
bool disambiguate_only = true;
if (translate
@@ -3136,7 +3136,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb,
Returns NULL_TREE if no suitable virtual operand can be found. */
tree
-get_continuation_for_phi (gimple *phi, ao_ref *ref,
+get_continuation_for_phi (gimple *phi, ao_ref *ref, bool tbaa_p,
unsigned int &limit, bitmap *visited,
bool abort_on_visited,
void *(*translate)(ao_ref *, tree, void *, bool *),
@@ -3179,7 +3179,8 @@ get_continuation_for_phi (gimple *phi, ao_ref *ref,
arg1 = PHI_ARG_DEF (phi, i);
if (arg1 == arg0)
;
- else if (! maybe_skip_until (phi, arg0, dom, ref, arg1, limit, visited,
+ else if (! maybe_skip_until (phi, arg0, dom, ref, arg1, tbaa_p,
+ limit, visited,
abort_on_visited,
/* Do not translate when walking over
backedges. */
@@ -3223,7 +3224,7 @@ get_continuation_for_phi (gimple *phi, ao_ref *ref,
TODO: Cache the vector of equivalent vuses per ref, vuse pair. */
void *
-walk_non_aliased_vuses (ao_ref *ref, tree vuse,
+walk_non_aliased_vuses (ao_ref *ref, tree vuse, bool tbaa_p,
void *(*walker)(ao_ref *, tree, void *),
void *(*translate)(ao_ref *, tree, void *, bool *),
tree (*valueize)(tree),
@@ -3264,7 +3265,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
if (gimple_nop_p (def_stmt))
break;
else if (gimple_code (def_stmt) == GIMPLE_PHI)
- vuse = get_continuation_for_phi (def_stmt, ref, limit,
+ vuse = get_continuation_for_phi (def_stmt, ref, tbaa_p, limit,
&visited, translated, translate, data);
else
{
@@ -3274,7 +3275,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
break;
}
--limit;
- if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
+ if (stmt_may_clobber_ref_p_1 (def_stmt, ref, tbaa_p))
{
if (!translate)
break;
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index cee8449..ddd28ec 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -131,11 +131,11 @@ extern bool call_may_clobber_ref_p (gcall *, tree);
extern bool call_may_clobber_ref_p_1 (gcall *, ao_ref *);
extern bool stmt_kills_ref_p (gimple *, tree);
extern bool stmt_kills_ref_p (gimple *, ao_ref *);
-extern tree get_continuation_for_phi (gimple *, ao_ref *,
+extern tree get_continuation_for_phi (gimple *, ao_ref *, bool,
unsigned int &, bitmap *, bool,
void *(*)(ao_ref *, tree, void *, bool *),
void *);
-extern void *walk_non_aliased_vuses (ao_ref *, tree,
+extern void *walk_non_aliased_vuses (ao_ref *, tree, bool,
void *(*)(ao_ref *, tree, void *),
void *(*)(ao_ref *, tree, void *, bool *),
tree (*)(tree), unsigned &, void *);
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 086f8c3..231ac00 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -1185,8 +1185,8 @@ translate_vuse_through_block (vec<vn_reference_op_s> operands,
bitmap visited = NULL;
/* Try to find a vuse that dominates this phi node by skipping
non-clobbering statements. */
- vuse = get_continuation_for_phi (phi, &ref, cnt, &visited, false,
- NULL, NULL);
+ vuse = get_continuation_for_phi (phi, &ref, true,
+ cnt, &visited, false, NULL, NULL);
if (visited)
BITMAP_FREE (visited);
}
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 2cc76d8..6d4ad75 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1648,9 +1648,16 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
struct vn_walk_cb_data
{
+ vn_walk_cb_data (vn_reference_t vr_, tree *last_vuse_ptr_,
+ vn_lookup_kind vn_walk_kind_, bool tbaa_p_)
+ : vr (vr_), last_vuse_ptr (last_vuse_ptr_), vn_walk_kind (vn_walk_kind_),
+ tbaa_p (tbaa_p_)
+ {}
+
vn_reference_t vr;
tree *last_vuse_ptr;
vn_lookup_kind vn_walk_kind;
+ bool tbaa_p;
};
/* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_
@@ -1927,6 +1934,33 @@ public:
static rpo_elim *rpo_avail;
basic_block vn_context_bb;
+/* Return true if BASE1 and BASE2 can be adjusted so they have the
+ same address and adjust *OFFSET1 and *OFFSET2 accordingly.
+ Otherwise return false. */
+
+static bool
+adjust_offsets_for_equal_base_address (tree base1, poly_int64 *offset1,
+ tree base2, poly_int64 *offset2)
+{
+ poly_int64 soff;
+ if (TREE_CODE (base1) == MEM_REF
+ && TREE_CODE (base2) == MEM_REF)
+ {
+ if (mem_ref_offset (base1).to_shwi (&soff))
+ {
+ base1 = TREE_OPERAND (base1, 0);
+ *offset1 += soff * BITS_PER_UNIT;
+ }
+ if (mem_ref_offset (base2).to_shwi (&soff))
+ {
+ base2 = TREE_OPERAND (base2, 0);
+ *offset2 += soff * BITS_PER_UNIT;
+ }
+ return operand_equal_p (base1, base2, 0);
+ }
+ return operand_equal_p (base1, base2, OEP_ADDRESS_OF);
+}
+
/* Callback for walk_non_aliased_vuses. Tries to perform a lookup
from the statement defining VUSE and if not successful tries to
translate *REFP and VR_ through an aggregate copy at the definition
@@ -1966,7 +2000,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
get_alias_set (lhs),
TREE_TYPE (lhs), lhs_ops);
if (lhs_ref_ok
- && !refs_may_alias_p_1 (ref, &lhs_ref, true))
+ && !refs_may_alias_p_1 (ref, &lhs_ref, data->tbaa_p))
{
*disambiguate_only = true;
return NULL;
@@ -2055,7 +2089,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
}
}
- if (*disambiguate_only)
+ /* If we are looking for redundant stores do not create new hashtable
+ entries from aliasing defs with made up alias-sets. */
+ if (*disambiguate_only || !data->tbaa_p)
return (void *)-1;
/* If we cannot constrain the size of the reference we cannot
@@ -2186,7 +2222,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
&offset2, &size2, &maxsize2, &reverse);
if (known_size_p (maxsize2)
&& known_eq (maxsize2, size2)
- && operand_equal_p (base, base2, 0)
+ && adjust_offsets_for_equal_base_address (base, &offset,
+ base2, &offset2)
&& known_subrange_p (offset, maxsize, offset2, size2))
{
tree val = build_zero_cst (vr->type);
@@ -2213,15 +2250,20 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
&& is_gimple_min_invariant (SSA_VAL (gimple_assign_rhs1 (def_stmt))))))
{
tree base2;
- HOST_WIDE_INT offset2, size2;
+ poly_int64 offset2, size2, maxsize2;
+ HOST_WIDE_INT offset2i;
bool reverse;
- base2 = get_ref_base_and_extent_hwi (gimple_assign_lhs (def_stmt),
- &offset2, &size2, &reverse);
+ base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
+ &offset2, &size2, &maxsize2, &reverse);
if (base2
&& !reverse
- && size2 % BITS_PER_UNIT == 0
- && offset2 % BITS_PER_UNIT == 0
- && operand_equal_p (base, base2, 0)
+ && known_eq (maxsize2, size2)
+ && multiple_p (size2, BITS_PER_UNIT)
+ && multiple_p (offset2, BITS_PER_UNIT)
+ && adjust_offsets_for_equal_base_address (base, &offset,
+ base2, &offset2)
+ && offset.is_constant (&offseti)
+ && offset2.is_constant (&offset2i)
&& known_subrange_p (offseti, maxsizei, offset2, size2))
{
/* We support up to 512-bit values (for V8DFmode). */
@@ -2233,12 +2275,12 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
rhs = SSA_VAL (rhs);
len = native_encode_expr (rhs,
buffer, sizeof (buffer),
- (offseti - offset2) / BITS_PER_UNIT);
+ (offseti - offset2i) / BITS_PER_UNIT);
if (len > 0 && len * BITS_PER_UNIT >= maxsizei)
{
tree type = vr->type;
/* Make sure to interpret in a type that has a range
- covering the whole access size. */
+ covering the whole access size. */
if (INTEGRAL_TYPE_P (vr->type)
&& maxsizei != TYPE_PRECISION (vr->type))
type = build_nonstandard_integer_type (maxsizei,
@@ -2283,7 +2325,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
if (!reverse
&& known_size_p (maxsize2)
&& known_eq (maxsize2, size2)
- && operand_equal_p (base, base2, 0)
+ && adjust_offsets_for_equal_base_address (base, &offset,
+ base2, &offset2)
&& known_subrange_p (offset, maxsize, offset2, size2)
/* ??? We can't handle bitfield precision extracts without
either using an alternate type for the BIT_FIELD_REF and
@@ -2653,10 +2696,10 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
{
ao_ref r;
unsigned limit = PARAM_VALUE (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS);
- vn_walk_cb_data data = { &vr1, NULL, kind };
+ vn_walk_cb_data data (&vr1, NULL, kind, true);
if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
*vnresult =
- (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
+ (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, true,
vn_reference_lookup_2,
vn_reference_lookup_3,
vuse_valueize, limit, &data);
@@ -2693,7 +2736,7 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
vr1.operands = operands
= valueize_shared_reference_ops_from_ref (op, &valuezied_anything);
vr1.type = TREE_TYPE (op);
- vr1.set = tbaa_p ? get_alias_set (op) : 0;
+ vr1.set = get_alias_set (op);
vr1.hashcode = vn_reference_compute_hash (&vr1);
if ((cst = fully_constant_vn_reference_p (&vr1)))
return cst;
@@ -2710,11 +2753,9 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
|| !ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type,
vr1.operands))
ao_ref_init (&r, op);
- if (! tbaa_p)
- r.ref_alias_set = r.base_alias_set = 0;
- vn_walk_cb_data data = { &vr1, last_vuse_ptr, kind };
+ vn_walk_cb_data data (&vr1, last_vuse_ptr, kind, tbaa_p);
wvnresult =
- (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
+ (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, tbaa_p,
vn_reference_lookup_2,
vn_reference_lookup_3,
vuse_valueize, limit, &data);
diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c
index 50413eb..838cf8f 100644
--- a/gcc/tree-ssa-scopedtables.c
+++ b/gcc/tree-ssa-scopedtables.c
@@ -298,7 +298,7 @@ avail_exprs_stack::lookup_avail_expr (gimple *stmt, bool insert, bool tbaa_p)
&& TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
&& (ao_ref_init (&ref, gimple_assign_rhs1 (stmt)),
ref.base_alias_set = ref.ref_alias_set = tbaa_p ? -1 : 0, true)
- && walk_non_aliased_vuses (&ref, vuse2, vuse_eq, NULL, NULL,
+ && walk_non_aliased_vuses (&ref, vuse2, true, vuse_eq, NULL, NULL,
limit, vuse1) != NULL))
{
if (insert)