[llvm] [WebAssembly] Fix SELECT_CC lowering for reference types (PR #181622)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 16 01:54:05 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-webassembly
Author: Hood Chatham (hoodmane)
<details>
<summary>Changes</summary>
SELECT_CC nodes with externref or funcref return types were not being expanded, causing "Cannot select" errors during instruction selection.
This adds SELECT_CC to the list of operations that should be expanded for reference types, similar to how it's already handled for scalar types (i32, i64, f32, f64). This allows the SELECT_CC to be lowered to a SELECT node, which already has instruction patterns defined in WebAssemblyInstrRef.td.
---
Full diff: https://github.com/llvm/llvm-project/pull/181622.diff
2 Files Affected:
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp (+6)
- (modified) llvm/test/CodeGen/WebAssembly/select.ll (+62)
``````````diff
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 2799b0ee0c804..a26db5ef5cf92 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -370,6 +370,12 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
setOperationAction(Op, T, Expand);
+ // Reference types need SELECT_CC to be expanded to SELECT as well.
+ if (Subtarget->hasReferenceTypes()) {
+ for (auto T : {MVT::externref, MVT::funcref})
+ setOperationAction(ISD::SELECT_CC, T, Expand);
+ }
+
// We have custom switch handling.
setOperationAction(ISD::BR_JT, MVT::Other, Custom);
diff --git a/llvm/test/CodeGen/WebAssembly/select.ll b/llvm/test/CodeGen/WebAssembly/select.ll
index 93faf2e3dd3f7..de7525e96a426 100644
--- a/llvm/test/CodeGen/WebAssembly/select.ll
+++ b/llvm/test/CodeGen/WebAssembly/select.ll
@@ -383,3 +383,65 @@ define float @pr44012_i64(i64 %x, float %y, float %z) {
%c = select i1 %b, float %y, float %z
ret float %c
}
+
+; Reference type tests (externref and funcref)
+
+define ptr addrspace(10) @select_externref_eq(i32 %a, ptr addrspace(10) %b, ptr addrspace(10) %c) {
+; CHECK-LABEL: select_externref_eq:
+; CHECK: .functype select_externref_eq (i32, externref, externref) -> (externref)
+; CHECK: externref.select $push0=, $2, $1, $0
+; CHECK-NEXT: return $pop0
+;
+; FAST-LABEL: select_externref_eq:
+; FAST: .functype select_externref_eq (i32, externref, externref) -> (externref)
+; FAST: externref.select $push0=, $2, $1, $0
+; FAST-NEXT: return $pop0
+ %cmp = icmp eq i32 %a, 0
+ %cond = select i1 %cmp, ptr addrspace(10) %b, ptr addrspace(10) %c
+ ret ptr addrspace(10) %cond
+}
+
+define ptr addrspace(10) @select_externref_ne(i32 %a, ptr addrspace(10) %b, ptr addrspace(10) %c) {
+; CHECK-LABEL: select_externref_ne:
+; CHECK: .functype select_externref_ne (i32, externref, externref) -> (externref)
+; CHECK: externref.select $push0=, $1, $2, $0
+; CHECK-NEXT: return $pop0
+;
+; FAST-LABEL: select_externref_ne:
+; FAST: .functype select_externref_ne (i32, externref, externref) -> (externref)
+; FAST: externref.select $push0=, $1, $2, $0
+; FAST-NEXT: return $pop0
+ %cmp = icmp ne i32 %a, 0
+ %cond = select i1 %cmp, ptr addrspace(10) %b, ptr addrspace(10) %c
+ ret ptr addrspace(10) %cond
+}
+
+define ptr addrspace(20) @select_funcref_eq(i32 %a, ptr addrspace(20) %b, ptr addrspace(20) %c) {
+; CHECK-LABEL: select_funcref_eq:
+; CHECK: .functype select_funcref_eq (i32, funcref, funcref) -> (funcref)
+; CHECK: funcref.select $push0=, $2, $1, $0
+; CHECK-NEXT: return $pop0
+;
+; FAST-LABEL: select_funcref_eq:
+; FAST: .functype select_funcref_eq (i32, funcref, funcref) -> (funcref)
+; FAST: funcref.select $push0=, $2, $1, $0
+; FAST-NEXT: return $pop0
+ %cmp = icmp eq i32 %a, 0
+ %cond = select i1 %cmp, ptr addrspace(20) %b, ptr addrspace(20) %c
+ ret ptr addrspace(20) %cond
+}
+
+define ptr addrspace(20) @select_funcref_ne(i32 %a, ptr addrspace(20) %b, ptr addrspace(20) %c) {
+; CHECK-LABEL: select_funcref_ne:
+; CHECK: .functype select_funcref_ne (i32, funcref, funcref) -> (funcref)
+; CHECK: funcref.select $push0=, $1, $2, $0
+; CHECK-NEXT: return $pop0
+;
+; FAST-LABEL: select_funcref_ne:
+; FAST: .functype select_funcref_ne (i32, funcref, funcref) -> (funcref)
+; FAST: funcref.select $push0=, $1, $2, $0
+; FAST-NEXT: return $pop0
+ %cmp = icmp ne i32 %a, 0
+ %cond = select i1 %cmp, ptr addrspace(20) %b, ptr addrspace(20) %c
+ ret ptr addrspace(20) %cond
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/181622
More information about the llvm-commits
mailing list