[llvm] [Clang][InstCombine] Recognise div/ldiv/lldiv libcalls (PR #215868)

Magnus Strømme via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 5 09:00:10 PDT 2026


================
@@ -923,7 +923,13 @@ static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
 static void getAllNoBuiltinFuncValues(ArgList &Args,
                                       std::vector<std::string> &Funcs) {
   std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);
-  auto BuiltinEnd = llvm::partition(Values, Builtin::Context::isBuiltinFunc);
+  auto IsBuiltinFunc = [](StringRef Name) {
+    // These libcalls have target-specific aggregate return types that cannot be
+    // represented by Clang's builtin type encoding.
+    return Builtin::Context::isBuiltinFunc(Name) || Name == "div" ||
+           Name == "ldiv" || Name == "lldiv";
----------------
Magnushst wrote:

I measured it, sdiv+srem on the same operands already lowers to a single idivl on x86-64 (DivRemPairs plus the SDIVREM combine):
  %q = sdiv i32 %a, %b
  %r = srem i32 %a, %b
  ->  movl %edi, %eax ; cltd ; idivl %esi ; retq

So yeah, you're right, this fold buys nothing the backend doesn't already give you from plain division and remainder. The only reason it isn't done that way today is that div/ldiv/lldiv aren't builtins in Clang; abs/labs/llabs are, but there's nothing equivalent for the div family. So the call survives to IR, and catching it there means rebuilding div_t's per-target ABI shape (packed integer, struct, array, one-element wrapper, sret) plus endianness. That's where all the complexity came from as Clang has none of it, since it builds div_t itself.

Thanks to everyone who spent time on it. I don't think further investment here is welcome, so I'll leave it there. Closing.

https://github.com/llvm/llvm-project/pull/215868


More information about the llvm-commits mailing list