upmem / llvm-project

This is a mirror and a fork of the upstream LLVM repository with the DPU hardware support. The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
7 stars 3 forks source link

Arithmetic + Jump instructions are not correctly handled in O0 #58

Open JordiChauzi opened 3 years ago

JordiChauzi commented 3 years ago

When looking at #57 in O0, i found at that this is a more generic issue. Here are two examples with the problem (64-bit rotation & 64-bit count leading zeros): https://dpu.dev/z/zwJoIP

The important, and faulty, part in both cases is that the result from the arithmetic + jump instruction is not correctly spilled:

Here is my hypothesis: in O0, llvm will always spill registers just before the last instruction in a MBB. However, this is only possible if the last instruction in the MBB does not modify registers, and it seems like llvm does not handle the other case correctly (it will try to spill the register before the last instruction anyway).

It seems to me that the only safe solution for us is to never use arithmetic + jump instructions in O0. Most uses can be found in the functions called by DPUTargetLowering::EmitInstrWithCustomInserter (in llvm/lib/Target/DPU/DPUTargetLowering.cpp). The 16-bit multiplication case seems to be already handled (cf PerformMULCombine in llvm/lib/Target/DPU/DPUTargetLowering.cpp). The other important case is when we automatically try to merge two instructions (cf DPUMacroFusion.cpp and mostly DPUMergeComboInstrPass.cpp). I could not find an example to make it fail (llvm adds a lot of load/store between the operations before this pass, so that it may not be possible to merge anything), however I think it would be safer to also disable this pass in O0.

dlagneux-upmem commented 3 years ago

This gives me a headache!