Message ID | 1580515470.16471.8.camel@med.uni-goettingen.de |
---|---|
State | New |
Headers | show |
Series | [RFC] __builtin_escape/__builtin_bless | expand |
On Sat, Feb 1, 2020 at 1:04 AM Uecker, Martin <Martin.Uecker@med.uni-goettingen.de> wrote: > > > > Hi Richard and Joseph, > > for discussion: here is my simple patch > for __builtin_escape/__builtin_bless. > > Maybe it does something stupid. I'd use an internal function once the frontend inserts the calls, we shouldn't expose those to the user. I expect the builtins to show as quite invasive with their data dependence blocking many optimizations. Any reason that __builtin_escape is not marked as const? Do you try to prevent code motion of it so flow-sensitive "escape" analysis can be used? But nothing prevents hoisting of the bless call across the escape one. Richard. > > Best, > Martin > > > diff --git a/gcc/builtins.c b/gcc/builtins.c > index e4a8694054e..d0046135213 100644 > --- a/gcc/builtins.c > +++ b/gcc/builtins.c > @@ -6014,6 +6014,31 @@ expand_builtin_unreachable (void) > emit_barrier (); > } > > + > +static rtx > +expand_builtin_escape (tree exp, rtx target) > +{ > + if (call_expr_nargs (exp) < 1) > + return const0_rtx; > + > + target = expand_expr (CALL_EXPR_ARG (exp, 0), target, Pmode, > + EXPAND_NORMAL); > + > + return target; > +} > + > +static rtx > +expand_builtin_bless (tree exp, rtx target) > +{ > + if (call_expr_nargs (exp) < 1) > + return const0_rtx; > + > + target = expand_expr (CALL_EXPR_ARG (exp, 0), target, Pmode, > + EXPAND_NORMAL); > + > + return target; > +} > + > /* Expand EXP, a call to fabs, fabsf or fabsl. > Return NULL_RTX if a normal call should be emitted rather than expanding > the function inline. If convenient, the result should be placed > @@ -8304,6 +8329,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, > expand_builtin_unreachable (); > return const0_rtx; > > + case BUILT_IN_ESCAPE: > + return expand_builtin_escape (exp, target); > + > + case BUILT_IN_BLESS: > + return expand_builtin_bless (exp, target); > + > CASE_FLT_FN (BUILT_IN_SIGNBIT): > case BUILT_IN_SIGNBITD32: > case BUILT_IN_SIGNBITD64: > diff --git a/gcc/builtins.def b/gcc/builtins.def > index fa8b0641ab1..9264a0fdaab 100644 > --- a/gcc/builtins.def > +++ b/gcc/builtins.def > @@ -865,6 +865,8 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVP, "execvp", BT_FN_INT_CONST_STRING_PT > DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVE, "execve", BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST) > DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST) > DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_ESCAPE, "escape", BT_FN_PTR_PTR, ATTR_NOTHROW_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_BLESS, "bless", BT_FN_PTR_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) > DEF_GCC_BUILTIN (BUILT_IN_EXPECT_WITH_PROBABILITY, "expect_with_probability", BT_FN_LONG_LONG_LONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) > DEF_GCC_BUILTIN (BUILT_IN_ASSUME_ALIGNED, "assume_aligned", BT_FN_PTR_CONST_PTR_SIZE_VAR, ATTR_CONST_NOTHROW_LEAF_LIST) > DEF_GCC_BUILTIN (BUILT_IN_EXTEND_POINTER, "extend_pointer", BT_FN_UNWINDWORD_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) > diff --git a/gcc/testsuite/gcc.dg/alias-17.c b/gcc/testsuite/gcc.dg/alias-17.c > new file mode 100644 > index 00000000000..c375e4027ca > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/alias-17.c > @@ -0,0 +1,29 @@ > +/* { dg-do run } */ > +/* { dg-options "-O1" } */ > + > + > +static > +int test(int a, int b, int c) > +{ > + int x, y; > + int d = (&x < &y) ? 1 : -1; > + if (a) __builtin_escape(&y); > + y = 0; //! > + int *q = &x; > + q += d; > + int *r = q; > + if (b) r = __builtin_bless(q); > + *(c ? r : q) = 1; > + return y; > +} > + > +int main() > +{ > + if (0 != test(0, 0, 1)) __builtin_abort(); > + if (0 != test(0, 1, 0)) __builtin_abort(); > + if (0 != test(0, 1, 1)) __builtin_abort(); > + if (0 != test(1, 0, 1)) __builtin_abort(); > +// if (0 != test(1, 1, 0)) __builtin_abort(); > + if (0 == test(1, 1, 1)) __builtin_abort(); > + return 0; > +} > diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c > index 670676f20c3..d5befff71a6 100644 > --- a/gcc/tree-ssa-alias.c > +++ b/gcc/tree-ssa-alias.c > @@ -2462,6 +2462,8 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *ref, bool tbaa_p) > } > > /* The following builtins do not read from memory. */ > + case BUILT_IN_ESCAPE: > + case BUILT_IN_BLESS: > case BUILT_IN_FREE: > case BUILT_IN_MALLOC: > case BUILT_IN_POSIX_MEMALIGN: > diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c > index be6647db894..53a38a04ebb 100644 > --- a/gcc/tree-ssa-ccp.c > +++ b/gcc/tree-ssa-ccp.c > @@ -1963,6 +1963,8 @@ evaluate_stmt (gimple *stmt) > break; > > /* These builtins return their first argument, unmodified. */ > + case BUILT_IN_ESCAPE: > + case BUILT_IN_BLESS: > case BUILT_IN_MEMCPY: > case BUILT_IN_MEMMOVE: > case BUILT_IN_MEMSET: > diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c > index 416a26c996c..003349c7278 100644 > --- a/gcc/tree-ssa-structalias.c > +++ b/gcc/tree-ssa-structalias.c > @@ -4381,6 +4381,24 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t) > in the alias-oracle query functions explicitly! */ > switch (DECL_FUNCTION_CODE (fndecl)) > { > + case BUILT_IN_ESCAPE: > + { > + make_escape_constraint (gimple_call_arg (t, 0)); > + return true; > + } > + case BUILT_IN_BLESS: > + { > + tree lhs = gimple_call_lhs (t); > + struct constraint_expr rhsc, *lhsp; > + unsigned j; > + get_constraint_for (lhs, &lhsc); > + rhsc.var = nonlocal_id; > + rhsc.offset = 0; > + rhsc.type = SCALAR; > + FOR_EACH_VEC_ELT (lhsc, j, lhsp) > + process_constraint (new_constraint (*lhsp, rhsc)); > + return true; > + } > /* All the following functions return a pointer to the same object > as their first argument points to. The functions do not add > to the ESCAPED solution. The functions make the first argument > @@ -5257,6 +5275,7 @@ find_func_clobbers (struct function *fn, gimple *origt) > if (gimple_call_builtin_p (t, BUILT_IN_NORMAL)) > switch (DECL_FUNCTION_CODE (decl)) > { > + > /* The following functions use and clobber memory pointed to > by their arguments. */ > case BUILT_IN_STRCPY: > @@ -5349,6 +5368,9 @@ find_func_clobbers (struct function *fn, gimple *origt) > case BUILT_IN_ASSUME_ALIGNED: > case BUILT_IN_FREE: > return; > + case BUILT_IN_ESCAPE: > + case BUILT_IN_BLESS: > + return; > /* Trampolines are of no interest to us. */ > case BUILT_IN_INIT_TRAMPOLINE: > case BUILT_IN_ADJUST_TRAMPOLINE:
Am Dienstag, den 04.02.2020, 15:01 +0100 schrieb Richard Biener: > On Sat, Feb 1, 2020 at 1:04 AM Uecker, Martin > <Martin.Uecker@med.uni-goettingen.de> wrote: > > > > > > > > Hi Richard and Joseph, > > > > for discussion: here is my simple patch > > for __builtin_escape/__builtin_bless. > > > > Maybe it does something stupid. > > I'd use an internal function once the frontend inserts the calls, > we shouldn't expose those to the user. Ok. I thought it might be useful for testing... > I expect the builtins to show as quite invasive with their > data dependence blocking many optimizations. Yes, I wondering about the impact of this on optimization and whether this could be made more light-weight somehow. Do you think it is worth investigating the use of some other kind of marker? > Any reason that __builtin_escape is not marked as const? Conceptually, letting something escape (or marking it "exposed" according to the formal semantics in the PVNI proposal) is a side-effect. Practically, if I mark it constant, I think the problem was that it was getting optimized away completely. > Do you try to prevent code motion of it so flow-sensitive > "escape" analysis can be used? If I don't miss something important, there is no flow-sensitive analysis done in GCC. > But nothing prevents hoisting of the bless call > across the escape one. With flow-sensitive analysis, this would be incorrect. Martin > > > > diff --git a/gcc/builtins.c b/gcc/builtins.c > > index e4a8694054e..d0046135213 100644 > > --- a/gcc/builtins.c > > +++ b/gcc/builtins.c > > @@ -6014,6 +6014,31 @@ expand_builtin_unreachable (void) > > emit_barrier (); > > } > > > > + > > +static rtx > > +expand_builtin_escape (tree exp, rtx target) > > +{ > > + if (call_expr_nargs (exp) < 1) > > + return const0_rtx; > > + > > + target = expand_expr (CALL_EXPR_ARG (exp, 0), target, Pmode, > > + EXPAND_NORMAL); > > + > > + return target; > > +} > > + > > +static rtx > > +expand_builtin_bless (tree exp, rtx target) > > +{ > > + if (call_expr_nargs (exp) < 1) > > + return const0_rtx; > > + > > + target = expand_expr (CALL_EXPR_ARG (exp, 0), target, Pmode, > > + EXPAND_NORMAL); > > + > > + return target; > > +} > > + > > /* Expand EXP, a call to fabs, fabsf or fabsl. > > Return NULL_RTX if a normal call should be emitted rather than > > expanding > > the function inline. If convenient, the result should be > > placed > > @@ -8304,6 +8329,12 @@ expand_builtin (tree exp, rtx target, rtx > > subtarget, machine_mode mode, > > expand_builtin_unreachable (); > > return const0_rtx; > > > > + case BUILT_IN_ESCAPE: > > + return expand_builtin_escape (exp, target); > > + > > + case BUILT_IN_BLESS: > > + return expand_builtin_bless (exp, target); > > + > > CASE_FLT_FN (BUILT_IN_SIGNBIT): > > case BUILT_IN_SIGNBITD32: > > case BUILT_IN_SIGNBITD64: > > diff --git a/gcc/builtins.def b/gcc/builtins.def > > index fa8b0641ab1..9264a0fdaab 100644 > > --- a/gcc/builtins.def > > +++ b/gcc/builtins.def > > @@ -865,6 +865,8 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVP, > > "execvp", BT_FN_INT_CONST_STRING_PT > > DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVE, "execve", > > BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, > > ATTR_NOTHROW_LIST) > > DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, > > ATTR_NORETURN_NOTHROW_LIST) > > DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", > > BT_FN_LONG_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST) > > +DEF_GCC_BUILTIN (BUILT_IN_ESCAPE, "escape", BT_FN_PTR_PTR, > > ATTR_NOTHROW_LEAF_LIST) > > +DEF_GCC_BUILTIN (BUILT_IN_BLESS, "bless", BT_FN_PTR_PTR, > > ATTR_CONST_NOTHROW_LEAF_LIST) > > DEF_GCC_BUILTIN (BUILT_IN_EXPECT_WITH_PROBABILITY, > > "expect_with_probability", BT_FN_LONG_LONG_LONG_DOUBLE, > > ATTR_CONST_NOTHROW_LEAF_LIST) > > DEF_GCC_BUILTIN (BUILT_IN_ASSUME_ALIGNED, "assume_aligned", > > BT_FN_PTR_CONST_PTR_SIZE_VAR, ATTR_CONST_NOTHROW_LEAF_LIST) > > DEF_GCC_BUILTIN (BUILT_IN_EXTEND_POINTER, "extend_pointer", > > BT_FN_UNWINDWORD_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) > > diff --git a/gcc/testsuite/gcc.dg/alias-17.c > > b/gcc/testsuite/gcc.dg/alias-17.c > > new file mode 100644 > > index 00000000000..c375e4027ca > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/alias-17.c > > @@ -0,0 +1,29 @@ > > +/* { dg-do run } */ > > +/* { dg-options "-O1" } */ > > + > > + > > +static > > +int test(int a, int b, int c) > > +{ > > + int x, y; > > + int d = (&x < &y) ? 1 : -1; > > + if (a) __builtin_escape(&y); > > + y = 0; //! > > + int *q = &x; > > + q += d; > > + int *r = q; > > + if (b) r = __builtin_bless(q); > > + *(c ? r : q) = 1; > > + return y; > > +} > > + > > +int main() > > +{ > > + if (0 != test(0, 0, 1)) __builtin_abort(); > > + if (0 != test(0, 1, 0)) __builtin_abort(); > > + if (0 != test(0, 1, 1)) __builtin_abort(); > > + if (0 != test(1, 0, 1)) __builtin_abort(); > > +// if (0 != test(1, 1, 0)) __builtin_abort(); > > + if (0 == test(1, 1, 1)) __builtin_abort(); > > + return 0; > > +} > > diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c > > index 670676f20c3..d5befff71a6 100644 > > --- a/gcc/tree-ssa-alias.c > > +++ b/gcc/tree-ssa-alias.c > > @@ -2462,6 +2462,8 @@ ref_maybe_used_by_call_p_1 (gcall *call, > > ao_ref *ref, bool tbaa_p) > > } > > > > /* The following builtins do not read from memory. */ > > + case BUILT_IN_ESCAPE: > > + case BUILT_IN_BLESS: > > case BUILT_IN_FREE: > > case BUILT_IN_MALLOC: > > case BUILT_IN_POSIX_MEMALIGN: > > diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c > > index be6647db894..53a38a04ebb 100644 > > --- a/gcc/tree-ssa-ccp.c > > +++ b/gcc/tree-ssa-ccp.c > > @@ -1963,6 +1963,8 @@ evaluate_stmt (gimple *stmt) > > break; > > > > /* These builtins return their first argument, > > unmodified. */ > > + case BUILT_IN_ESCAPE: > > + case BUILT_IN_BLESS: > > case BUILT_IN_MEMCPY: > > case BUILT_IN_MEMMOVE: > > case BUILT_IN_MEMSET: > > diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa- > > structalias.c > > index 416a26c996c..003349c7278 100644 > > --- a/gcc/tree-ssa-structalias.c > > +++ b/gcc/tree-ssa-structalias.c > > @@ -4381,6 +4381,24 @@ find_func_aliases_for_builtin_call (struct > > function *fn, gcall *t) > > in the alias-oracle query functions explicitly! */ > > switch (DECL_FUNCTION_CODE (fndecl)) > > { > > + case BUILT_IN_ESCAPE: > > + { > > + make_escape_constraint (gimple_call_arg (t, 0)); > > + return true; > > + } > > + case BUILT_IN_BLESS: > > + { > > + tree lhs = gimple_call_lhs (t); > > + struct constraint_expr rhsc, *lhsp; > > + unsigned j; > > + get_constraint_for (lhs, &lhsc); > > + rhsc.var = nonlocal_id; > > + rhsc.offset = 0; > > + rhsc.type = SCALAR; > > + FOR_EACH_VEC_ELT (lhsc, j, lhsp) > > + process_constraint (new_constraint (*lhsp, rhsc)); > > + return true; > > + } > > /* All the following functions return a pointer to the same > > object > > as their first argument points to. The functions do not > > add > > to the ESCAPED solution. The functions make the first > > argument > > @@ -5257,6 +5275,7 @@ find_func_clobbers (struct function *fn, > > gimple *origt) > > if (gimple_call_builtin_p (t, BUILT_IN_NORMAL)) > > switch (DECL_FUNCTION_CODE (decl)) > > { > > + > > /* The following functions use and clobber memory pointed > > to > > by their arguments. */ > > case BUILT_IN_STRCPY: > > @@ -5349,6 +5368,9 @@ find_func_clobbers (struct function *fn, > > gimple *origt) > > case BUILT_IN_ASSUME_ALIGNED: > > case BUILT_IN_FREE: > > return; > > + case BUILT_IN_ESCAPE: > > + case BUILT_IN_BLESS: > > + return; > > /* Trampolines are of no interest to us. */ > > case BUILT_IN_INIT_TRAMPOLINE: > > case BUILT_IN_ADJUST_TRAMPOLINE:
diff --git a/gcc/builtins.c b/gcc/builtins.c index e4a8694054e..d0046135213 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -6014,6 +6014,31 @@ expand_builtin_unreachable (void) emit_barrier (); } + +static rtx +expand_builtin_escape (tree exp, rtx target) +{ + if (call_expr_nargs (exp) < 1) + return const0_rtx; + + target = expand_expr (CALL_EXPR_ARG (exp, 0), target, Pmode, + EXPAND_NORMAL); + + return target; +} + +static rtx +expand_builtin_bless (tree exp, rtx target) +{ + if (call_expr_nargs (exp) < 1) + return const0_rtx; + + target = expand_expr (CALL_EXPR_ARG (exp, 0), target, Pmode, + EXPAND_NORMAL); + + return target; +} + /* Expand EXP, a call to fabs, fabsf or fabsl. Return NULL_RTX if a normal call should be emitted rather than expanding the function inline. If convenient, the result should be placed @@ -8304,6 +8329,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, expand_builtin_unreachable (); return const0_rtx; + case BUILT_IN_ESCAPE: + return expand_builtin_escape (exp, target); + + case BUILT_IN_BLESS: + return expand_builtin_bless (exp, target); + CASE_FLT_FN (BUILT_IN_SIGNBIT): case BUILT_IN_SIGNBITD32: case BUILT_IN_SIGNBITD64: diff --git a/gcc/builtins.def b/gcc/builtins.def index fa8b0641ab1..9264a0fdaab 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -865,6 +865,8 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVP, "execvp", BT_FN_INT_CONST_STRING_PT DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVE, "execve", BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST) DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_ESCAPE, "escape", BT_FN_PTR_PTR, ATTR_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_BLESS, "bless", BT_FN_PTR_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_EXPECT_WITH_PROBABILITY, "expect_with_probability", BT_FN_LONG_LONG_LONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_ASSUME_ALIGNED, "assume_aligned", BT_FN_PTR_CONST_PTR_SIZE_VAR, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_EXTEND_POINTER, "extend_pointer", BT_FN_UNWINDWORD_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) diff --git a/gcc/testsuite/gcc.dg/alias-17.c b/gcc/testsuite/gcc.dg/alias-17.c new file mode 100644 index 00000000000..c375e4027ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/alias-17.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + + +static +int test(int a, int b, int c) +{ + int x, y; + int d = (&x < &y) ? 1 : -1; + if (a) __builtin_escape(&y); + y = 0; //! + int *q = &x; + q += d; + int *r = q; + if (b) r = __builtin_bless(q); + *(c ? r : q) = 1; + return y; +} + +int main() +{ + if (0 != test(0, 0, 1)) __builtin_abort(); + if (0 != test(0, 1, 0)) __builtin_abort(); + if (0 != test(0, 1, 1)) __builtin_abort(); + if (0 != test(1, 0, 1)) __builtin_abort(); +// if (0 != test(1, 1, 0)) __builtin_abort(); + if (0 == test(1, 1, 1)) __builtin_abort(); + return 0; +} diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 670676f20c3..d5befff71a6 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -2462,6 +2462,8 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *ref, bool tbaa_p) } /* The following builtins do not read from memory. */ + case BUILT_IN_ESCAPE: + case BUILT_IN_BLESS: case BUILT_IN_FREE: case BUILT_IN_MALLOC: case BUILT_IN_POSIX_MEMALIGN: diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index be6647db894..53a38a04ebb 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -1963,6 +1963,8 @@ evaluate_stmt (gimple *stmt) break; /* These builtins return their first argument, unmodified. */ + case BUILT_IN_ESCAPE: + case BUILT_IN_BLESS: case BUILT_IN_MEMCPY: case BUILT_IN_MEMMOVE: case BUILT_IN_MEMSET: diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 416a26c996c..003349c7278 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -4381,6 +4381,24 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t) in the alias-oracle query functions explicitly! */ switch (DECL_FUNCTION_CODE (fndecl)) { + case BUILT_IN_ESCAPE: + { + make_escape_constraint (gimple_call_arg (t, 0)); + return true; + } + case BUILT_IN_BLESS: + { + tree lhs = gimple_call_lhs (t); + struct constraint_expr rhsc, *lhsp; + unsigned j; + get_constraint_for (lhs, &lhsc); + rhsc.var = nonlocal_id; + rhsc.offset = 0; + rhsc.type = SCALAR; + FOR_EACH_VEC_ELT (lhsc, j, lhsp) + process_constraint (new_constraint (*lhsp, rhsc)); + return true; + } /* All the following functions return a pointer to the same object as their first argument points to. The functions do not add to the ESCAPED solution. The functions make the first argument @@ -5257,6 +5275,7 @@ find_func_clobbers (struct function *fn, gimple *origt) if (gimple_call_builtin_p (t, BUILT_IN_NORMAL)) switch (DECL_FUNCTION_CODE (decl)) { + /* The following functions use and clobber memory pointed to by their arguments. */ case BUILT_IN_STRCPY: @@ -5349,6 +5368,9 @@ find_func_clobbers (struct function *fn, gimple *origt) case BUILT_IN_ASSUME_ALIGNED: case BUILT_IN_FREE: return; + case BUILT_IN_ESCAPE: + case BUILT_IN_BLESS: + return; /* Trampolines are of no interest to us. */ case BUILT_IN_INIT_TRAMPOLINE: case BUILT_IN_ADJUST_TRAMPOLINE: