On Mon, Oct 20, 2025 at 11:24 AM Tomasz Kaminski <[email protected]>
wrote:
> Another topic is that SIMD uses following custom precondition macro:
> #if not IFNDR_SIMD_PRECONDITIONS
> #define __glibcxx_simd_precondition(expr, msg, ...)
> \
> do {
> \
> if (__builtin_expect(!bool(expr), false))
> \
> std::simd::__invoke_ub(
> \
> _GLIBCXX_SIMD_LOC "precondition failure in '%s':\n" msg " ('"
> #expr "' does not hold)", \
> __PRETTY_FUNCTION__ __VA_OPT__(,) __VA_ARGS__);
> \
> } while(false)
> #else
> #define __glibcxx_simd_precondition(expr, msg, ...)
> \
> do {
> \
> const bool __precondition_result = !bool(expr);
> \
> if (__builtin_constant_p(__precondition_result) &&
> __precondition_result) \
> []() __attribute__((__noinline__, __noipa__, __error__("precondition
> failure." \
> "\n" _GLIBCXX_SIMD_LOC "note: " msg " (precondition '" #expr "'
> does not hold)"))) \
> { __builtin_unreachable(); }();
> \
> else if (__builtin_expect(__precondition_result, false))
> \
> std::simd::__invoke_ub(
> \
> _GLIBCXX_SIMD_LOC "precondition failure in '%s':\n" msg " ('"
> #expr "' does not hold)", \
> __PRETTY_FUNCTION__ __VA_OPT__(,) __VA_ARGS__);
> \
> } while(false)
> #endif
>
> I do not think that turning (possible) preconditions violations into an
> ill-formed program is conforming,
> and the error should be emitted only if the part of code is evaluated. In
> particular it is fine to to have a
> template instantiation that will emit a call that will break precondition,
> if it is never reached.
>
> The second, most important concern I have is that this lead to checks
> being completely removed,
> without any message, even if assertion would be enabled. For example for
> this very simple test program:
> void foo(int n)
> {
> const bool __precondition_result = !bool(n < 5);
> if (__builtin_constant_p(__precondition_result) && __precondition_result)
> []() __attribute__(( __error__("precondition failure."
> "\n" "foo" "note: " "err" " (precondition 'n < 5' does not hold)")))
> { __builtin_unreachable(); }();
> }
>
> void bar(bool b, int x) {
> if (b)
> foo(x + 7);
> }
> The `bar` gets compiled to (link
> <https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:15,endLineNumber:14,positionColumn:15,positionLineNumber:14,selectionStartColumn:15,selectionStartLineNumber:14,startColumn:15,startLineNumber:14),source:'%23include+%3Carray%3E%0A%0Avoid+foo(int+n)%0A%7B%0A++const+bool+__precondition_result+%3D+!!bool(n+%3C+5)%3B%0A++if+(__builtin_constant_p(__precondition_result)+%26%26+__precondition_result)+%0A+++++++++%5B%5D()+__attribute__((+__error__(%22precondition+failure.%22%0A++++++++%22%5Cn%22+%22foo%22+%22note:+%22+%22err%22+%22+(precondition+!'n+%3C+5!'+does+not+hold)%22)))%0A++++++%7B+__builtin_unreachable()%3B+%7D()%3B%0A%7D%0A%0Avoid+bar(bool+b,+int+x)+%7B%0A++if+(b)%0A+++foo(x+%2B+7)%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:34.98432601880877,l:'4',m:56.23733182907284,n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:gsnapshot,filters:(b:'0',binary:'1',binaryObject:'1',commentOnly:'0',debugCalls:'1',demangle:'0',directives:'0',execute:'0',intel:'0',libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!((name:fmt,ver:trunk)),options:'-std%3Dc%2B%2B26+-O2',overrides:!(),selection:(endColumn:12,endLineNumber:4,positionColumn:1,positionLineNumber:3,selectionStartColumn:12,selectionStartLineNumber:4,startColumn:1,startLineNumber:3),source:1),l:'5',n:'0',o:'+x86-64+gcc+(trunk)+(Editor+%231)',t:'0')),header:(),k:50,l:'4',m:37.02290076335878,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(editorid:1,fontScale:14,fontUsePx:'0',j:1,wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+gcc+(trunk)+(Compiler+%231)',t:'0')),header:(),l:'4',m:62.97709923664122,n:'0',o:'',s:0,t:'0')),k:65.01567398119123,l:'3',n:'0',o:'',t:'0')),l:'2',m:100.00000000000001,n:'0',o:'',t:'0')),version:4>
> ):
> "bar(bool, int)":
> ret
>
More illustrative example:
int foo(int n)
{
const bool __precondition_result = !bool(n < 5);
if (__builtin_constant_p(__precondition_result) && __precondition_result)
[]() __attribute__(( __error__("precondition failure."
"\n" "foo" "note: " "err" " (precondition 'n < 5' does not hold)")))
{ __builtin_unreachable(); }();
else
return 10;
}
int bar(bool b, int x) {
if (b)
return foo(7);
return 20;
}
bar again get's compiled to (link
<https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:4,endLineNumber:3,positionColumn:4,positionLineNumber:3,selectionStartColumn:4,selectionStartLineNumber:3,startColumn:4,startLineNumber:3),source:'%23include+%3Carray%3E%0A%0Aint+foo(int+n)%0A%7B%0A++const+bool+__precondition_result+%3D+!!bool(n+%3C+5)%3B%0A++if+(__builtin_constant_p(__precondition_result)+%26%26+__precondition_result)+%0A+++++++++%5B%5D()+__attribute__((+__error__(%22precondition+failure.%22%0A++++++++%22%5Cn%22+%22foo%22+%22note:+%22+%22err%22+%22+(precondition+!'n+%3C+5!'+does+not+hold)%22)))%0A++++++%7B+__builtin_unreachable()%3B+%7D()%3B%0A++++++return+n%3B%0A%7D%0A%0Avoid+bar(bool+b,+int+x)+%7B%0A++if+(b)%0A+++foo(x+%2B+7)%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:34.98432601880877,l:'4',m:56.23733182907284,n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:gsnapshot,filters:(b:'0',binary:'1',binaryObject:'1',commentOnly:'0',debugCalls:'1',demangle:'0',directives:'0',execute:'0',intel:'0',libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!((name:fmt,ver:trunk)),options:'-std%3Dc%2B%2B26+-O2',overrides:!(),selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'+x86-64+gcc+(trunk)+(Editor+%231)',t:'0')),header:(),k:50,l:'4',m:37.02290076335878,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(editorid:1,fontScale:14,fontUsePx:'0',j:1,wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+gcc+(trunk)+(Compiler+%231)',t:'0')),header:(),l:'4',m:62.97709923664122,n:'0',o:'',s:0,t:'0')),k:65.01567398119123,l:'3',n:'0',o:'',t:'0')),l:'2',m:100.00000000000001,n:'0',o:'',t:'0')),version:4>
):
"bar(bool, int)":
mov eax, 20
ret
While if the condition is not know at compile time (link
<https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:1,endLineNumber:19,positionColumn:1,positionLineNumber:14,selectionStartColumn:1,selectionStartLineNumber:19,startColumn:1,startLineNumber:14),source:'%23include+%3Carray%3E%0A%0Aint+foo(int+n)%0A%7B%0A++const+bool+__precondition_result+%3D+!!bool(n+%3C+5)%3B%0A++if+(__builtin_constant_p(__precondition_result)+%26%26+__precondition_result)+%0A+++++++++%5B%5D()+__attribute__((+__error__(%22precondition+failure.%22%0A++++++++%22%5Cn%22+%22foo%22+%22note:+%22+%22err%22+%22+(precondition+!'n+%3C+5!'+does+not+hold)%22)))%0A++++++%7B+__builtin_unreachable()%3B+%7D()%3B%0A++++++else%0A++return+10%3B%0A%7D%0A%0Aint+bar(bool+b,+int+x)+%7B%0A++if+(b)%0A+++return+foo(x+%2B+7)%3B%0A++return+20%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:34.98432601880877,l:'4',m:56.23733182907284,n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:gsnapshot,filters:(b:'0',binary:'1',binaryObject:'1',commentOnly:'0',debugCalls:'1',demangle:'0',directives:'0',execute:'0',intel:'0',libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!((name:fmt,ver:trunk)),options:'-std%3Dc%2B%2B26+-O2',overrides:!(),selection:(endColumn:12,endLineNumber:9,positionColumn:1,positionLineNumber:4,selectionStartColumn:12,selectionStartLineNumber:9,startColumn:1,startLineNumber:4),source:1),l:'5',n:'0',o:'+x86-64+gcc+(trunk)+(Editor+%231)',t:'0')),header:(),k:50,l:'4',m:37.02290076335878,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(editorid:1,fontScale:14,fontUsePx:'0',j:1,wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+gcc+(trunk)+(Compiler+%231)',t:'0')),header:(),l:'4',m:62.97709923664122,n:'0',o:'',s:0,t:'0')),k:65.01567398119123,l:'3',n:'0',o:'',t:'0')),l:'2',m:100.00000000000001,n:'0',o:'',t:'0')),version:4>
):
int bar(bool b, int x) {
if (b)
return foo(x + 7);
return 20;
}
"bar(bool, int)":
cmp dil, 1
sbb eax, eax
and eax, 10
add eax, 10
ret
Given that you have an option on trapping in __invoke__ub, the option to
> report errors on precondition seems to be desired.
>
> I think I would prefer the direction of just using plain __glibcxx_assert
> for libstdc++, and not innovate a new error checking
> strategies.
>
> Would be interested to hear other people's opinions on this.
>
> Regards,
> Tomasz
>
>
> On Wed, Oct 8, 2025 at 1:54 PM Matthias Kretz <[email protected]> wrote:
>
>> This set of patches implements C++26 [simd]. The implementation differs a
>> lot
>> from the std::experimental implementation. I tried my best to reduce the
>> number of template instantiations wrt. what std::experimental::simd does.
>>
>> A basic_vec/basic_mask that uses multiple registers is built as a tree of
>> smaller specializations, where the left branch always stores a power-of-2
>> number of elements.
>>
>> Still missing: [simd.loadstore], [simd.permute.dynamic],
>> [simd.permute.mask],
>> [simd.permute.memory].
>>
>> [simd.math] is partially implemented. But I don't want to go any further
>> on
>> this without some feedback on the direction I took.
>>
>> I have an extensive set of unit tests at
>> https://github.com/GSI-HPC/simd/tree/
>> rewrite. But I don't want to repeat what I did for
>> std::experimental::simd. So
>> I'll look into possibly keeping an external complete simd testsuite while
>> added some tests to libstdc++ later.
>>
>> The PR is split into multiple commits to hopefully make it easier to get
>> through the review.
>>
>> Matthias Kretz (11):
>> libstdc++: C++26 [simd] details
>> libstdc++: Implement C++26 [simd.iterator]
>> libstdc++: C++26 [simd] rebind, resize, permute, chunk, cat and
>> basic_mask
>> libstdc++: Implement C++26 [simd.mask.reductions]
>> libstdc++: Implement C++26 [simd.flags] and alignment(_v)
>> libstdc++: Implement C++26 [simd] basic_vec
>> libstdc++: Implement C++26 [simd.alg]
>> libstdc++: Implement C++26 [simd.bit]
>> libstdc++: Implement C++26 [simd.reductions]
>> libstdc++: Specialize basic_mask and basic_vec for complex value-types
>> libstdc++: First sketch for C++26 [simd.math]
>>
>> libstdc++-v3/include/bits/simd_alg.h | 76 +
>> libstdc++-v3/include/bits/simd_bit.h | 156 ++
>> libstdc++-v3/include/bits/simd_complex.h | 1342 +++++++++++
>> libstdc++-v3/include/bits/simd_details.h | 1443 +++++++++++
>> libstdc++-v3/include/bits/simd_flags.h | 265 ++
>> libstdc++-v3/include/bits/simd_iterator.h | 153 ++
>> libstdc++-v3/include/bits/simd_mask.h | 1732 ++++++++++++++
>> .../include/bits/simd_mask_reductions.h | 94 +
>> libstdc++-v3/include/bits/simd_math.h | 993 ++++++++
>> libstdc++-v3/include/bits/simd_reductions.h | 112 +
>> libstdc++-v3/include/bits/simd_vec.h | 2130 +++++++++++++++++
>> libstdc++-v3/include/bits/simd_x86.h | 953 ++++++++
>> libstdc++-v3/include/bits/vec_ops.h | 592 +++++
>> 13 files changed, 10041 insertions(+)
>> create mode 100644 libstdc++-v3/include/bits/simd_alg.h
>> create mode 100644 libstdc++-v3/include/bits/simd_bit.h
>> create mode 100644 libstdc++-v3/include/bits/simd_complex.h
>> create mode 100644 libstdc++-v3/include/bits/simd_details.h
>> create mode 100644 libstdc++-v3/include/bits/simd_flags.h
>> create mode 100644 libstdc++-v3/include/bits/simd_iterator.h
>> create mode 100644 libstdc++-v3/include/bits/simd_mask.h
>> create mode 100644 libstdc++-v3/include/bits/simd_mask_reductions.h
>> create mode 100644 libstdc++-v3/include/bits/simd_math.h
>> create mode 100644 libstdc++-v3/include/bits/simd_reductions.h
>> create mode 100644 libstdc++-v3/include/bits/simd_vec.h
>> create mode 100644 libstdc++-v3/include/bits/simd_x86.h
>> create mode 100644 libstdc++-v3/include/bits/vec_ops.h
>>
>> --
>> ──────────────────────────────────────────────────────────────────────────
>> Dr. Matthias Kretz https://mattkretz.github.io
>> GSI Helmholtz Center for Heavy Ion Research https://gsi.de
>> std::simd
>> ──────────────────────────────────────────────────────────────────────────
>>
>>
>>
>>
>>