[llvm] 5baf58b - [RISCV] Improve use of BSETI/BCLRI in constant materialization. (#91546)

via llvm-commits llvm-commits at lists.llvm.org
Wed May 8 21:53:19 PDT 2024


Author: Craig Topper
Date: 2024-05-08T21:53:15-07:00
New Revision: 5baf58b628a4488de3f1a6af7c0df180358ba5dc

URL: https://github.com/llvm/llvm-project/commit/5baf58b628a4488de3f1a6af7c0df180358ba5dc
DIFF: https://github.com/llvm/llvm-project/commit/5baf58b628a4488de3f1a6af7c0df180358ba5dc.diff

LOG: [RISCV] Improve use of BSETI/BCLRI in constant materialization. (#91546)

We failed to use BSETI when bit 31 was set and a few bits above bit 31
were set. We also failed to use multiple BSETI when the low 32 bits were
zero.

I've removed the special cases for constants 0x80000000-0xffffffff and
wrote a more generic algorithm for BSETI.

I've rewritten the BCLRI handling to be similar to the new BSETI
algorithm. This picks up cases where bit 31 is 0 and only a few high
bits are 0.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp
    llvm/test/CodeGen/RISCV/imm.ll
    llvm/test/CodeGen/RISCV/rv64-legal-i32/imm.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp
index c3bae152993ea..0a304d4cb7d90 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp
@@ -310,56 +310,45 @@ InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI) {
     }
   }
 
-  // Perform optimization with BCLRI/BSETI in the Zbs extension.
+  // Perform optimization with BSETI in the Zbs extension.
   if (Res.size() > 2 && STI.hasFeature(RISCV::FeatureStdExtZbs)) {
-    // 1. For values in range 0xffffffff 7fffffff ~ 0xffffffff 00000000,
-    //    call generateInstSeqImpl with Val|0x80000000 (which is expected be
-    //    an int32), then emit (BCLRI r, 31).
-    // 2. For values in range 0x80000000 ~ 0xffffffff, call generateInstSeqImpl
-    //    with Val&~0x80000000 (which is expected to be an int32), then
-    //    emit (BSETI r, 31).
-    int64_t NewVal;
-    unsigned Opc;
-    if (Val < 0) {
-      Opc = RISCV::BCLRI;
-      NewVal = Val | 0x80000000ll;
-    } else {
-      Opc = RISCV::BSETI;
-      NewVal = Val & ~0x80000000ll;
-    }
-    if (isInt<32>(NewVal)) {
-      RISCVMatInt::InstSeq TmpSeq;
-      generateInstSeqImpl(NewVal, STI, TmpSeq);
-      if ((TmpSeq.size() + 1) < Res.size()) {
-        TmpSeq.emplace_back(Opc, 31);
-        Res = TmpSeq;
-      }
+    // Create a simm32 value for LUI+ADDIW by forcing the upper 33 bits to zero.
+    // Xor that with original value to get which bits should be set by BSETI.
+    uint64_t Lo = Val & 0x7fffffff;
+    uint64_t Hi = Val ^ Lo;
+    assert(Hi != 0);
+    RISCVMatInt::InstSeq TmpSeq;
+
+    if (Lo != 0)
+      generateInstSeqImpl(Lo, STI, TmpSeq);
+
+    if (TmpSeq.size() + llvm::popcount(Hi) < Res.size()) {
+      do {
+        TmpSeq.emplace_back(RISCV::BSETI, llvm::countr_zero(Hi));
+        Hi &= (Hi - 1); // Clear lowest set bit.
+      } while (Hi != 0);
+      Res = TmpSeq;
     }
+  }
+
+  // Perform optimization with BCLRI in the Zbs extension.
+  if (Res.size() > 2 && STI.hasFeature(RISCV::FeatureStdExtZbs)) {
+    // Create a simm32 value for LUI+ADDIW by forcing the upper 33 bits to one.
+    // Xor that with original value to get which bits should be cleared by
+    // BCLRI.
+    uint64_t Lo = Val | 0xffffffff80000000;
+    uint64_t Hi = Val ^ Lo;
+    assert(Hi != 0);
 
-    // Try to use BCLRI for upper 32 bits if the original lower 32 bits are
-    // negative int32, or use BSETI for upper 32 bits if the original lower
-    // 32 bits are positive int32.
-    int32_t Lo = Lo_32(Val);
-    uint32_t Hi = Hi_32(Val);
-    Opc = 0;
     RISCVMatInt::InstSeq TmpSeq;
     generateInstSeqImpl(Lo, STI, TmpSeq);
-    // Check if it is profitable to use BCLRI/BSETI.
-    if (Lo > 0 && TmpSeq.size() + llvm::popcount(Hi) < Res.size()) {
-      Opc = RISCV::BSETI;
-    } else if (Lo < 0 && TmpSeq.size() + llvm::popcount(~Hi) < Res.size()) {
-      Opc = RISCV::BCLRI;
-      Hi = ~Hi;
-    }
-    // Search for each bit and build corresponding BCLRI/BSETI.
-    if (Opc > 0) {
-      while (Hi != 0) {
-        unsigned Bit = llvm::countr_zero(Hi);
-        TmpSeq.emplace_back(Opc, Bit + 32);
+
+    if (TmpSeq.size() + llvm::popcount(Hi) < Res.size()) {
+      do {
+        TmpSeq.emplace_back(RISCV::BCLRI, llvm::countr_zero(Hi));
         Hi &= (Hi - 1); // Clear lowest set bit.
-      }
-      if (TmpSeq.size() < Res.size())
-        Res = TmpSeq;
+      } while (Hi != 0);
+      Res = TmpSeq;
     }
   }
 

diff  --git a/llvm/test/CodeGen/RISCV/imm.ll b/llvm/test/CodeGen/RISCV/imm.ll
index 0dc5c7ceb500c..c5c1657b526a6 100644
--- a/llvm/test/CodeGen/RISCV/imm.ll
+++ b/llvm/test/CodeGen/RISCV/imm.ll
@@ -4025,9 +4025,8 @@ define i64 @imm64_0x8000080000000() {
 ;
 ; RV64IZBS-LABEL: imm64_0x8000080000000:
 ; RV64IZBS:       # %bb.0:
-; RV64IZBS-NEXT:    lui a0, 256
-; RV64IZBS-NEXT:    addiw a0, a0, 1
-; RV64IZBS-NEXT:    slli a0, a0, 31
+; RV64IZBS-NEXT:    bseti a0, zero, 31
+; RV64IZBS-NEXT:    bseti a0, a0, 51
 ; RV64IZBS-NEXT:    ret
 ;
 ; RV64IXTHEADBB-LABEL: imm64_0x8000080000000:
@@ -4083,9 +4082,8 @@ define i64 @imm64_0x10000100000000() {
 ;
 ; RV64IZBS-LABEL: imm64_0x10000100000000:
 ; RV64IZBS:       # %bb.0:
-; RV64IZBS-NEXT:    lui a0, 256
-; RV64IZBS-NEXT:    addi a0, a0, 1
-; RV64IZBS-NEXT:    slli a0, a0, 32
+; RV64IZBS-NEXT:    bseti a0, zero, 32
+; RV64IZBS-NEXT:    bseti a0, a0, 52
 ; RV64IZBS-NEXT:    ret
 ;
 ; RV64IXTHEADBB-LABEL: imm64_0x10000100000000:
@@ -4146,10 +4144,9 @@ define i64 @imm64_0xFF7FFFFF7FFFFFFE() {
 ;
 ; RV64IZBS-LABEL: imm64_0xFF7FFFFF7FFFFFFE:
 ; RV64IZBS:       # %bb.0:
-; RV64IZBS-NEXT:    lui a0, 1044480
-; RV64IZBS-NEXT:    addiw a0, a0, -1
-; RV64IZBS-NEXT:    slli a0, a0, 31
-; RV64IZBS-NEXT:    addi a0, a0, -1
+; RV64IZBS-NEXT:    li a0, -1
+; RV64IZBS-NEXT:    bclri a0, a0, 31
+; RV64IZBS-NEXT:    bclri a0, a0, 55
 ; RV64IZBS-NEXT:    ret
 ;
 ; RV64IXTHEADBB-LABEL: imm64_0xFF7FFFFF7FFFFFFE:

diff  --git a/llvm/test/CodeGen/RISCV/rv64-legal-i32/imm.ll b/llvm/test/CodeGen/RISCV/rv64-legal-i32/imm.ll
index bac4bb9ce6f1a..561686374a9b9 100644
--- a/llvm/test/CodeGen/RISCV/rv64-legal-i32/imm.ll
+++ b/llvm/test/CodeGen/RISCV/rv64-legal-i32/imm.ll
@@ -2648,9 +2648,8 @@ define i64 @imm64_0x8000080000000() {
 ;
 ; RV64IZBS-LABEL: imm64_0x8000080000000:
 ; RV64IZBS:       # %bb.0:
-; RV64IZBS-NEXT:    lui a0, 256
-; RV64IZBS-NEXT:    addiw a0, a0, 1
-; RV64IZBS-NEXT:    slli a0, a0, 31
+; RV64IZBS-NEXT:    bseti a0, zero, 31
+; RV64IZBS-NEXT:    bseti a0, a0, 51
 ; RV64IZBS-NEXT:    ret
 ;
 ; RV64IXTHEADBB-LABEL: imm64_0x8000080000000:
@@ -2686,9 +2685,8 @@ define i64 @imm64_0x10000100000000() {
 ;
 ; RV64IZBS-LABEL: imm64_0x10000100000000:
 ; RV64IZBS:       # %bb.0:
-; RV64IZBS-NEXT:    lui a0, 256
-; RV64IZBS-NEXT:    addi a0, a0, 1
-; RV64IZBS-NEXT:    slli a0, a0, 32
+; RV64IZBS-NEXT:    bseti a0, zero, 32
+; RV64IZBS-NEXT:    bseti a0, a0, 52
 ; RV64IZBS-NEXT:    ret
 ;
 ; RV64IXTHEADBB-LABEL: imm64_0x10000100000000:
@@ -2727,10 +2725,9 @@ define i64 @imm64_0xFF7FFFFF7FFFFFFE() {
 ;
 ; RV64IZBS-LABEL: imm64_0xFF7FFFFF7FFFFFFE:
 ; RV64IZBS:       # %bb.0:
-; RV64IZBS-NEXT:    lui a0, 1044480
-; RV64IZBS-NEXT:    addiw a0, a0, -1
-; RV64IZBS-NEXT:    slli a0, a0, 31
-; RV64IZBS-NEXT:    addi a0, a0, -1
+; RV64IZBS-NEXT:    li a0, -1
+; RV64IZBS-NEXT:    bclri a0, a0, 31
+; RV64IZBS-NEXT:    bclri a0, a0, 55
 ; RV64IZBS-NEXT:    ret
 ;
 ; RV64IXTHEADBB-LABEL: imm64_0xFF7FFFFF7FFFFFFE:


        


More information about the llvm-commits mailing list