Обсуждение: Broken ./configure checks for __cpuid() and __cpuidex()
Hi all, While looking at patch 0001 posted by Lukas at [1], the following bit stood out as an independent fix: +++ b/configure unsigned int exx[4] = {0, 0, 0, 0}; - __get_cpuidex(exx[0], 7, 0); + __cpuidex(exx, 7, 0); The patch posted is incorrect because it does not touch configure.ac and an autoreconf -i or equivalent is missing, but it does not change the fact that this looks like a valid issue to me. While looking at the surroundings, I have noticed a second check that's incorrect in ./configure.ac, with __cpuid(). I may be missing something, of course, but these two typos have been introduced by 3dc2d62d0486, back in 2015. meson is doing these checks correctly. I have not been able to test that on cirrus, it seems to run into problems this morning. I don't know much about these instructions, but it seems like __get_cpuid_count() and __get_cpuid() are much more populate than the two others, so the impact may be lighter than I suspect for builds using ./configure. Equally, I think that one comment in meson.build is just a consequence of these two typos. The attached warrants a backpatch to me, thoughts? Thanks, [1]: https://www.postgresql.org/message-id/CAP53Pky-BN0Ui+A9no3TsU=GoMTFpxYSWYtp_LVaDH=y69BxNg@mail.gmail.com -- Michael
Вложения
On Tue, Jul 29, 2025 at 11:21:41AM +0900, Michael Paquier wrote: > The attached warrants a backpatch to me, thoughts? That's of course better with the patch. -- Michael
Вложения
Michael Paquier <michael@paquier.xyz> writes: > While looking at the surroundings, I have noticed a second check > that's incorrect in ./configure.ac, with __cpuid(). I may be missing > something, of course, but these two typos have been introduced by > 3dc2d62d0486, back in 2015. meson is doing these checks correctly. I > have not been able to test that on cirrus, it seems to run into > problems this morning. I don't know much about these instructions, > but it seems like __get_cpuid_count() and __get_cpuid() are much more > populate than the two others, so the impact may be lighter than I > suspect for builds using ./configure. That's clearly broken. Some quick googling suggests that __cpuid and __cpuidex are Microsoft-isms, so this would only affect autoconf-based builds on Windows, which probably explains how we didn't notice. Still, oughta fix it. regards, tom lane
On Tue, Jul 29, 2025 at 11:36:35AM +0900, Michael Paquier wrote: > On Tue, Jul 29, 2025 at 11:21:41AM +0900, Michael Paquier wrote: > > The attached warrants a backpatch to me, thoughts? > > That's of course better with the patch. So, the CI has accepted to run, and compilation fails with this failure when attempting to use MinGW: https://cirrus-ci.com/task/6401865375547392 [02:48:32.488] In file included from /usr/share/mingw-w64/include/intrin.h:41, [02:48:32.488] from pg_crc32c_sse42_choose.c:28: [02:48:32.488] /usr/share/mingw-w64/include/psdk_inc/intrin-impl.h:2013:42: error: macro "__cpuid" requires 5 arguments, but only 2 given [02:48:32.488] 2013 | void __cpuid(int CPUInfo[4], int InfoType); [02:48:32.488] | ^ [02:48:32.489]In file included from pg_crc32c_sse42_choose.c:24: [02:48:32.489] /usr/lib/gcc/x86_64-w64-mingw32/12-win32/include/cpuid.h:223: note: macro "__cpuid" defined here [02:48:32.489] 223 | #define __cpuid(level, a, b, c, d) \ [02:48:32.489] | [02:48:32.489] /usr/share/mingw-w64/include/psdk_inc/intrin-impl.h:2016:42: error: macro "__cpuid" requires 5 arguments, but only 2 given [02:48:32.489] 2016 | void __cpuid(int CPUInfo[4], int InfoType) { [02:48:32.489] | ^ [02:48:32.489] /usr/lib/gcc/x86_64-w64-mingw32/12-win32/include/cpuid.h:223: note: macro "__cpuid" defined here [02:48:32.489] 223 | #define __cpuid(level, a, b, c, d) \ [02:48:32.489] | [02:48:32.489] /usr/share/mingw-w64/include/psdk_inc/intrin-impl.h:2016:44: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token [02:48:32.489] 2016 | void __cpuid(int CPUInfo[4], int InfoType) { [02:48:32.489] | How isn't that a bug in MinGW itself? I'm puzzled my the macro definition of __cpuid() that reports a conflict. __cpuidex() and __cpuid() are both detected by ./configure, the PG use of __cpuid() in pg_crc32c_sse42_choose.c causes a failure. Thoughts and comments are welcome. -- Michael
Вложения
Michael Paquier <michael@paquier.xyz> writes: > /usr/share/mingw-w64/include/psdk_inc/intrin-impl.h:2013:42: error: > macro "__cpuid" requires 5 arguments, but only 2 given Yeah, surely that's broken ... > How isn't that a bug in MinGW itself? I'm puzzled my the macro > definition of __cpuid() that reports a conflict. __cpuidex() and > __cpuid() are both detected by ./configure, the PG use of __cpuid() in > pg_crc32c_sse42_choose.c causes a failure. Why is the configure probe succeeding? Maybe pg_crc32c_sse42_choose.c is including something the configure check isn't? regards, tom lane
On Mon, Jul 28, 2025 at 8:40 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> How isn't that a bug in MinGW itself? I'm puzzled my the macro
> definition of __cpuid() that reports a conflict. __cpuidex() and
> __cpuid() are both detected by ./configure, the PG use of __cpuid() in
> pg_crc32c_sse42_choose.c causes a failure.
Why is the configure probe succeeding? Maybe pg_crc32c_sse42_choose.c
is including something the configure check isn't?
Could it be that the problem only happens when including both cpuid.h and intrin.h, because they both define __cpuid? (the configure check only includes intrin.h)
My theory when I worked on the patch that Michael referenced in the original email was that intrin.h is only for MSVC (for GCC at least, __cpuidex is defined in cpuid.h).
I'm not sure how to get CI to run MinGW (it appears paused for me?), so I can't test this myself easily.
But the relevant change would be to change "defined(HAVE__CPUIDEX)" to "(defined(HAVE__CPUIDEX) && defined(_MSC_VER))" for the guard on both intrin.h includes.
Thanks,
Lukas
Lukas Fittl
On Mon, Jul 28, 2025 at 08:53:43PM -0700, Lukas Fittl wrote: > Could it be that the problem only happens when including both cpuid.h and > intrin.h, because they both define __cpuid? (the configure check only > includes intrin.h) > > My theory when I worked on the patch that Michael referenced in the > original email was that intrin.h is only for MSVC (for GCC at least, > __cpuidex is defined in cpuid.h). Ah, yes, you have the right point here, and that would be obviously the right way to do it and also why I guess MinGW is not complaining with meson: meson.build does not check for the second pieces if the first checks pass. configure checks each of these four APIs individually, and all of them detected in MinGW. So we can simply mimick in ./configure what meson does like in the attached, which has been working for some time now. The CI is happy with this version for me, with MSVC reporting the second steps, and MinGW reporting the first steps. That would be for the buildfarm to decide if it is entirely stable, but from my perspective I am pretty confident that this patch should be OK as-is. And that's pretty much what the CRC32 code expects from these checks: we only want one of these routines. > I'm not sure how to get CI to run MinGW (it appears paused for me?), so I > can't test this myself easily. src/tools/ci/README, "Enabling cirrus-ci in a github repository". I've enabled it in my own copy of Postgres on github, relying on that as an extra pre-commit check mostly for patches that are OS-sensitive. It runs independently on the CI, relying on the OS base images that Andres has been cooking for the last few years, of course. > But the relevant change would be to change "defined(HAVE__CPUIDEX)" to > "(defined(HAVE__CPUIDEX) && defined(_MSC_VER))" for the guard on both > intrin.h includes. _MSC_VER is a flag specific to MSVC, so we'd still get the problem with MinGW, no? So we'd still have the same problem. Perhaps we'll need the _MSC_VER piece for your other patch, but for the sake of the back-branches and what we are doing here it does not seem necessary to me to do so. -- Michael
Вложения
On Mon, Jul 28, 2025 at 10:30 PM Michael Paquier <michael@paquier.xyz> wrote:
meson.build does not check for the second pieces if the
first checks pass. configure checks each of these four APIs
individually, and all of them detected in MinGW. So we can simply
mimick in ./configure what meson does like in the attached, which has
been working for some time now.
The CI is happy with this version for me, with MSVC reporting the second
steps, and MinGW reporting the first steps. That would be for the
buildfarm to decide if it is entirely stable, but from my perspective
I am pretty confident that this patch should be OK as-is. And that's
pretty much what the CRC32 code expects from these checks: we only
want one of these routines.
Nice, happy to hear that makes it work, and if I got my reading of configure.ac correct, the code looks good to me.
And agreed on the approach for the back-branches, the code would only use one of the two, and it makes sense to match how Meson already behaved.
Its worth noting that __get_cpuid_count and __cpuidex are not fully equivalent (which is part of why GCC added __cpuidex despite already having __get_cpuid_count), but in any case the current code doesn't care about that, since it prefers __get_cpuid_count if available, and I think that difference only applies to special leafs like the VM Hypervisor information (not used yet).
> I'm not sure how to get CI to run MinGW (it appears paused for me?), so I
> can't test this myself easily.
src/tools/ci/README, "Enabling cirrus-ci in a github repository".
I've enabled it in my own copy of Postgres on github, relying on that
as an extra pre-commit check mostly for patches that are OS-sensitive.
It runs independently on the CI, relying on the OS base images that
Andres has been cooking for the last few years, of course.
Thanks, to be clear, I have CI enabled but the MinGW tasks were always paused (presumably because of the trigger type being manual). But I think "ci-os-only" as noted in the README should do the trick, I'll go investigate that.
> But the relevant change would be to change "defined(HAVE__CPUIDEX)" to
> "(defined(HAVE__CPUIDEX) && defined(_MSC_VER))" for the guard on both
> intrin.h includes.
_MSC_VER is a flag specific to MSVC, so we'd still get the problem
with MinGW, no? So we'd still have the same problem. Perhaps we'll
need the _MSC_VER piece for your other patch, but for the sake of the
back-branches and what we are doing here it does not seem necessary to
me to do so.
Hmm, yeah, let me do some more testing of MinGW in the context of the other patch.
FWIW, I looked again at the MinGW sources and I think you're right that intrin.h is likely also correct for MinGW. I originally thought that cpuid.h would be correct, given that's whats used by GCC/clang, but I think the MinGW source itself is authoritative here (vs the compiler in use), and that has a intrin.h include ([0]) but no cpuid.h.
Thanks,
Lukas
Lukas Fittl
On Tue, Jul 29, 2025 at 12:21:32AM -0700, Lukas Fittl wrote: > Its worth noting that __get_cpuid_count and __cpuidex are not fully > equivalent (which is part of why GCC added __cpuidex despite already > having __get_cpuid_count), but in any case the current code doesn't care > about that, since it prefers __get_cpuid_count if available, and I think > that difference only applies to special leafs like the VM Hypervisor > information (not used yet). Yes, do you think that there would be a case in the future where it makes sense to be able to detect both at the same time? Based on what I see in the tree like bitutils.c, I really doubt so. We could always deal with that if it shows as a problem later, as required. > Thanks, to be clear, I have CI enabled but the MinGW tasks were always > paused (presumably because of the trigger type being manual). But I think > "ci-os-only" as noted in the README should do the trick, I'll go > investigate that. My failures were detected in the Compiler Warnings job. > FWIW, I looked again at the MinGW sources and I think you're right that > intrin.h is likely also correct for MinGW. I originally thought that > cpuid.h would be correct, given that's whats used by GCC/clang, but I think > the MinGW source itself is authoritative here (vs the compiler in use), and > that has a intrin.h include ([0]) but no cpuid.h. Yeah. I have a close of MinGW locally, and that matches what I saw. Applied on all the branches. Let's wait for the buildfarm to report, now. -- Michael
Вложения
On Wed, Jul 30, 2025 at 12:02:44PM +0900, Michael Paquier wrote: > On Tue, Jul 29, 2025 at 12:21:32AM -0700, Lukas Fittl wrote: >> FWIW, I looked again at the MinGW sources and I think you're right that >> intrin.h is likely also correct for MinGW. I originally thought that >> cpuid.h would be correct, given that's whats used by GCC/clang, but I think >> the MinGW source itself is authoritative here (vs the compiler in use), and >> that has a intrin.h include ([0]) but no cpuid.h. > > Yeah. I have a close of MinGW locally, and that matches what I saw. s/close/clone/. > Applied on all the branches. Let's wait for the buildfarm to report, > now. The first reports are popping up for the Windows animals, and as far as I can see things seem to tbe OK for now in terms of the flavors of __cpuid & friends detected, for the mix of meson, MinGW, MSVC and configure that we have. -- Michael
Вложения
Hi, On 2025-07-29 00:21:32 -0700, Lukas Fittl wrote: > On Mon, Jul 28, 2025 at 10:30 PM Michael Paquier <michael@paquier.xyz> > wrote: > > > I'm not sure how to get CI to run MinGW (it appears paused for me?), so I > > > can't test this myself easily. > > > > src/tools/ci/README, "Enabling cirrus-ci in a github repository". > > I've enabled it in my own copy of Postgres on github, relying on that > > as an extra pre-commit check mostly for patches that are OS-sensitive. > > It runs independently on the CI, relying on the OS base images that > > Andres has been cooking for the last few years, of course. > > > > Thanks, to be clear, I have CI enabled but the MinGW tasks were always > paused (presumably because of the trigger type being manual). But I think > "ci-os-only" as noted in the README should do the trick, I'll go > investigate that. FWIW, you can trigger manual tasks in the cirrus-ci web-interface. Greetings, Andres Freund