[llvm] [RISCV] Use default promotion for i32 CTLZ on RV64 with XTHeadBb. (PR #157994)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 10 22:28:30 PDT 2025


https://github.com/topperc created https://github.com/llvm/llvm-project/pull/157994

The existing isel pattern felt like it was emitting more instructions than an isel pattern probably should. We were also missing opportunities to fold the innermost instructions with surrounding instructions.

I tried to move the expansion to lowering, but we got a little too aggressive folding the (not (slli (not))) with other operations in some tests and created code with constants that are hard to materialize and missed using TH_FF0. We could probably have fixed that with a RISCVISD::TH_FF0 node.

While investigating, I tried using the default promotion. The results aren't obviously worse than the previous codegen. And in some case they are obviously better.

>From 6c0ff9e083d1129d70182c24ce6bc1f3f6bbf86d Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 10 Sep 2025 15:56:45 -0700
Subject: [PATCH] [RISCV] Use default promotion for i32 CTLZ on RV64 with
 XTHeadBb.

The existing isel pattern felt like it was emitting more
instructions than an isel pattern probably should. We were also
missing opportunities to fold the innermost instructions with
surrounding instructions.

I tried to move the expansion to lowering, but we got a little
too aggressive folding the (not (slli (not))) with other
operations in some tests and created code with constants that
are hard to materialize and missed using TH_FF0. We could
probably have fixed that with a RISCVISD::TH_FF0 node.

While investigating, I tried using the default promotion. The
results aren't obviously worse than the previous codegen. And in
some case they are obviously better.
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  9 +++----
 llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td |  2 --
 llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll    |  6 ++---
 llvm/test/CodeGen/RISCV/rv64xtheadbb.ll       | 25 ++++++++-----------
 4 files changed, 17 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index ae9e2fef88673..1a7402aa3ed20 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -421,12 +421,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
       (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit())) {
     // We need the custom lowering to make sure that the resulting sequence
     // for the 32bit case is efficient on 64bit targets.
-    if (Subtarget.is64Bit()) {
-      setOperationAction(ISD::CTLZ, MVT::i32, Custom);
-      // Use default promotion for XTHeadBb.
-      if (Subtarget.hasStdExtZbb())
-        setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Custom);
-    }
+    // Use default promotion for i32 without Zbb.
+    if (Subtarget.is64Bit() && Subtarget.hasStdExtZbb())
+      setOperationAction({ISD::CTLZ, ISD::CTLZ_ZERO_UNDEF}, MVT::i32, Custom);
   } else {
     setOperationAction(ISD::CTLZ, XLenVT, Expand);
   }
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
index 4c31ce43c2e5e..49c9bdd83d3f6 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
@@ -594,8 +594,6 @@ def : Pat<(i64 (sra (bswap GPR:$rs1), (i64 32))),
           (TH_REVW GPR:$rs1)>;
 def : Pat<(binop_allwusers<srl> (bswap GPR:$rs1), (i64 32)),
           (TH_REVW GPR:$rs1)>;
-def : Pat<(riscv_clzw GPR:$rs1),
-          (TH_FF0 (i64 (SLLI (i64 (XORI GPR:$rs1, -1)), 32)))>;
 } // Predicates = [HasVendorXTHeadBb, IsRV64]
 
 let Predicates = [HasVendorXTHeadBs] in {
diff --git a/llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll b/llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll
index 99ed0a355b909..e6b22b2b9deea 100644
--- a/llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll
+++ b/llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll
@@ -1375,9 +1375,9 @@ define i32 @test_ctlz_i32(i32 %a) nounwind {
 ;
 ; RV64XTHEADBB-LABEL: test_ctlz_i32:
 ; RV64XTHEADBB:       # %bb.0:
-; RV64XTHEADBB-NEXT:    not a0, a0
-; RV64XTHEADBB-NEXT:    slli a0, a0, 32
-; RV64XTHEADBB-NEXT:    th.ff0 a0, a0
+; RV64XTHEADBB-NEXT:    th.extu a0, a0, 31, 0
+; RV64XTHEADBB-NEXT:    th.ff1 a0, a0
+; RV64XTHEADBB-NEXT:    addi a0, a0, -32
 ; RV64XTHEADBB-NEXT:    ret
   %tmp = call i32 @llvm.ctlz.i32(i32 %a, i1 false)
   ret i32 %tmp
diff --git a/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll b/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll
index f20ebca314b35..c5707987408f7 100644
--- a/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll
@@ -52,9 +52,9 @@ define signext i32 @ctlz_i32(i32 signext %a) nounwind {
 ;
 ; RV64XTHEADBB-NOB-LABEL: ctlz_i32:
 ; RV64XTHEADBB-NOB:       # %bb.0:
-; RV64XTHEADBB-NOB-NEXT:    not a0, a0
-; RV64XTHEADBB-NOB-NEXT:    slli a0, a0, 32
-; RV64XTHEADBB-NOB-NEXT:    th.ff0 a0, a0
+; RV64XTHEADBB-NOB-NEXT:    th.extu a0, a0, 31, 0
+; RV64XTHEADBB-NOB-NEXT:    th.ff1 a0, a0
+; RV64XTHEADBB-NOB-NEXT:    addi a0, a0, -32
 ; RV64XTHEADBB-NOB-NEXT:    ret
 ;
 ; RV64XTHEADBB-B-LABEL: ctlz_i32:
@@ -112,10 +112,9 @@ define signext i32 @log2_i32(i32 signext %a) nounwind {
 ;
 ; RV64XTHEADBB-NOB-LABEL: log2_i32:
 ; RV64XTHEADBB-NOB:       # %bb.0:
-; RV64XTHEADBB-NOB-NEXT:    not a0, a0
-; RV64XTHEADBB-NOB-NEXT:    slli a0, a0, 32
-; RV64XTHEADBB-NOB-NEXT:    th.ff0 a0, a0
-; RV64XTHEADBB-NOB-NEXT:    li a1, 31
+; RV64XTHEADBB-NOB-NEXT:    th.extu a0, a0, 31, 0
+; RV64XTHEADBB-NOB-NEXT:    th.ff1 a0, a0
+; RV64XTHEADBB-NOB-NEXT:    li a1, 63
 ; RV64XTHEADBB-NOB-NEXT:    sub a0, a1, a0
 ; RV64XTHEADBB-NOB-NEXT:    ret
 ;
@@ -177,10 +176,9 @@ define signext i32 @log2_ceil_i32(i32 signext %a) nounwind {
 ; RV64XTHEADBB-NOB-LABEL: log2_ceil_i32:
 ; RV64XTHEADBB-NOB:       # %bb.0:
 ; RV64XTHEADBB-NOB-NEXT:    addi a0, a0, -1
-; RV64XTHEADBB-NOB-NEXT:    not a0, a0
-; RV64XTHEADBB-NOB-NEXT:    slli a0, a0, 32
-; RV64XTHEADBB-NOB-NEXT:    th.ff0 a0, a0
-; RV64XTHEADBB-NOB-NEXT:    li a1, 32
+; RV64XTHEADBB-NOB-NEXT:    th.extu a0, a0, 31, 0
+; RV64XTHEADBB-NOB-NEXT:    th.ff1 a0, a0
+; RV64XTHEADBB-NOB-NEXT:    li a1, 64
 ; RV64XTHEADBB-NOB-NEXT:    sub a0, a1, a0
 ; RV64XTHEADBB-NOB-NEXT:    ret
 ;
@@ -309,9 +307,8 @@ define i32 @ctlz_lshr_i32(i32 signext %a) {
 ; RV64XTHEADBB-NOB-LABEL: ctlz_lshr_i32:
 ; RV64XTHEADBB-NOB:       # %bb.0:
 ; RV64XTHEADBB-NOB-NEXT:    srliw a0, a0, 1
-; RV64XTHEADBB-NOB-NEXT:    not a0, a0
-; RV64XTHEADBB-NOB-NEXT:    slli a0, a0, 32
-; RV64XTHEADBB-NOB-NEXT:    th.ff0 a0, a0
+; RV64XTHEADBB-NOB-NEXT:    th.ff1 a0, a0
+; RV64XTHEADBB-NOB-NEXT:    addi a0, a0, -32
 ; RV64XTHEADBB-NOB-NEXT:    ret
 ;
 ; RV64XTHEADBB-B-LABEL: ctlz_lshr_i32:



More information about the llvm-commits mailing list