This is an archive of the discontinued LLVM Phabricator instance.

[PPCISelLowering] Avoid emitting calls to __multi3, __muloti4
ClosedPublic

Authored by aaronpuchert on Mar 19 2022, 4:57 PM.

Details

Summary

After D108936, @llvm.smul.with.overflow.i64 was lowered to multi3
instead of
mulodi4, which also doesn't exist on PowerPC 32-bit, not
even with compiler-rt. Block it as well so that we get inline code.

Just to be on the safe side, we also block __muloti4 as D108842 did
for ARM. Though I have no idea if there is legitimate C code that ends
up using this since 32-bit arches have no 128-bit int type.

Fixes #54460.

Diff Detail

Event Timeline

aaronpuchert created this revision.Mar 19 2022, 4:57 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 19 2022, 4:58 PM
aaronpuchert requested review of this revision.Mar 19 2022, 4:58 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 19 2022, 4:58 PM
craig.topper added inline comments.Mar 19 2022, 6:46 PM
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
1346

Can probably pull say MULO_I128 isn't available on PP64 either. It does not exist in libgcc only in compiler-rt. So if we want to support linking with libgcc it should be removed.

aaronpuchert marked an inline comment as done.

Block MULO_I128 also on 64-bit, because libgcc doesn't have __muloti4 there.

This revision is now accepted and ready to land.Mar 19 2022, 10:07 PM

Had to adapt two more tests where we were emitting __multi3 calls on PowerPC 32-bit. That builtin doesn't exist even in compiler-rt, so I guess it's an improvement.

I was also wondering if we could block the overflow intrinsics only if Subtarget.getTargetTriple().isGNUEnvironment() is true, but we can also discuss this separately. (That would affect all targets then, I guess.)

This revision was landed with ongoing or failed builds.Mar 20 2022, 1:00 PM
This revision was automatically updated to reflect the committed changes.

I was also wondering if we could block the overflow intrinsics only if Subtarget.getTargetTriple().isGNUEnvironment() is true, but we can also discuss this separately.

I see that @craig.topper suggested something similar in D109385.

On the Clang side, we have in clang::driver::ToolChain:

enum RuntimeLibType {
  RLT_CompilerRT,
  RLT_Libgcc
};

and then virtual RuntimeLibType GetDefaultRuntimeLibType() const. Going through the overrides (git grep -A3 GetDefaultRuntimeLibType clang/lib/Driver/ clang/include/clang/Driver/), it seems that compiler-rt is the default on AIX, BareMetal, Darwin, Fuchsia, Android Linux, OpenBSD, VE, and WebAssembly. But it's just the default, there could still be a --rtlib= command line argument. And since the backend is using the builtin even in cases where the original code didn't use it, we have to be very careful.

An alternative is to pass on the --rtlib= argument to the backend (or put it into metadata). At least I think the backend currently doesn't know about the runtime library being used.

I was also wondering if we could block the overflow intrinsics only if Subtarget.getTargetTriple().isGNUEnvironment() is true, but we can also discuss this separately.

I see that @craig.topper suggested something similar in D109385.

On the Clang side, we have in clang::driver::ToolChain:

enum RuntimeLibType {
  RLT_CompilerRT,
  RLT_Libgcc
};

and then virtual RuntimeLibType GetDefaultRuntimeLibType() const. Going through the overrides (git grep -A3 GetDefaultRuntimeLibType clang/lib/Driver/ clang/include/clang/Driver/), it seems that compiler-rt is the default on AIX, BareMetal, Darwin, Fuchsia, Android Linux, OpenBSD, VE, and WebAssembly. But it's just the default, there could still be a --rtlib= command line argument. And since the backend is using the builtin even in cases where the original code didn't use it, we have to be very careful.

An alternative is to pass on the --rtlib= argument to the backend (or put it into metadata). At least I think the backend currently doesn't know about the runtime library being used.

I think it would only be safe to assume --rtlib=compiler-rt if the compiler was driving a full link. Otherwise, the linker could be invoked manually against libgcc.

I think it would only be safe to assume --rtlib=compiler-rt if the compiler was driving a full link. Otherwise, the linker could be invoked manually against libgcc.

True, currently one might only pass --rtlib= for the link, but I think we could reasonably require it for compilation as well. (That is, forgetting it might work but would officially be unsupported.)

This is not something that I would drive anyway, I'm on Linux and I'll probably continue to use libgcc for now.