Unintended LTO configuration differences between ELF and COFF

Using the new pass manager, we recently ran across an interesting problem where some LTO optimization behaved differently on Windows versus Linux. We traced it down to differences in createConfig() in lld/ELF/LTO.cpp and lld/COFF/LTO.cpp. The ELF version has

c.PTO.LoopVectorization = c.OptLevel > 1;
c.PTO.SLPVectorization = c.OptLevel > 1;

but the COFF version does not. Eyeballing the two versions, it looks like there are probably a number of things that are unintentionally missing from the COFF version.

Arguably, vectorization enablement is a compiler setting that shouldn’t depend on the target environment, or even which linker is being used. Would it be better for such things to be moved into runNewPMPasses() in llvm/lib/LTO/LTOBackend.cpp?

Obviously I could submit a patch to do this for the vectorization settings, but there are quite a few other differences, and I don’t feel qualified to determine the proper resolution for all of them. Hence this post. It would be good if somebody knowledgeable could make some recommendations to bring the two environments back in line. (I didn’t even look at MachO, or any of the other linkers.)

Thanks!
Bill

1 Like

c.PTO.LoopVectorization = c.OptLevel > 1;

c.PTO.LoopVectorization is inferred from c.OptLevel, which is also set by user code. If we want to have a unified setting, c.PTO.LoopVectorization needs to know whether user code has explicitly provided c.PTO.LoopVectorization.

Nowadays some downstream projects set the option explicitly, including rust llvm-wrapper/PassWrapper.cpp, halide, wasm-micro-runtime.

It may be good for lld/COFF to use ELF’s way setting LoopVectorization, but I think it is difficult to make things more unified now.

That’s fair, and perhaps these decisions need to stay in ELF/COFF/MachO as they are. But I still think there’s a lot of unintended divergence that should be investigated, and perhaps some commentary additions to try to reduce these occurrences in the future.