Message ID | CADzB+2=ZiPWdb-yri9JaxEofgx6K_GWU3ixCx77as7cu=s2zxA@mail.gmail.com |
---|---|
State | New |
Headers | show |
On Tue, Nov 01, 2016 at 05:33:17PM -0400, Jason Merrill wrote: > Like so? LGTM, thanks. > diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c > index de5e575..6899d2a 100644 > --- a/gcc/tree-inline.c > +++ b/gcc/tree-inline.c > @@ -1045,6 +1045,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) > copy_body_data *id = (copy_body_data *) data; > tree fn = id->src_fn; > tree new_block; > + bool copied = false; > > /* Begin by recognizing trees that we'll completely rewrite for the > inlining context. Our output for these trees is completely > @@ -1241,10 +1242,40 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) > *walk_subtrees = 0; > return NULL; > } > + else if (TREE_CODE (*tp) == COND_EXPR) > + { > + tree cond = TREE_OPERAND (*tp, 0); > + walk_tree (&cond, copy_tree_body_r, data, NULL); > + tree folded = fold (cond); > + if (TREE_CODE (folded) == INTEGER_CST) > + { > + /* Only copy the taken branch; for a C++ base constructor clone > + inherited from a virtual base, copying the other branch leads > + to references to parameters that were optimized away. */ > + tree branch = (integer_nonzerop (folded) > + ? TREE_OPERAND (*tp, 1) > + : TREE_OPERAND (*tp, 2)); > + tree type = TREE_TYPE (*tp); > + if (VOID_TYPE_P (type) > + || type == TREE_TYPE (branch)) > + { > + *tp = branch; > + return copy_tree_body_r (tp, walk_subtrees, data); > + } > + } > + /* Avoid copying the condition twice. */ > + copy_tree_r (tp, walk_subtrees, NULL); > + TREE_OPERAND (*tp, 0) = cond; > + walk_tree (&TREE_OPERAND (*tp, 1), copy_tree_body_r, data, NULL); > + walk_tree (&TREE_OPERAND (*tp, 2), copy_tree_body_r, data, NULL); > + *walk_subtrees = 0; > + copied = true; > + } > > /* Here is the "usual case". Copy this tree node, and then > tweak some special cases. */ > - copy_tree_r (tp, walk_subtrees, NULL); > + if (!copied) > + copy_tree_r (tp, walk_subtrees, NULL); > > /* If EXPR has block defined, map it to newly constructed block. > When inlining we want EXPRs without block appear in the block Jakub
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index de5e575..6899d2a 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1045,6 +1045,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) copy_body_data *id = (copy_body_data *) data; tree fn = id->src_fn; tree new_block; + bool copied = false; /* Begin by recognizing trees that we'll completely rewrite for the inlining context. Our output for these trees is completely @@ -1241,10 +1242,40 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) *walk_subtrees = 0; return NULL; } + else if (TREE_CODE (*tp) == COND_EXPR) + { + tree cond = TREE_OPERAND (*tp, 0); + walk_tree (&cond, copy_tree_body_r, data, NULL); + tree folded = fold (cond); + if (TREE_CODE (folded) == INTEGER_CST) + { + /* Only copy the taken branch; for a C++ base constructor clone + inherited from a virtual base, copying the other branch leads + to references to parameters that were optimized away. */ + tree branch = (integer_nonzerop (folded) + ? TREE_OPERAND (*tp, 1) + : TREE_OPERAND (*tp, 2)); + tree type = TREE_TYPE (*tp); + if (VOID_TYPE_P (type) + || type == TREE_TYPE (branch)) + { + *tp = branch; + return copy_tree_body_r (tp, walk_subtrees, data); + } + } + /* Avoid copying the condition twice. */ + copy_tree_r (tp, walk_subtrees, NULL); + TREE_OPERAND (*tp, 0) = cond; + walk_tree (&TREE_OPERAND (*tp, 1), copy_tree_body_r, data, NULL); + walk_tree (&TREE_OPERAND (*tp, 2), copy_tree_body_r, data, NULL); + *walk_subtrees = 0; + copied = true; + } /* Here is the "usual case". Copy this tree node, and then tweak some special cases. */ - copy_tree_r (tp, walk_subtrees, NULL); + if (!copied) + copy_tree_r (tp, walk_subtrees, NULL); /* If EXPR has block defined, map it to newly constructed block. When inlining we want EXPRs without block appear in the block