-
Notifications
You must be signed in to change notification settings - Fork 16k
[Mips] Fix cttz.i32 fails to lower on mips16 #179633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
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. The fix adds a virtual method `canUseConstantPoolForCTTZ()` to TargetLowering. MIPS16 overrides this to return false, using ISD::CTPOP. Fix llvm#61055.
|
@llvm/pr-subscribers-llvm-selectiondag @llvm/pr-subscribers-backend-mips Author: None (yingopq) ChangesMIPS16 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. The fix adds a virtual method Fix #61055. Full diff: https://github.com/llvm/llvm-project/pull/179633.diff 5 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index ada4ffd3bcc89..27954affe7b61 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -727,6 +727,9 @@ class LLVM_ABI TargetLoweringBase {
return false;
}
+ /// Return true if constant pool can be used for CTTZ expansion.
+ virtual bool canUseConstantPoolForCTTZ() const { return true; }
+
/// Return true if ctlz instruction is fast.
virtual bool isCtlzFast() const {
return false;
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index a10b93063dc27..2c02e761b1b03 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9691,8 +9691,9 @@ 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.
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
if (!VT.isVector() && !isOperationLegalOrCustomOrPromote(ISD::CTPOP, VT) &&
- !isOperationLegal(ISD::CTLZ, VT))
+ !isOperationLegal(ISD::CTLZ, VT) && TLI.canUseConstantPoolForCTTZ())
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..d92b70633fb94 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -1190,6 +1190,11 @@ bool MipsTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {
return Subtarget.hasMips32();
}
+bool MipsTargetLowering::canUseConstantPoolForCTTZ() const {
+ // MIPS16 cannot use constant pools for CTTZ expansion.
+ return !Subtarget.inMips16Mode();
+}
+
bool MipsTargetLowering::hasBitTest(SDValue X, SDValue Y) const {
// We can use ANDI+SLTIU as a bit test. Y contains the bit position.
// For MIPSR2 or later, we may be able to use the `ext` instruction or its
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 806fb59f5ff3e..17fd4db0ba152 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -81,6 +81,7 @@ class TargetRegisterClass;
bool isCheapToSpeculateCttz(Type *Ty) const override;
bool isCheapToSpeculateCtlz(Type *Ty) const override;
+ bool canUseConstantPoolForCTTZ() const override;
bool hasBitTest(SDValue X, SDValue Y) const override;
bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override;
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)
|
RKSimon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we not just missing a legality check inside CTTZTableLookup? I'd really like to avoid yet another TLI hack.
arsenm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No new TLI hook
| /// Return true if constant pool can be used for CTTZ expansion. | ||
| virtual bool canUseConstantPoolForCTTZ() const { return true; } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make any sense and is too specific
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.
The fix adds a virtual method
canUseConstantPoolForCTTZ()to TargetLowering. MIPS16 overrides this to return false, using ISD::CTPOP.Fix #61055.