Skip to content
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

[RISCV] Use templates to reduce duplicated code for assembler operand predicates. #133351

Merged
merged 1 commit into from
Mar 28, 2025

Conversation

topperc
Copy link
Collaborator

@topperc topperc commented Mar 28, 2025

We already had a template isUImm function. This patch adds isSImm, isShiftedUImm, and 2 helpers that take a predicate function to validate the immediate with.

I'm using a template for the predicate though we could probably use a std::function. That might reduce compiler code size if the predicate doesn't get inlined anyway.

… predicates.

We already had a template isUImm function. This patch adds isSImm,
isShiftedUImm, and 2 helpers that take a predicate function to
validate the immediate with.

I'm using a template for the predicate though we could probably
use a std::function. That might reduce compiler code size if the
predicate doesn't get inlined anyway.
@topperc topperc requested review from asb, lenary and wangpc-pp March 28, 2025 01:40
@topperc topperc changed the title [RISCV] Use templates to reduce duplicated code for assembler operand… [RISCV] Use templates to reduce duplicated code for assembler operand predicates. Mar 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 28, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Craig Topper (topperc)

Changes

We already had a template isUImm function. This patch adds isSImm, isShiftedUImm, and 2 helpers that take a predicate function to validate the immediate with.

I'm using a template for the predicate though we could probably use a std::function. That might reduce compiler code size if the predicate doesn't get inlined anyway.


Patch is 20.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133351.diff

1 Files Affected:

  • (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+105-327)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 02cb1b5c9a12b..61720b194a5e6 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -600,26 +600,17 @@ struct RISCVOperand final : public MCParsedAsmOperand {
 
   bool isCSRSystemRegister() const { return isSystemRegister(); }
 
-  bool isVTypeImm(unsigned N) const {
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    if (!isImm())
-      return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_None;
-  }
-
   // If the last operand of the vsetvli/vsetvli instruction is a constant
   // expression, KindTy is Immediate.
   bool isVTypeI10() const {
-    if (Kind == KindTy::Immediate)
-      return isVTypeImm(10);
-    return Kind == KindTy::VType;
+    if (Kind == KindTy::VType)
+      return true;
+    return isUImm<10>();
   }
   bool isVTypeI11() const {
-    if (Kind == KindTy::Immediate)
-      return isVTypeImm(11);
-    return Kind == KindTy::VType;
+    if (Kind == KindTy::VType)
+      return true;
+    return isUImm<11>();
   }
 
   /// Return true if the operand is a valid for the fence instruction e.g.
@@ -675,308 +666,179 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
   }
 
-  bool isUImmLog2XLen() const {
+  template <unsigned N> bool isUImm() const {
     int64_t Imm;
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
     if (!isImm())
       return false;
-    if (!evaluateConstantImm(getImm(), Imm, VK) || VK != RISCVMCExpr::VK_None)
-      return false;
-    return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_None;
   }
 
-  bool isUImmLog2XLenNonZero() const {
+  template <unsigned N, unsigned S> bool isUImmShifted() const {
     int64_t Imm;
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
     if (!isImm())
       return false;
-    if (!evaluateConstantImm(getImm(), Imm, VK) || VK != RISCVMCExpr::VK_None)
-      return false;
-    if (Imm == 0)
-      return false;
-    return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && isShiftedUInt<N, S>(Imm) &&
+           VK == RISCVMCExpr::VK_None;
   }
 
-  bool isUImmLog2XLenHalf() const {
+  template <class Pred> bool isUImmPred(Pred p) const {
     int64_t Imm;
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
     if (!isImm())
       return false;
-    if (!evaluateConstantImm(getImm(), Imm, VK) || VK != RISCVMCExpr::VK_None)
-      return false;
-    return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && p(Imm) && VK == RISCVMCExpr::VK_None;
   }
 
-  template <unsigned N> bool IsUImm() const {
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    if (!isImm())
-      return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_None;
+  bool isUImmLog2XLen() const {
+    if (isImm() && isRV64Imm())
+      return isUImm<6>();
+    return isUImm<5>();
   }
 
-  bool isUImm1() const { return IsUImm<1>(); }
-  bool isUImm2() const { return IsUImm<2>(); }
-  bool isUImm3() const { return IsUImm<3>(); }
-  bool isUImm4() const { return IsUImm<4>(); }
-  bool isUImm5() const { return IsUImm<5>(); }
-  bool isUImm6() const { return IsUImm<6>(); }
-  bool isUImm7() const { return IsUImm<7>(); }
-  bool isUImm8() const { return IsUImm<8>(); }
-  bool isUImm10() const { return IsUImm<10>(); }
-  bool isUImm11() const { return IsUImm<11>(); }
-  bool isUImm16() const { return IsUImm<16>(); }
-  bool isUImm20() const { return IsUImm<20>(); }
-  bool isUImm32() const { return IsUImm<32>(); }
-  bool isUImm48() const { return IsUImm<48>(); }
-  bool isUImm64() const { return IsUImm<64>(); }
+  bool isUImmLog2XLenNonZero() const {
+    if (isImm() && isRV64Imm())
+      return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<6>(Imm); });
+    return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });
+  }
+
+  bool isUImmLog2XLenHalf() const {
+    if (isImm() && isRV64Imm())
+      return isUImm<5>();
+    return isUImm<4>();
+  }
+
+  bool isUImm1() const { return isUImm<1>(); }
+  bool isUImm2() const { return isUImm<2>(); }
+  bool isUImm3() const { return isUImm<3>(); }
+  bool isUImm4() const { return isUImm<4>(); }
+  bool isUImm5() const { return isUImm<5>(); }
+  bool isUImm6() const { return isUImm<6>(); }
+  bool isUImm7() const { return isUImm<7>(); }
+  bool isUImm8() const { return isUImm<8>(); }
+  bool isUImm10() const { return isUImm<10>(); }
+  bool isUImm11() const { return isUImm<11>(); }
+  bool isUImm16() const { return isUImm<16>(); }
+  bool isUImm20() const { return isUImm<20>(); }
+  bool isUImm32() const { return isUImm<32>(); }
+  bool isUImm48() const { return isUImm<48>(); }
+  bool isUImm64() const { return isUImm<64>(); }
 
   bool isUImm5NonZero() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });
   }
 
   bool isUImm5GT3() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isUInt<5>(Imm) && (Imm > 3) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred([](int64_t Imm) { return isUInt<5>(Imm) && Imm > 3; });
   }
 
   bool isUImm5Plus1() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && ((isUInt<5>(Imm) && (Imm != 0)) || (Imm == 32)) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred(
+        [](int64_t Imm) { return Imm > 0 && isUInt<5>(Imm - 1); });
   }
 
   bool isUImm5GE6Plus1() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && ((isUInt<5>(Imm) && (Imm >= 6)) || (Imm == 32)) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred(
+        [](int64_t Imm) { return Imm >= 6 && isUInt<5>(Imm - 1); });
   }
 
   bool isUImm5Slist() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm &&
-           ((Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
-            (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31)) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred([](int64_t Imm) {
+      return (Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
+             (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31);
+    });
   }
 
   bool isUImm8GE32() const {
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    if (!isImm())
-      return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred([](int64_t Imm) { return isUInt<8>(Imm) && Imm >= 32; });
   }
 
   bool isRnumArg() const {
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    if (!isImm())
-      return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred(
+        [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(10); });
   }
 
   bool isRnumArg_0_7() const {
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    if (!isImm())
-      return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(7) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred(
+        [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(7); });
   }
 
   bool isRnumArg_1_10() const {
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    if (!isImm())
-      return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && Imm >= INT64_C(1) && Imm <= INT64_C(10) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred(
+        [](int64_t Imm) { return Imm >= INT64_C(1) && Imm <= INT64_C(10); });
   }
 
   bool isRnumArg_2_14() const {
+    return isUImmPred(
+        [](int64_t Imm) { return Imm >= INT64_C(2) && Imm <= INT64_C(14); });
+  }
+
+  template <unsigned N> bool isSImm() const {
     int64_t Imm;
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
     if (!isImm())
       return false;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && Imm >= INT64_C(2) && Imm <= INT64_C(14) &&
+    return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Imm())) &&
            VK == RISCVMCExpr::VK_None;
   }
 
-  bool isSImm5() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
+  template <class Pred> bool isSImmPred(Pred p) const {
     int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
-           VK == RISCVMCExpr::VK_None;
-  }
-
-  bool isSImm5NonZero() const {
+    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
     if (!isImm())
       return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && Imm != 0 &&
-           isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
+    return IsConstantImm && p(fixImmediateForRV32(Imm, isRV64Imm())) &&
            VK == RISCVMCExpr::VK_None;
   }
 
-  bool isSImm6() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
-           VK == RISCVMCExpr::VK_None;
+  bool isSImm5() const { return isSImm<5>(); }
+  bool isSImm6() const { return isSImm<6>(); }
+  bool isSImm11() const { return isSImm<11>(); }
+  bool isSImm20() const { return isSImm<20>(); }
+  bool isSImm26() const { return isSImm<26>(); }
+  bool isSImm32() const { return isSImm<32>(); }
+
+  bool isSImm5NonZero() const {
+    return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<5>(Imm); });
   }
 
   bool isSImm6NonZero() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && Imm != 0 &&
-           isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
-           VK == RISCVMCExpr::VK_None;
+    return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<6>(Imm); });
   }
 
   bool isCLUIImm() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && (Imm != 0) &&
-           (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred([](int64_t Imm) {
+      return (isUInt<5>(Imm) && Imm != 0) || (Imm >= 0xfffe0 && Imm <= 0xfffff);
+    });
   }
 
-  bool isUImm2Lsb0() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
-           VK == RISCVMCExpr::VK_None;
-  }
+  bool isUImm2Lsb0() const { return isUImmShifted<1, 1>(); }
 
-  bool isUImm5Lsb0() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<4, 1>(Imm) &&
-           VK == RISCVMCExpr::VK_None;
-  }
+  bool isUImm5Lsb0() const { return isUImmShifted<4, 1>(); }
 
-  bool isUImm6Lsb0() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<5, 1>(Imm) &&
-           VK == RISCVMCExpr::VK_None;
-  }
+  bool isUImm6Lsb0() const { return isUImmShifted<5, 1>(); }
 
-  bool isUImm7Lsb00() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
-           VK == RISCVMCExpr::VK_None;
-  }
+  bool isUImm7Lsb00() const { return isUImmShifted<5, 2>(); }
 
-  bool isUImm7Lsb000() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<4, 3>(Imm) &&
-           VK == RISCVMCExpr::VK_None;
-  }
+  bool isUImm7Lsb000() const { return isUImmShifted<4, 3>(); }
 
-  bool isUImm8Lsb00() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
-           VK == RISCVMCExpr::VK_None;
-  }
+  bool isUImm8Lsb00() const { return isUImmShifted<6, 2>(); }
 
-  bool isUImm8Lsb000() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
-           VK == RISCVMCExpr::VK_None;
-  }
+  bool isUImm8Lsb000() const { return isUImmShifted<5, 3>(); }
 
   bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
 
-  bool isUImm9Lsb000() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
-           VK == RISCVMCExpr::VK_None;
-  }
+  bool isUImm9Lsb000() const { return isUImmShifted<6, 3>(); }
 
   bool isUImm10Lsb00NonZero() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred(
+        [](int64_t Imm) { return isShiftedUInt<8, 2>(Imm) && (Imm != 0); });
   }
 
   // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
@@ -987,16 +849,6 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     return SignExtend64<32>(Imm);
   }
 
-  bool isSImm11() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isInt<11>(fixImmediateForRV32(Imm, isRV64Imm())) &&
-           VK == RISCVMCExpr::VK_None;
-  }
-
   bool isSImm12() const {
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
     int64_t Imm;
@@ -1019,48 +871,22 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
 
   bool isSImm12Lsb00000() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm &&
-           isShiftedInt<7, 5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
-           VK == RISCVMCExpr::VK_None;
+    return isSImmPred([](int64_t Imm) { return isShiftedInt<7, 5>(Imm); });
   }
 
   bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
 
   bool isSImm10Lsb0000NonZero() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && (Imm != 0) &&
-           isShiftedInt<6, 4>(fixImmediateForRV32(Imm, isRV64Imm())) &&
-           VK == RISCVMCExpr::VK_None;
+    return isSImmPred(
+        [](int64_t Imm) { return Imm != 0 && isShiftedInt<6, 4>(Imm); });
   }
 
   bool isSImm16NonZero() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && Imm != 0 &&
-           isInt<16>(fixImmediateForRV32(Imm, isRV64Imm())) &&
-           VK == RISCVMCExpr::VK_None;
+    return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<16>(Imm); });
   }
 
   bool isUImm16NonZero() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isUInt<16>(Imm) && (Imm != 0) &&
-           VK == RISCVMCExpr::VK_None;
+    return isUImmPred([](int64_t Imm) { return isUInt<16>(Imm) && Imm != 0; });
   }
 
   bool isUImm20LUI() const {
@@ -1107,64 +933,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
 
   bool isImmZero() const {
-    if (!isImm())
-      return false;
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_None;
+    return isUImmPred([](int64_t Imm) { return 0 == Imm; });
   }
 
   bool isSImm5Plus1() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm &&
-           isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
-           VK == RISCVMCExpr::VK_None;
-  }
-
-  bool isSImm20() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && (VK == RISCVMCExpr::VK_None) &&
-           isInt<20>(fixImmediateForRV32(Imm, isRV64Imm()));
-  }
-
-  bool isSImm26() const {
-    if (!isImm())
-      return false;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    int64_t Imm;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && (VK == RISCVMCExpr::VK_None) &&
-           isInt<26>(fixImmediateForRV32(Imm, isRV64Imm()));
-  }
-
-  bool isSImm32() const {
-    int64_t Imm;
-    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
-    if (!isImm())
-      return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isInt<32>(fixImmediateForRV32(Imm, isRV64Imm())) &&
-           VK == RISCVMCExpr::VK_None;
+    re...
[truncated]

bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_None;
bool isUImmLog2XLen() const {
if (isImm() && isRV64Imm())
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pulled the check of isRV64Imm() earlier so we can reuse isUImm

return IsConstantImm && ((isUInt<5>(Imm) && (Imm != 0)) || (Imm == 32)) &&
VK == RISCVMCExpr::VK_None;
return isUImmPred(
[](int64_t Imm) { return Imm > 0 && isUInt<5>(Imm - 1); });
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I modified the way the predicate is written but it should be equivalent. Checking Imm > 0 first also serves to avoid UB if Imm is INT64_MIN

return IsConstantImm && isInt<32>(fixImmediateForRV32(Imm, isRV64Imm())) &&
VK == RISCVMCExpr::VK_None;
return isSImmPred(
[](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(Imm - 1); });
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the INT64_MIN check to guard undefined behavior on the Imm-1. The code wasn't optimizable, but could fail if someone build llvm with UBSAN.

Copy link
Contributor

@wangpc-pp wangpc-pp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, nice cleanup!

Copy link
Member

@lenary lenary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been a bit overdue, thank you.

I have been having thoughts about how we deal with the Immedate or Symbol Expression variants, which I might attack as a follow-up.

@topperc topperc merged commit f7f479b into llvm:main Mar 28, 2025
13 checks passed
@topperc topperc deleted the pr/asm-predicate branch March 28, 2025 16:03
@asb
Copy link
Contributor

asb commented Mar 28, 2025

Very nice cleanup!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants