[llvm] [SelectionDAG] Respect no-builtins attribute in SMULO expansion (PR #191020)
Cameron Taggart via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 8 10:52:37 PDT 2026
https://github.com/cataggar updated https://github.com/llvm/llvm-project/pull/191020
>From 4f8a0ff918698a6359a835069a1c5e68cced38ff Mon Sep 17 00:00:00 2001
From: Cameron Taggart <cataggar at microsoft.com>
Date: Wed, 8 Apr 2026 17:27:13 +0100
Subject: [PATCH] [SelectionDAG] Respect no-builtins attribute in SMULO
expansion
When expanding ISD::SMULO for types that require a libcall (e.g. i128
on WebAssembly), the legalizer now checks for the "no-builtins"
function attribute. If present, it expands inline instead of emitting
a call to __muloti4.
This prevents infinite recursion when a custom implementation of
__muloti4 (under a different name) is compiled with no-builtins, as
the overflow intrinsic introduced by instcombine would otherwise be
lowered back to a call to __muloti4.
Fixes https://github.com/llvm/llvm-project/issues/189173
Assisted-by: GitHub Copilot
---
.../SelectionDAG/LegalizeIntegerTypes.cpp | 9 +++++---
.../WebAssembly/muloti4-no-builtins.ll | 21 +++++++++++++++++++
2 files changed, 27 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/WebAssembly/muloti4-no-builtins.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 35e61b78e99a2..eed88eb3cdd47 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -5301,11 +5301,14 @@ void DAGTypeLegalizer::ExpandIntRes_XMULO(SDNode *N,
RTLIB::Libcall LC = RTLIB::getMULO(VT);
RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
- // If we don't have the libcall or if the function we are compiling is the
- // implementation of the expected libcall (avoid inf-loop), expand inline.
+ // If we don't have the libcall, if the function we are compiling is the
+ // implementation of the expected libcall (avoid inf-loop), or if the
+ // function has the no-builtins attribute (it may be a custom implementation
+ // of the libcall under a different name), expand inline.
if (LCImpl == RTLIB::Unsupported ||
RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LCImpl) ==
- DAG.getMachineFunction().getName()) {
+ DAG.getMachineFunction().getName() ||
+ DAG.getMachineFunction().getFunction().hasFnAttribute("no-builtins")) {
// FIXME: This is not an optimal expansion, but better than crashing.
SDValue MulLo, MulHi;
TLI.forceExpandWideMUL(DAG, dl, /*Signed=*/true, N->getOperand(0),
diff --git a/llvm/test/CodeGen/WebAssembly/muloti4-no-builtins.ll b/llvm/test/CodeGen/WebAssembly/muloti4-no-builtins.ll
new file mode 100644
index 0000000000000..b75bf4d16fb58
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/muloti4-no-builtins.ll
@@ -0,0 +1,21 @@
+; RUN: llc -asm-verbose=false < %s -wasm-keep-registers | FileCheck %s
+
+; Test that 128-bit smul.with.overflow does not emit a call to __muloti4
+; when the function has the "no-builtins" attribute. This avoids infinite
+; recursion when the function is a custom implementation of __muloti4.
+; See https://github.com/llvm/llvm-project/issues/189173
+
+target triple = "wasm32-unknown-unknown"
+
+define i128 @custom_muloti4(i128 %a, i128 %b) nounwind "no-builtins" {
+entry:
+ %smul = tail call { i128, i1 } @llvm.smul.with.overflow.i128(i128 %a, i128 %b)
+ %cmp = extractvalue { i128, i1 } %smul, 1
+ %smul.result = extractvalue { i128, i1 } %smul, 0
+ %X = select i1 %cmp, i128 %smul.result, i128 42
+ ret i128 %X
+}
+
+; CHECK-NOT: call __muloti4
+
+declare { i128, i1 } @llvm.smul.with.overflow.i128(i128, i128) nounwind readnone
More information about the llvm-commits
mailing list