Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for LLVM 16 and bump LDC-LLVM to v16.0.6 for prebuilt packages #4423

Merged
merged 30 commits into from
Aug 16, 2023

Conversation

kinke
Copy link
Member

@kinke kinke commented Jun 11, 2023

Based on #4411.

ikeycode and others added 13 commits June 3, 2023 22:05
In stable LLVM 16 this is now under `Support` and not `IR`

Signed-off-by: Ikey Doherty <[email protected]>
The StandardInstrumentations type now takes an LLVMContext parameter
so pass it along from the current module.

Signed-off-by: Ikey Doherty <[email protected]>
Instructions now use friend APIs to add themselves into a
BasicBlock, rather than a BasicBlock having an API to add
the instructions.

Signed-off-by: Ikey Doherty <[email protected]>
This was killed upstream in the codegen pipeline as part of a bunch of
legacy PM removals:

 - https://reviews.llvm.org/D137116

Signed-off-by: Ikey Doherty <[email protected]>
This isn't *the* most ideal approach and in future we may want
to select specific fallbacks other than "generic".

Signed-off-by: Ikey Doherty <[email protected]>
Unfortunately when building with LLVM < 15, we're using C++-11,
so the std::optional bits are only available in C++-17.

Even more unfortunately we can't really override this, rather
inherit the fact of using C++-17 when using LLVM > 16.

Thus, we add a slightly messy conditional compilation situation
to allow usage of LDC on older LLVM versions, and with newer
LLVM/libcxx.

Signed-off-by: Ikey Doherty <[email protected]>
Modified to have an explicit `main()` per the other profdata
imports in this tree.

Signed-off-by: Ikey Doherty <[email protected]>
@kinke
Copy link
Member Author

kinke commented Jun 12, 2023

Regarding the rather immediate crashes when compiling druntime/Phobos, we'll probably need an LLVM with enabled assertions to check for LLVM 16 changes.

@kinke
Copy link
Member Author

kinke commented Jul 7, 2023

@thewilsonator: The GitHub Actions Main workflow is currently using an LDC-LLVM v16.0.6 candidate (from https://github.com/ldc-developers/llvm-project/releases/tag/CI), one with SPIRV included as experimental target. 3 dcompute lit-tests fail, hitting an assertion wrt. t->toBasetype()->ty == TY::Ttuple || stripAddrSpaces(v->getType()) == DtoPtrToType(t), see e.g. https://github.com/ldc-developers/ldc/actions/runs/5485337264/jobs/9994033947.

@thewilsonator
Copy link
Contributor

Thanks, Will take a look over the weekend

@kinke
Copy link
Member Author

kinke commented Jul 7, 2023

The dmd-testsuite regressions (2 failures with apparently same cause) with that LDC-LLVM 16 on Mac and Windows look really bad:

Test 'fail_compilation/dtor_attributes.d' failed: 
[...]
----
diff:
----
 fail_compilation/dtor_attributes.d(118): Error: `pure` function `dtor_attributes.test1` cannot call impure destructor `dtor_attributes.Strict.~this`
-fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is impure because of the following field's destructors:
+fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(111):         - HasDtor member
-fail_compilation/dtor_attributes.d(103):           impure `HasDtor.~this` is declared here
+fail_compilation/dtor_attributes.d(103):           @�Y�@� `HasDtor.~this` is declared here
 fail_compilation/dtor_attributes.d(118): Error: `@safe` function `dtor_attributes.test1` cannot call `@system` destructor `dtor_attributes.Strict.~this`
 fail_compilation/dtor_attributes.d(113):        which calls `dtor_attributes.Strict.~this`
 fail_compilation/dtor_attributes.d(103):        which calls `dtor_attributes.HasDtor.~this`
 fail_compilation/dtor_attributes.d(113):        `dtor_attributes.Strict.~this` is declared here
-fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is @system because of the following field's destructors:
+fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(111):         - HasDtor member
-fail_compilation/dtor_attributes.d(103):           @system `HasDtor.~this` is declared here
+fail_compilation/dtor_attributes.d(103):           ��Y�@� `HasDtor.~this` is declared here
 fail_compilation/dtor_attributes.d(118): Error: `@nogc` function `dtor_attributes.test1` cannot call non-@nogc destructor `dtor_attributes.Strict.~this`
 fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is non-@nogc because of the following field's destructors:
 fail_compilation/dtor_attributes.d(111):         - HasDtor member
 fail_compilation/dtor_attributes.d(103):           non-@nogc `HasDtor.~this` is declared here
 fail_compilation/dtor_attributes.d(118): Error: destructor `dtor_attributes.Strict.~this` is not `nothrow`
-fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is not nothrow because of the following field's destructors:
+fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(111):         - HasDtor member
-fail_compilation/dtor_attributes.d(103):           not nothrow `HasDtor.~this` is declared here
+fail_compilation/dtor_attributes.d(103):           �
+Y�@� `HasDtor.~this` is declared here
 fail_compilation/dtor_attributes.d(116): Error: function `dtor_attributes.test1` may throw but is marked as `nothrow`
 fail_compilation/dtor_attributes.d(209): Error: `pure` function `dtor_attributes.test2` cannot call impure destructor `dtor_attributes.StrictClass.~this`
-fail_compilation/dtor_attributes.d(204):        generated `StrictClass.~this` is impure because of the following field's destructors:
+fail_compilation/dtor_attributes.d(204):        generated `StrictClass.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(203):         - HasDtor member
-fail_compilation/dtor_attributes.d(103):           impure `HasDtor.~this` is declared here
+fail_compilation/dtor_attributes.d(103):           �
+Y�@� `HasDtor.~this` is declared here
 fail_compilation/dtor_attributes.d(321): Error: `pure` function `dtor_attributes.test3` cannot call impure destructor `dtor_attributes.StrictStructRef.~this`
-fail_compilation/dtor_attributes.d(316):        generated `StrictStructRef.~this` is impure because of the following field's destructors:
+fail_compilation/dtor_attributes.d(316):        generated `StrictStructRef.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(310):         - HasDtor structMember
-fail_compilation/dtor_attributes.d(103):           impure `HasDtor.~this` is declared here
+fail_compilation/dtor_attributes.d(103):           �
+Y�@� `HasDtor.~this` is declared here
 fail_compilation/dtor_attributes.d(411): Error: `pure` function `dtor_attributes.test4` cannot call impure destructor `dtor_attributes.StrictNested.~this`
-fail_compilation/dtor_attributes.d(406):        generated `StrictNested.~this` is impure because of the following field's destructors:
+fail_compilation/dtor_attributes.d(406):        generated `StrictNested.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(403):         - HasDtor[4] arrayMember
-fail_compilation/dtor_attributes.d(103):           impure `HasDtor.~this` is declared here
+fail_compilation/dtor_attributes.d(103):           ��Y�@� `HasDtor.~this` is declared here
 fail_compilation/dtor_attributes.d(509): Error: `pure` function `dtor_attributes.test5` cannot call impure destructor `dtor_attributes.Permissive.~this`
 fail_compilation/dtor_attributes.d(618): Error: `pure` function `dtor_attributes.test6` cannot call impure destructor `dtor_attributes.HasNestedDtor3.~this`
-fail_compilation/dtor_attributes.d(611):        generated `HasNestedDtor3.~this` is impure because of the following field's destructors:
+fail_compilation/dtor_attributes.d(611):        generated `HasNestedDtor3.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(613):         - HasNestedDtor2 member3
-fail_compilation/dtor_attributes.d(606):        generated `HasNestedDtor2.~this` is impure because of the following field's destructors:
+fail_compilation/dtor_attributes.d(606):        generated `HasNestedDtor2.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(608):         - HasNestedDtor1 member2
-fail_compilation/dtor_attributes.d(601):        generated `HasNestedDtor1.~this` is impure because of the following field's destructors:
+fail_compilation/dtor_attributes.d(601):        generated `HasNestedDtor1.~this` is ���m#O1� because of the following field's destructors:
 fail_compilation/dtor_attributes.d(603):         - HasDtor member1
-fail_compilation/dtor_attributes.d(103):           impure `HasDtor.~this` is declared here
+fail_compilation/dtor_attributes.d(103):            `HasDtor.~this` is declared here

Smells like a miscompile of the compiler itself. I've checked the garbage strings, they are passed as literals to checkOverridenDtor(), where they are passed as length+ptr varargs pair for errorSupplemental() %.*s formatting. So I doubt this is memory corruption, but the varargs getting corrupted somehow with that new LLVM (but working fine on Linux).

@thewilsonator
Copy link
Contributor

@thewilsonator: The GitHub Actions Main workflow is currently using an LDC-LLVM v16.0.6 candidate (from https://github.com/ldc-developers/llvm-project/releases/tag/CI), one with SPIRV included as experimental target. 3 dcompute lit-tests fail, hitting an assertion wrt. t->toBasetype()->ty == TY::Ttuple || stripAddrSpaces(v->getType()) == DtoPtrToType(t), see e.g. https://github.com/ldc-developers/ldc/actions/runs/5485337264/jobs/9994033947.

Looking at it, that seems to be harmless. For LLVM 16 (where pointers are always opaque) the second part of the || should probably be replaced with isaPointer(v->getType()) anyway since DtoPtrToType(t) == getVoidPtrType() always. If it still trips after that change then we have a problem somewhere. Will do some actual testing tomorrow.

@kinke
Copy link
Member Author

kinke commented Jul 8, 2023

We still default to non-opaque pointers with LLVM 16, as we aren't ready yet: #4261

@thewilsonator
Copy link
Contributor

Oh, in that case the cause of that assertion is

ldc/gen/tollvm.cpp

Lines 589 to 590 in d4f2bed

#if LDC_LLVM_VER >= 1600
return getVoidPtrType();
it should do the LLVM14-15 path and check for isOpaque

@kinke
Copy link
Member Author

kinke commented Jul 10, 2023

Yep thx, that was it.

@kinke
Copy link
Member Author

kinke commented Aug 12, 2023

The LLVM 16 bump is a PITA because of:

  1. Vanilla LLVM CI job:
    • macOS: Their official releases on GitHub don't have any x86_64 archive anymore, only arm64.
    • Linux x64: They now use primarily Ubuntu 22, with 16.0.0 being the only available Ubuntu-18 archive. I don't want to bump the CI job to Ubuntu 22 (from 20), because its gdb came with regressions for global variables, leading to at least 4 test failures (lit testsuite + DMD testsuite). And unfortunately I cannot use a Mac job instead.
      Edit: Oh, and we're hitting weird immediate crashes in llvm::AttrBuilder::addAlignmentAttr() with that LLVM 16.0.0 Ubuntu 18 archive. I've locally built v16.0.0 with enabled assertions, and the LDC build went through just fine. The v16.0.3 Ubuntu 22 package didn't have that problem in Enable LLVM 16.0.3 #4411. I guess there's something off with that official v16.0.0 archive.
  2. The apparent miscompile of the frontend itself on Windows and Mac mentioned above in Add support for LLVM 16 and bump LDC-LLVM to v16.0.6 for prebuilt packages #4423 (comment). In the release log, they mention a miscompile with an LTO+PGO combo caused by newly enabled-by-default function specializations; I'm wondering if we're hitting something similar.

@kinke kinke force-pushed the llvm16-2 branch 2 times, most recently from 13f69f7 to 358761d Compare August 13, 2023 09:02
@kinke
Copy link
Member Author

kinke commented Aug 13, 2023

Wrt. the miscompile when compiling the frontend with LLVM 16, I've tried:

  1. Reverting to clang v15 (from v16) for compiling both LLVM and the LDC C++ parts; didn't change anything.
  2. Additionally disabling PGO (for the compiler) alone; didn't change anything.
  3. Additionally disabling LTO (for the compiler):
    • Makes the Win64 job finally green (Win32 was already green before).
    • Causes a libc++abi: Pure virtual function called! error on Mac x64 when trying to compile druntime/Phobos with that fresh LDC compiled with itself!

@JohanEngelen
Copy link
Member

could the miscompile be because of typed pointers no longer being really supported by LLVM?

@kinke
Copy link
Member Author

kinke commented Aug 13, 2023

Your guess is probably as good as mine, but I don't think so.

@kinke
Copy link
Member Author

kinke commented Aug 13, 2023

Disabling the new function specializations has fixed the miscompile on Win64 at least; Mac still needs troubleshooting.

@kinke kinke force-pushed the llvm16-2 branch 2 times, most recently from 66f0b82 to fcc5fa7 Compare August 13, 2023 13:33
@kinke
Copy link
Member Author

kinke commented Aug 13, 2023

macOS x64 is 'solved' too now (with LTO+PGO), after disabling the func specializations for the LTO plugin too. 2 important questions remain:

  1. What about arm64 macOS? Linux aarch64 is good. @JohanEngelen: Could you please test the main GHA CI artifact (once available - edit: https://github.com/ldc-developers/ldc/actions/runs/5847668379?pr=4423) and check whether you get any crashes or garbage outputs for fail_compilation/dtor_attributes.d? (maybe run a few times to really be sure)
  2. Looks like the func specializations are highly problematic for us, at least for some platforms. As our generated IR for Linux and macOS x64 don't differ much, I'm a bit skeptical about the problem lying in our court (such as still using typed IR pointers etc.). So I think we should disable it by default in ldc2.conf when using LLVM 16 for now (CMake ADDITIONAL_DEFAULT_LDC_SWITCHES). I guess for all targets to be on the safe side?

@JohanEngelen
Copy link
Member

I will test soon. What is the flag to enable/disable the func specialization?

@kinke
Copy link
Member Author

kinke commented Aug 13, 2023

I will test soon.

Great! Nothing to build, just downlaod & extract CI artifact, then try compiling the failing module. The cross-compiled binary is either miscompiled (will crash or produce garbage) or works.

What is the flag to enable/disable the func specialization?

I'm using -func-specialization-size-threshold=1000000000, so that all functions with less than 1e9 instructions aren't candidates. ;) - It defaults to 100 in LLVM 16.

@JohanEngelen
Copy link
Member

the macos arm64 artifact produces a little garbage indeed...

❯ bin/ldc2 ~/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(118): Error: `pure` function `dtor_attributes.test1` cannot call impure destructor `dtor_attributes.Strict.~this`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is destructor because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(111):         - HasDtor member
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(103):           member `HasDtor.~this` is declared here
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(118): Error: `@safe` function `dtor_attributes.test1` cannot call `@system` destructor `dtor_attributes.Strict.~this`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(113):        `dtor_attributes.Strict.~this` is declared here
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is function because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(111):         - HasDtor member
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(103):           member `HasDtor.~this` is declared here
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(118): Error: `@nogc` function `dtor_attributes.test1` cannot call non-@nogc destructor `dtor_attributes.Strict.~this`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is non-@nogc because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(111):         - HasDtor member
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(103):           non-@nogc `HasDtor.~this` is declared here
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(118): Error: destructor `dtor_attributes.Strict.~this` is not `nothrow`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(113):        generated `Strict.~this` is �_��_����_��{��(`@9 because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(111):         - HasDtor member
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(103):           member `HasDtor.~this` is declared here
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(116): Error: function `dtor_attributes.test1` may throw but is marked as `nothrow`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(209): Error: `pure` function `dtor_attributes.test2` cannot call impure destructor `dtor_attributes.StrictClass.~this`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(204):        generated `StrictClass.~this` is destructor because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(203):         - HasDtor member
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(103):           member `HasDtor.~this` is declared here
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(321): Error: `pure` function `dtor_attributes.test3` cannot call impure destructor `dtor_attributes.StrictStructRef.~this`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(316):        generated `StrictStructRef.~this` is destructor because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(310):         - HasDtor structMember
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(103):           structMember `HasDtor.~this` is declared here
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(411): Error: `pure` function `dtor_attributes.test4` cannot call impure destructor `dtor_attributes.StrictNested.~this`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(406):        generated `StrictNested.~this` is destructor because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(403):         - HasDtor[4] arrayMember
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(103):           arrayMember `HasDtor.~this` is declared here
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(509): Error: `pure` function `dtor_attributes.test5` cannot call impure destructor `dtor_attributes.Permissive.~this`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(618): Error: `pure` function `dtor_attributes.test6` cannot call impure destructor `dtor_attributes.HasNestedDtor3.~this`
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(611):        generated `HasNestedDtor3.~this` is destructor because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(613):         - HasNestedDtor2 member3
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(606):        generated `HasNestedDtor2.~this` is `�� because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(608):         - HasNestedDtor1 member2
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(601):        generated `HasNestedDtor1.~this` is `�� because of the following field's destructors:
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(603):         - HasDtor member1
/Users/johan/ldc/ldc/tests/dmd/fail_compilation/dtor_attributes.d(103):           member1 `HasDtor.~this` is declared here

@kinke
Copy link
Member Author

kinke commented Aug 13, 2023

Alright, thx a lot for testing.

@kinke kinke changed the title [CI: Play with LLVM 16] Add support for LLVM 16 and bump LDC-LLVM to v16.0.6 for prebuilt packages Aug 14, 2023
@kinke kinke marked this pull request as ready for review August 14, 2023 09:43
@kinke
Copy link
Member Author

kinke commented Aug 14, 2023

[The CircleCI Mac jobs 'fail' because we've run out of credits.]

@kinke kinke merged commit c1105d5 into ldc-developers:master Aug 16, 2023
23 checks passed
@kinke kinke deleted the llvm16-2 branch August 16, 2023 09:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants