[llvm] [Mips] Fix cttz.i32 fails to lower on mips16 (PR #179633)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 5 02:09:59 PST 2026
https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/179633
>From af68a29d2d64d2c4aca2b32420457e3d23b0e7b4 Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Wed, 4 Feb 2026 17:34:44 +0800
Subject: [PATCH] [Mips] Fix cttz.i32 fails to lower on mips16
MIPS16 cannot handle constant pools created by CTTZ table lookup
expansion. This causes "Cannot select" errors when trying to select
MipsISD::Lo nodes for constant pool addresses.
Modify the table lookup conditions to check ConstantPool operation
status, and only set ConstantPool to Custom in non-MIPS16 mode in
MIPS backend.
This ensures MIPS16 uses the ISD::CTPOP instead of attempting
unsupported constant pool operations.
Fix #61055.
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 3 +-
llvm/lib/Target/Mips/MipsISelLowering.cpp | 6 +-
.../Mips/GlobalISel/llvm-ir/cttz-mips16.ll | 61 +++++++++++++++++++
3 files changed, 67 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/cttz-mips16.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index a10b93063dc27..09d46a44b551b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9692,7 +9692,8 @@ SDValue TargetLowering::expandCTTZ(SDNode *Node, SelectionDAG &DAG) const {
// Emit Table Lookup if ISD::CTPOP used in the fallback path below is going
// to be expanded or converted to a libcall.
if (!VT.isVector() && !isOperationLegalOrCustomOrPromote(ISD::CTPOP, VT) &&
- !isOperationLegal(ISD::CTLZ, VT))
+ !isOperationLegal(ISD::CTLZ, VT) &&
+ isOperationCustom(ISD::ConstantPool, VT))
if (SDValue V = CTTZTableLookup(Node, DAG, dl, VT, Op, NumBitsPerElt))
return V;
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index f7e2825edcc5d..dae8f411ff654 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -224,7 +224,8 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
- setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
+ if (!Subtarget.inMips16Mode())
+ setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::SELECT, MVT::f32, Custom);
setOperationAction(ISD::SELECT, MVT::f64, Custom);
setOperationAction(ISD::SELECT, MVT::i32, Custom);
@@ -272,7 +273,8 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::BlockAddress, MVT::i64, Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
- setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
+ if (!Subtarget.inMips16Mode())
+ setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
setOperationAction(ISD::SELECT, MVT::i64, Custom);
if (Subtarget.hasMips64r6()) {
setOperationAction(ISD::LOAD, MVT::i64, Legal);
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/cttz-mips16.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/cttz-mips16.ll
new file mode 100644
index 0000000000000..7dbb4fc567a8b
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/cttz-mips16.ll
@@ -0,0 +1,61 @@
+; RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips32 -mattr=+mips16 -verify-machineinstrs < %s | FileCheck %s -check-prefixes=MIPS16
+
+define i32 @cttz_i32(i32 %a) {
+; MIPS16-LABEL: cttz_i32:
+; MIPS16: # %bb.0: # %entry
+; MIPS16-NEXT: not $2, $4
+; MIPS16-NEXT: addiu $4, -1 # 16 bit inst
+; MIPS16-NEXT: and $4, $2
+; MIPS16-NEXT: srl $2, $4, 1
+; MIPS16-NEXT: lw $3, $CPI0_0 # 16 bit inst
+; MIPS16-NEXT: and $3, $2
+; MIPS16-NEXT: subu $2, $4, $3
+; MIPS16-NEXT: lw $3, $CPI0_1 # 16 bit inst
+; MIPS16-NEXT: srl $4, $2, 2
+; MIPS16-NEXT: and $2, $3
+; MIPS16-NEXT: and $4, $3
+; MIPS16-NEXT: addu $2, $2, $4
+; MIPS16-NEXT: srl $3, $2, 4
+; MIPS16-NEXT: addu $2, $2, $3
+; MIPS16-NEXT: lw $3, $CPI0_2 # 16 bit inst
+; MIPS16-NEXT: and $3, $2
+; MIPS16-NEXT: lw $2, $CPI0_3 # 16 bit inst
+; MIPS16-NEXT: mult $3, $2
+; MIPS16-NEXT: mflo $2
+; MIPS16-NEXT: srl $2, $2, 24
+; MIPS16-NEXT: jrc $ra
+
+entry:
+ %0 = call i32 @llvm.cttz.i32(i32 %a, i1 false)
+ ret i32 %0
+}
+declare i32 @llvm.cttz.i32(i32, i1 immarg)
+
+define i64 @cttz_i64(i64 %a) {
+; MIPS16-LABEL: cttz_i64:
+; MIPS16: # %bb.1: # %entry
+; MIPS16-NEXT: not $4, $5
+; MIPS16-NEXT: addiu $5, -1 # 16 bit inst
+; MIPS16-NEXT: and $5, $4
+; MIPS16-NEXT: srl $4, $5, 1
+; MIPS16-NEXT: and $4, $7
+; MIPS16-NEXT: subu $4, $5, $4
+; MIPS16-NEXT: srl $5, $4, 2
+; MIPS16-NEXT: and $4, $6
+; MIPS16-NEXT: and $5, $6
+; MIPS16-NEXT: addu $4, $4, $5
+; MIPS16-NEXT: srl $5, $4, 4
+; MIPS16-NEXT: addu $4, $4, $5
+; MIPS16-NEXT: and $4, $3
+; MIPS16-NEXT: mult $4, $2
+; MIPS16-NEXT: mflo $2
+; MIPS16-NEXT: srl $2, $2, 24
+; MIPS16-NEXT: addiu $2, 32 # 16 bit inst
+; MIPS16-NEXT: li $3, 0
+; MIPS16-NEXT: jrc $ra
+
+entry:
+ %0 = call i64 @llvm.cttz.i64(i64 %a, i1 false)
+ ret i64 %0
+}
+declare i64 @llvm.cttz.i64(i64, i1 immarg)
More information about the llvm-commits
mailing list