Add GlobalISel infrastructure up to the point where we can select a ret void.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Hi @RKSimon,
Implementing GlobalISel for M68k is one of the Outreachy (3-month internship, 24 May to 24 Aug) projects. Sushma is one of the candidates for this project. To select the candidate there is currently a contribution period(till 9 May) is going on. This patch is a kind of task to check the skills of candiadate.
So we (project mentor: Anshil & Myself) don't have an industry use case, it is more about education purpose. and then further improve it to a stable state. We know that currently, GlobalISel doesn't have big-endian targets support. But we had listed this project after an email conversation with Amara and Quentin.
So yes it is also our responsibility to add big-endian targets in GlobalISel. We ask Amara and Quentin about how we can implement this part. So I think I should also share their response with Sushma.
Amara :
The places where you’re most likely to run into issues with big endian are in the IRTranslator (including CallLowering), and the legalizer (in LegalizerHelper.cpp) (which has to deal with illegal memory operations, and therefore can split them into pieces that may not be correct when using big-endian).
The majority of this code I don’t expect to require many changes. The issue I see is that unless you already have a M68000 GISel backend, how you’re going to try test cases to see what needs fixing is going to be hard. Perhaps you could try using AArch64 scalar code with big-endian to see what problems come up (IIRC AArch64’s big-endian scheme w.r.t vectors may be different to other backends in SelectionDAG).
Quentin:
+1 on the IRTranslator and the Legalizer. Basically anything that
breaks down chunks of bytes into smaller chunks of bytes may need
fixing (e.g., lowering a structure, legalizing a large load by
splitting it in smaller loads, etc.).
Unfortunately, we didn't get much time to look at the source code to implement the support. We are also kind of inexperienced in this field and open to any suggestions from the community. But I want to assure you that as soon as or before that we select the intern we will look into this also.
While implementing RegBankInfo for M68k, since it has 3 register classes .ie. data, address and index register classes, should I define 3 register banks in the registerBanks.td file?
@sushmaunnibhavi For this patch, I think you only care about the general-purpose register bank. Have you looked at RISCV:https://reviews.llvm.org/D65219 , PowerPC:https://reviews.llvm.org/D83100 or Mips: https://reviews.llvm.org/D43583 implementations and read the https://llvm.org/docs/GlobalISel/GMIR.html#register-bank.
Please try to start with a test case and minimal implementation to support it as described in Head First into GlobalISel Tutorial.
(I wish you have something before 10-12 May to commit.)
I guess it is better to implement an initial but complete (all passes) skeleton of GlobalISel infrastructure for M68k than doing in pass by pass starting with IRTranslator. I saw the most previous implementations in this way.
(but I also don't have actual experience in implementing them so don't know which way is better)
some minor style cleanups
llvm/lib/Target/M68k/CMakeLists.txt | ||
---|---|---|
7 | (style) match indentation of the other entries | |
26 | (style) sorting | |
39 | (style) sorting | |
llvm/lib/Target/M68k/M68k.h | ||
21 | (style) sorting | |
llvm/lib/Target/M68k/M68kCallLowering.cpp | ||
53 ↗ | (On Diff #343856) | (style) missing newline |
llvm/lib/Target/M68k/M68kCallLowering.h | ||
45 ↗ | (On Diff #343856) | (style) missing newline |
llvm/lib/Target/M68k/M68kInstructionSelector.cpp | ||
60 ↗ | (On Diff #343856) | (style) missing newline |
llvm/lib/Target/M68k/M68kLegalizerInfo.cpp | ||
23 ↗ | (On Diff #343856) | (style) missing newline |
llvm/lib/Target/M68k/M68kLegalizerInfo.h | ||
28 ↗ | (On Diff #343856) | (style) missing newline |
llvm/lib/Target/M68k/M68kRegisterBankInfo.cpp | ||
27 ↗ | (On Diff #343856) | (style) missing newline |
llvm/lib/Target/M68k/M68kRegisterBankInfo.h | ||
38 ↗ | (On Diff #343856) | (style) missing newline |
llvm/lib/Target/M68k/M68kRegisterBanks.td | ||
14 ↗ | (On Diff #343856) | (style) missing newline |
Hi,
Add GlobalISel infrastructure up to the point where we can select a ret void.
Could you add a test case for that?
E.g., something as simple as:
; RUN: llc -global-isel %s -o - | FileCheck %s ; CHECK-LABEL: noArgRetVoid: ; CHECK: <whatever is your return instruction here> define void @noArgRetVoid() { ret void }
Yes, I added this
; RUN: llc -mtriple=m68k -global-isel %s -o - | FileCheck %s ; CHECK: name: f ; CHECK: RET define void @f() { ret void }
And when I run this test case, I get an error saying:
.text .file "irtranslator-ret.ll" LLVM ERROR: unable to translate in big endian mode (in function: f) PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace. Stack dump: 0. Program arguments: ./build/bin/llc -mtriple=m68k -global-isel /home/sushma/Desktop/llvm-project/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-ret.ll -o - 1. Running pass 'Function Pass Manager' on module '/home/sushma/Desktop/llvm-project/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-ret.ll'. 2. Running pass 'IRTranslator' on function '@f' #0 0x000055615e5e371c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (./build/bin/llc+0x2dcf71c) #1 0x000055615e5e1524 llvm::sys::RunSignalHandlers() (./build/bin/llc+0x2dcd524) #2 0x000055615e5e1693 SignalHandler(int) Signals.cpp:0:0 #3 0x00007ffbb3cc2f40 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x13f40) #4 0x00007ffbb376bed7 raise /build/glibc-KRRWSm/glibc-2.29/signal/../sysdeps/unix/sysv/linux/raise.c:51:1 #5 0x00007ffbb374d535 abort /build/glibc-KRRWSm/glibc-2.29/stdlib/abort.c:81:7 #6 0x000055615e549f46 llvm::report_fatal_error(llvm::Twine const&, bool) (./build/bin/llc+0x2d35f46) #7 0x000055615e54a09e (./build/bin/llc+0x2d3609e) #8 0x000055615ec7f9d9 reportTranslationError(llvm::MachineFunction&, llvm::TargetPassConfig const&, llvm::OptimizationRemarkEmitter&, llvm::OptimizationRemarkMissed&) IRTranslator.cpp:0:0 #9 0x000055615ec9491f llvm::IRTranslator::runOnMachineFunction(llvm::MachineFunction&) (./build/bin/llc+0x348091f) #10 0x000055615da0c925 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (./build/bin/llc+0x21f8925) #11 0x000055615de51a14 llvm::FPPassManager::runOnFunction(llvm::Function&) (./build/bin/llc+0x263da14) #12 0x000055615de52559 llvm::FPPassManager::runOnModule(llvm::Module&) (./build/bin/llc+0x263e559) #13 0x000055615de51331 llvm::legacy::PassManagerImpl::run(llvm::Module&) (./build/bin/llc+0x263d331) #14 0x000055615c1d251d compileModule(char**, llvm::LLVMContext&) llc.cpp:0:0 #15 0x000055615c117c72 main (./build/bin/llc+0x903c72) #16 0x00007ffbb374eb6b __libc_start_main /build/glibc-KRRWSm/glibc-2.29/csu/../csu/libc-start.c:342:3 #17 0x000055615c1c949a _start (./build/bin/llc+0x9b549a) Aborted (core dumped)
And I am working on this right now.
Hi,
LLVM ERROR: unable to translate in big endian mode (in function: f)
You'll need to turn that into a warning, otherwise effectively, none of your GISel changes will be testable (as in running the generated code on an actual target) until the support is complete, which is not a realistic constraint to have when bringing up a new GISel backend.
Cheers,
-Quentin
llvm/CMakeLists.txt | ||
---|---|---|
315 ↗ | (On Diff #348675) | M68k is an experimental target - it should NOT be added to any default target list |
Removing reportTranslationError() in IRtranslator.cpp file until big endian is supported.
llvm/CMakeLists.txt | ||
---|---|---|
315 ↗ | (On Diff #348675) | I will be temporarily keeping this in default targets since if I don't then when I submit the patch it will show "M68kGenRegisterBank.inc file not found" error. Maybe the buildbot does not check M68k backend with experimental_target_build flag. So I am keeping M68k in default targets temporarily. |
Hi @qcolombet ,
When I do a git grep with that error message, I find that it comes from IRTranslator.cpp file and in the runOnMachineFunction() function where it checks for big endian and throws a reportTranslationError() which is where that error comes from. By removing the reportTranslationError() temporarily in order to test my implementation, that would cause errors in other targets. Can you please suggest me any other way to solve this issue?
Thanks,
Sushma
You can add a hook to TargetLoweringInfo so that only targets which want to use big-endian in GlobalISel can enable it (just M68k for now). Then check this hook, if it false then do the current fallback code.
llvm/CMakeLists.txt | ||
---|---|---|
315 ↗ | (On Diff #348675) | I'm not familiar with this issue, but it sounds like a problem with the build system/cmake config. Either way, even adding this temporarily to the default targets can't be done if you want to have this committed. |
Hi,
By removing the reportTranslationError() temporarily in order to test my implementation, that would cause errors in other targets. Can you please suggest me any other way to solve this issue?
That kind of errors are you seeing in other targets?
Also like Amara said, you can turn that into a warning on for M68k with a target hook.
Cheers,
-Quentin
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | ||
---|---|---|
3133 | Instead of purely removing it, turn that into a warning. |
Yes I see those errors only in other targets after removing reportTranslationError(). The M68k test case doesn't fail.
Yes, I will do as Amara said.
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | ||
---|---|---|
3133 | @qcolombet , @aemerson if (Triple(MF->getTarget().getTargetTriple()).getArch() != Triple::m68k) { reportTranslationError(*MF, *TPC, *ORE, R); } This would not call reportTranslationError only for m68k but would not affect any other targets. |
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | ||
---|---|---|
3133 | It's less preferable than a TLI hook because it encodes target specific behavior into the translator. |
- Changed the test case name to noArgRetVoid
- Removed M68k from default targets in CMakeList.txt file
- Added enableBigEndian() hook so that targets which want to use big endian can enable it.
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | ||
---|---|---|
3136 | (style) Drop unnecessary braces | |
llvm/lib/Target/M68k/GlSel/M68kCallLowering.cpp | ||
33 | (style) Drop unnecessary braces | |
llvm/lib/Target/M68k/GlSel/M68kInstructionSelector.cpp | ||
78 | (style) Drop unnecessary braces and move comment above if() | |
llvm/lib/Target/M68k/GlSel/M68kLegalizerInfo.h | ||
28 | (style) Missing // LLVM_LIB_TARGET_M68K_GLSEL_M68KLEGALIZERINFO_H | |
llvm/test/CodeGen/M68k/GlobalISel/irtranslator-ret.ll | ||
8 | add newline |
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | ||
---|---|---|
3133 | I have created an enableBigEndian() hook which the targets can use if they want to use big-endian. I ran the tests locally and the tests passed. But some of the unit tests fail when I submitted the patch which is not related to globalisel. What could be the reason for that? I am new to compilers so wanted to know where I am going wrong. |
@aemerson , @qcolombet , @RKSimon, @myhsu can you review the patch?
I think the clang-tidy errors in M68kRegisterBankInfo.h come because the buildbot doesn't build with DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="M68k". But when built with DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="M68k" no such errors occur.
I have created an enableBigEndian() hook in llvm/CodeGen/GlobalISel/CallLowering.h which the targets can use if they want to use big-endian. For now only M68k uses this. Then in the IRTranslator.cpp file I check if the target wants to use big-endian, if yes that the reportTranslationError(*MF, *TPC, *ORE, R) will not be called.
That's exactly the issue - I don't think there's a way to force the buildbot to run for a particular LLVM_EXPERIMENTAL_TARGETS_TO_BUILD. This works in the other way too - changes to common code don't get tested on experimental targets. In both cases its up to the target maintainers to handle any regressions.
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | ||
---|---|---|
3125–3127 | Would this be better: if (!DL->isLittleEndian() && !CLI->enableBigEndian()) { I'm not sure if we should always emit at least a warning that big-endian gisel isn't properly supported. |
llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h | ||
---|---|---|
573 | I don't think this should be added. You already know the endianness from the datalayout |
llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h | ||
---|---|---|
573 | The point is that even if a DL says we're using big-endian, without properly implemented and tested support we don't want to actually use GlobalISel. This hook will let us override the fallback for targets like M68K while it's under development. |
@sushmaunnibhavi There is still a clang-tidy error : 'M68kGenRegisterBank.inc' file not found
First of all, big thanks for doing this :-)
Sorry for coming in late. This patch LGTM in general, just have some formatting / coding style comments.
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | ||
---|---|---|
3132 | (nit) please remove this empty line if it's not necessary | |
llvm/lib/Target/M68k/GlSel/M68kCallLowering.cpp | ||
30 | ||
llvm/lib/Target/M68k/GlSel/M68kCallLowering.h | ||
11 | Can you use the same file-level comment as M68kCallLowering.cpp? | |
26 | Can you also a TODO here (or in the implementation side) to note that we're only supporting return instruction with no value at this time point | |
llvm/lib/Target/M68k/GlSel/M68kInstructionSelector.cpp | ||
17 | ||
llvm/lib/Target/M68k/GlSel/M68kLegalizerInfo.h | ||
10 | ||
23 | (nit) Can you use struct instead of class since there is not private member here? | |
llvm/lib/Target/M68k/GlSel/M68kRegisterBankInfo.cpp | ||
23 | ditto, missing #undef? | |
llvm/lib/Target/M68k/GlSel/M68kRegisterBankInfo.h | ||
20 | should there be a #undef GET_REGBANK_DECLARATIONS? right after this line? | |
30 | ditto, should there be a #undef here? | |
llvm/lib/Target/M68k/GlSel/M68kRegisterBanks.td | ||
9 | Can you add a brief file-level comment? | |
llvm/lib/Target/M68k/M68kSubtarget.cpp | ||
64 | this casting seems to be redundant |
I recommend you to check the "Done" checkbox by an inline comment when you resolve a comment. With that you can easily navigate through unresolved comments by clicking on the "X/Y Comments" button on the top-right corner.
llvm/lib/Target/M68k/GlSel/M68kCallLowering.h | ||
---|---|---|
2 | this should be .h not .cpp, I think you forget to change this when copy the comments | |
llvm/lib/Target/M68k/GlSel/M68kLegalizerInfo.h | ||
10 | still outstanding |
llvm/lib/Target/M68k/M68kSubtarget.cpp | ||
---|---|---|
64 | But when I remove that cast it causes build errors when I build M68k |
llvm/lib/Target/M68k/M68kSubtarget.cpp | ||
---|---|---|
64 | In revision 351840, you changed the line into createM68kInstructionSelector(&TM, ...) but the first argument of createM68kInstructionSelector takes value of type const M68kTargetMachine& so of course it didn't compile. I think createM68kInstructionSelector(TM, ...) is the right way. I recommend you to read the compile error message. |
Changed
InstSelector.reset(createM68kInstructionSelector( *static_cast<const M68kTargetMachine *>(&TM), *this, *RBI));
to
InstSelector.reset(createM68kInstructionSelector(TM, *this, *RBI))
I don't think this should be added. You already know the endianness from the datalayout