> On 8 Oct 2025, at 16:57, Jason Merrill <[email protected]> wrote:
> 
> On 10/8/25 4:11 PM, Iain Sandoe wrote:
>>> On 8 Oct 2025, at 16:04, Jason Merrill <[email protected]> wrote:
>>> 
>>> On 10/8/25 3:08 PM, Iain Sandoe wrote:
>>>>>> Otherwise, I’m looking for guidance on what’s needed to land this.
>>>>> IIRC the paper talks about a call to an unknown function having the 
>>>>> desired semantics.  I’ll go with that, making it not throwing, const but 
>>>>> looping and leaf.  We can make it stronger if necessary, weakening it 
>>>>> after people rely on semantics is less useful IMO.  On RTL we have 
>>>>> nothing at all, I’ve heard ,volatile‘ asm is only about missing outputs, 
>>>>> not side effects in general.  So I’d expand to nothing on RTL, watching 
>>>>> what breaks.
>>>> with a follow up to a query
>>>>> I suggest to remove the assert or replace it with one that checks that if 
>>>>> ECF_LOOPING_CONST_OR_PURE is set the function is either ECF_CONST or 
>>>>> ECF_PURE.
>>>> Done and re-tested on x86_64-darwin24 and powerpc64le-linux, OK for trunk 
>>>> now?
>>>> thanks
>>>> Iain
>>>> --- 8< ---
>>>> P1494 provides a mechanism that serves to demarc epochs within the code
>>>> preventing UB-based optimisations from 'time traveling' across such
>>>> boundaries.  The additional paper, P3641, alters the name of the function
>>>> to 'observable_checkpoint' which is the name used here.
>>>> This implementation  maintains the observable function call through to
>>>> expand, where it produces no code.
>>>> PR c++/119060
>>>> gcc/ChangeLog:
>>>> * builtins.cc (expand_builtin): Handle BUILT_IN_OBSERVABLE_CHKPT.
>>>> * builtins.def (BUILT_IN_OBSERVABLE_CHKPT): New.
>>>> * tree.cc (build_common_builtin_nodes): Build observable
>>>> checkpoint builtin.
>>>> gcc/cp/ChangeLog:
>>>> * cp-gimplify.cc (cp_fold): Handle std::observable_checkpoint
>>>> specially, lowering it to the builtin.
>>>> * cxxapi-data.csv: Add observable_checkpoint to <utility>.
>>>> * std-name-hint.gperf: Add observable_checkpoint to <utility>.
>>>> * std-name-hint.h: Regenerate.
>>>> gcc/testsuite/ChangeLog:
>>>> * g++.dg/cpp26/observable-checkpoint.C: New test.
>>>> Signed-off-by: Iain Sandoe <[email protected]>
>>>> ---
>>>>  gcc/builtins.cc                               |   4 +
>>>>  gcc/builtins.def                              |   1 +
>>>>  gcc/cp/cp-gimplify.cc                         |  16 ++
>>>>  gcc/cp/cxxapi-data.csv                        |   1 +
>>>>  gcc/cp/std-name-hint.gperf                    |   1 +
>>>>  gcc/cp/std-name-hint.h                        | 142 +++++++++---------
>>>>  .../g++.dg/cpp26/observable-checkpoint.C      |  25 +++
>>>>  gcc/tree.cc                                   |   9 +-
>>>>  8 files changed, 128 insertions(+), 71 deletions(-)
>>>>  create mode 100644 gcc/testsuite/g++.dg/cpp26/observable-checkpoint.C
>>>> diff --git a/gcc/builtins.cc b/gcc/builtins.cc
>>>> index 78b561529f5..fb294ce58cd 100644
>>>> --- a/gcc/builtins.cc
>>>> +++ b/gcc/builtins.cc
>>>> @@ -8427,6 +8427,10 @@ expand_builtin (tree exp, rtx target, rtx 
>>>> subtarget, machine_mode mode,
>>>>        expand_builtin_unreachable ();
>>>>        return const0_rtx;
>>>>  +    case BUILT_IN_OBSERVABLE_CHKPT:
>>>> +      /* Generate no code.  */
>>>> +      return const0_rtx;
>>>> +
>>>>      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 3dc2333c6f2..7cd5353bcb1 100644
>>>> --- a/gcc/builtins.def
>>>> +++ b/gcc/builtins.def
>>>> @@ -1142,6 +1142,7 @@ DEF_C2Y_BUILTIN        (BUILT_IN_ULABS, "ulabs", 
>>>> BT_FN_ULONG_LONG, ATTR_CONST_NO
>>>>  DEF_C2Y_BUILTIN        (BUILT_IN_ULLABS, "ullabs", 
>>>> BT_FN_ULONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
>>>>  DEF_GCC_BUILTIN        (BUILT_IN_UNREACHABLE_TRAP, "unreachable trap", 
>>>> BT_FN_VOID, ATTR_CONST_NORETURN_NOTHROW_LEAF_COLD_LIST)
>>>>  DEF_GCC_BUILTIN        (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, 
>>>> ATTR_CONST_NORETURN_NOTHROW_LEAF_COLD_LIST)
>>>> +DEF_GCC_BUILTIN        (BUILT_IN_OBSERVABLE_CHKPT, 
>>>> "observable_checkpoint", BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
>>>>  DEF_GCC_BUILTIN        (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, 
>>>> ATTR_NULL)
>>>>  DEF_GCC_BUILTIN        (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", 
>>>> BT_FN_VOID_PTR, ATTR_NULL)
>>>>  DEF_GCC_BUILTIN        (BUILT_IN_VA_COPY, "va_copy", 
>>>> BT_FN_VOID_VALIST_REF_VALIST_ARG, ATTR_NOTHROW_LEAF_LIST)
>>>> diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
>>>> index 1662336e165..483d964bd62 100644
>>>> --- a/gcc/cp/cp-gimplify.cc
>>>> +++ b/gcc/cp/cp-gimplify.cc
>>>> @@ -3452,6 +3452,22 @@ cp_fold (tree x, fold_flags_t flags)
>>>>       break;
>>>>     }
>>>>  + /* We need to convert std::observable_checkpoint () into its equivalent
>>>> +    builtin for correctness, but must not rely on middle-end inlining
>>>> +    to do this; special-case it here.  */
>>> 
>>> Why is this necessary?  If it isn't inlined, it's still a call, and we 
>>> talked about an unknown call having the desired semantics.
>> As I understand the intention of the paper, the function is not supposed to 
>> generate any code - if, for some reason, it was not inlined then it would 
>> generate a call.
> 
> Indeed it's probably better QoI to avoid generating code,

in this instance I view it as somewhat stronger than QoI - since it’s stated in 
the paper as part of the general solution.

“
As a practical matter, a compiler can implement std::observable efficiently as 
an intrinsic that counts as a possible termination, which the optimizer thus 
cannot remove. After optimization (including any link-time optimization), the 
code generator can then produce zero machine instructions for it.
“

(I am not sure how one would turn that objective into normative text, but it 
seemed we should honour it).

> but marking the library function as always_inline should accomplish the same 
> result?

Yes, it seems to - even with -O0 -fno-inline (the function was already so 
marked).

Removed that hunk and bootstrapped and tested on x86_64-darwin24 (in fact, this 
is much the same as the implementation we have in the contracts development 
branch).

OK for trunk now?
thanks
Iain

Attachment: 0001-c-Implement-P1494-and-P3641-Partial-program-correctn.patch
Description: Binary data

Reply via email to