https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124088

            Bug ID: 124088
           Summary: [contracts] -fcontracts-conservative-ipa is
                    unnecessary and wrong as long as no mechanism for
                    runtime-configurable evaluation semantics is
                    implemented
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mkretz at gcc dot gnu.org
  Target Milestone: ---

Test case (https://compiler-explorer.com/z/x9nbh73ac):

#define _GLIBCXX_SIMD_TOSTRING_IMPL(x) #x
#define _GLIBCXX_SIMD_TOSTRING(x) _GLIBCXX_SIMD_TOSTRING_IMPL(x)
#define _GLIBCXX_SIMD_LOC __FILE__ ":" _GLIBCXX_SIMD_TOSTRING(__LINE__) ": "

#define check_precondition(expr) \
  do {                                                                         
  \
    const bool __precondition_result = !bool(expr);                            
  \
    if (__builtin_constant_p(__precondition_result) && __precondition_result)  
  \
      []() __attribute__((__noipa__, __warning__(                              
  \
        "precondition failure. \n" _GLIBCXX_SIMD_LOC "note: precondition '"
#expr \
        "' does not hold"))) {}();                                             
  \
    if (__builtin_expect(__precondition_result, false))                        
  \
      __builtin_trap();                                                        
  \
  } while(false)

inline
int f(int x)
{
  check_precondition(x >= 0 && x < 32);
  return 1 << x;
}

int g(int* ptr) pre(ptr != 0)
{
  if (ptr)
    return *ptr;
  return f(32);
}

Compile with -O2 -Wall -std=c++26 -fcontracts

-fcontract-evaluation-semantic can be either enforce or quick_enforce

With -fcontracts-conservative-ipa the above code emits a warning. With
-fno-contracts-conservative-ipa it does not emit a warning.

I believe IPA is doing the right thing here because it is looking at a concrete
implementation of https://eel.is/c++draft/basic.contract#eval-5, which
implements unconditional predicate evaluation and termination on contract
failure. Once GCC implements "It is unspecified whether the predicate is
evaluated." via e.g. a branch on a global variable, which can jump over
predicate evaluation and termination, then IPA will have to stop optimizing as
it does. This can be simulated right now by writing the function 'g' as a
dispatch function (https://compiler-explorer.com/z/az4qsKKoE):

inline int g_ignored(int* ptr)
{
  if (ptr)
    return *ptr;
  return f(32);
}

inline int g_checked(int* ptr) pre(ptr != 0)
{
  return g_ignored(ptr);
}

extern bool __always_ignore;

int g(int* ptr)
{
  if (__always_ignore)
    return g_ignored(ptr);
  else
    return g_checked(ptr);
}

The wording "It is unspecified whether the predicate is evaluated." allows
runtime-replaceable contracts evaluation semantics. If and only if
runtime-replaceble evaluation semantics are implemented is the removal of
assumptions necessary. And IPA already gets that right.

Reply via email to