[llvm] ebc11b6 - [RISCV] Add separate lookup tables for fli.h and fli.d.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 12 11:37:04 PDT 2023


Author: Craig Topper
Date: 2023-03-12T11:28:49-07:00
New Revision: ebc11b68412cdcf2a0e6e2c50df262cfd9b8f481

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

LOG: [RISCV] Add separate lookup tables for fli.h and fli.d.

Use separate lookup tables instead of trying to reuse the fli.s
table.

We were missing the 2 denormal cases for fli.h. We also had an issue
where fli.d was only checking 8 bits of the 11 bit exponent.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
    llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
    llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
    llvm/test/CodeGen/RISCV/double-zfa.ll
    llvm/test/CodeGen/RISCV/half-zfa-fli.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 9698c992b3f10..783c5eb7630b7 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -496,7 +496,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
       return isUImm5();
     if (Kind != KindTy::FPImmediate)
       return false;
-    int Idx = RISCVLoadFPImm::getLoadFP64Imm(APInt(64, getFPConst()));
+    int Idx = RISCVLoadFPImm::getLoadFP64Imm(
+        APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
     // Don't allow decimal version of the minimum value. It is a 
diff erent value
     // for each supported data type.
     return Idx >= 0 && Idx != 1;
@@ -984,7 +985,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
       return;
     }
 
-    int Imm = RISCVLoadFPImm::getLoadFP64Imm(APInt(64, getFPConst()));
+    int Imm = RISCVLoadFPImm::getLoadFP64Imm(
+        APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
     Inst.addOperand(MCOperand::createImm(Imm));
   }
 

diff  --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
index 988fefe1449bd..335c9585a92b9 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
@@ -214,8 +214,22 @@ bool RISCVRVC::uncompress(MCInst &OutInst, const MCInst &MI,
   return uncompressInst(OutInst, MI, STI);
 }
 
-// We expect an 5-bit binary encoding of a floating-point constant here.
-static constexpr std::pair<uint8_t, uint8_t> LoadFPImmArr[] = {
+// Lookup table for fli.h for entries 1-31. Entry 0(-1.0) is handled separately.
+// NOTE: The exponent for entry 1 is larger than entry 2 and 3 because they
+// are denormals.
+static constexpr std::pair<uint8_t, uint8_t> LoadFP16ImmArr[] = {
+    {0b00001, 0b00}, {0b00000, 0b10}, {0b00000, 0b01}, {0b00111, 0b00},
+    {0b01000, 0b00}, {0b01011, 0b00}, {0b01100, 0b00}, {0b01101, 0b00},
+    {0b01101, 0b01}, {0b01101, 0b10}, {0b01101, 0b11}, {0b01110, 0b00},
+    {0b01110, 0b01}, {0b01110, 0b10}, {0b01110, 0b11}, {0b01111, 0b00},
+    {0b01111, 0b01}, {0b01111, 0b10}, {0b01111, 0b11}, {0b10000, 0b00},
+    {0b10000, 0b01}, {0b10000, 0b10}, {0b10001, 0b00}, {0b10010, 0b00},
+    {0b10011, 0b00}, {0b10110, 0b00}, {0b10111, 0b00}, {0b11110, 0b00},
+    {0b11111, 0b00}, {0b11111, 0b00}, {0b11111, 0b10},
+};
+
+// Lookup table for fli.s for entries 1-31.
+static constexpr std::pair<uint8_t, uint8_t> LoadFP32ImmArr[] = {
     {0b00000001, 0b00}, {0b01101111, 0b00}, {0b01110000, 0b00},
     {0b01110111, 0b00}, {0b01111000, 0b00}, {0b01111011, 0b00},
     {0b01111100, 0b00}, {0b01111101, 0b00}, {0b01111101, 0b01},
@@ -229,15 +243,104 @@ static constexpr std::pair<uint8_t, uint8_t> LoadFPImmArr[] = {
     {0b11111111, 0b10},
 };
 
-int RISCVLoadFPImm::getLoadFPImm(bool Sign, uint8_t Exp, uint8_t Mantissa) {
-  // Lookup in the table, ignoring the sign.
-  auto EMI = llvm::lower_bound(LoadFPImmArr, std::make_pair(Exp, Mantissa));
-  if (EMI == std::end(LoadFPImmArr) || EMI->first != Exp ||
+// Lookup table for fli.d for entries 1-31.
+static constexpr std::pair<uint16_t, uint8_t> LoadFP64ImmArr[] = {
+    {0b00000000001, 0b00}, {0b01111101111, 0b00}, {0b01111110000, 0b00},
+    {0b01111110111, 0b00}, {0b01111111000, 0b00}, {0b01111111011, 0b00},
+    {0b01111111100, 0b00}, {0b01111111101, 0b00}, {0b01111111101, 0b01},
+    {0b01111111101, 0b10}, {0b01111111101, 0b11}, {0b01111111110, 0b00},
+    {0b01111111110, 0b01}, {0b01111111110, 0b10}, {0b01111111110, 0b11},
+    {0b01111111111, 0b00}, {0b01111111111, 0b01}, {0b01111111111, 0b10},
+    {0b01111111111, 0b11}, {0b10000000000, 0b00}, {0b10000000000, 0b01},
+    {0b10000000000, 0b10}, {0b10000000001, 0b00}, {0b10000000010, 0b00},
+    {0b10000000011, 0b00}, {0b10000000110, 0b00}, {0b10000000111, 0b00},
+    {0b10000001110, 0b00}, {0b10000001111, 0b00}, {0b11111111111, 0b00},
+    {0b11111111111, 0b10},
+};
+
+int RISCVLoadFPImm::getLoadFP16Imm(const APFloat &FPImm) {
+  assert(&FPImm.getSemantics() == &APFloat::IEEEhalf());
+
+  APInt Imm = FPImm.bitcastToAPInt();
+
+  if (Imm.extractBitsAsZExtValue(8, 0) != 0)
+    return -1;
+
+  bool Sign = Imm.extractBitsAsZExtValue(1, 15);
+  uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 8);
+  uint8_t Exp = Imm.extractBitsAsZExtValue(5, 10);
+
+  // The array isn't sorted so we must use std::find unlike fp32 and fp64.
+  auto EMI = llvm::find(LoadFP16ImmArr, std::make_pair(Exp, Mantissa));
+  if (EMI == std::end(LoadFP16ImmArr))
+    return -1;
+
+  // Table doesn't have entry 0.
+  int Entry = std::distance(std::begin(LoadFP16ImmArr), EMI) + 1;
+
+  // The only legal negative value is -1.0(entry 0). 1.0 is entry 16.
+  if (Sign) {
+    if (Entry == 16)
+      return 0;
+    return false;
+  }
+
+  // Entry 29 and 30 are both infinity, but 30 is the real infinity.
+  if (Entry == 29)
+    ++Entry;
+
+  return Entry;
+}
+
+int RISCVLoadFPImm::getLoadFP32Imm(const APFloat &FPImm) {
+  assert(&FPImm.getSemantics() == &APFloat::IEEEsingle());
+
+  APInt Imm = FPImm.bitcastToAPInt();
+
+  if (Imm.extractBitsAsZExtValue(21, 0) != 0)
+    return -1;
+
+  bool Sign = Imm.extractBitsAsZExtValue(1, 31);
+  uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 21);
+  uint8_t Exp = Imm.extractBitsAsZExtValue(8, 23);
+
+  auto EMI = llvm::lower_bound(LoadFP32ImmArr, std::make_pair(Exp, Mantissa));
+  if (EMI == std::end(LoadFP32ImmArr) || EMI->first != Exp ||
+      EMI->second != Mantissa)
+    return -1;
+
+  // Table doesn't have entry 0.
+  int Entry = std::distance(std::begin(LoadFP32ImmArr), EMI) + 1;
+
+  // The only legal negative value is -1.0(entry 0). 1.0 is entry 16.
+  if (Sign) {
+    if (Entry == 16)
+      return 0;
+    return false;
+  }
+
+  return Entry;
+}
+
+int RISCVLoadFPImm::getLoadFP64Imm(const APFloat &FPImm) {
+  assert(&FPImm.getSemantics() == &APFloat::IEEEdouble());
+
+  APInt Imm = FPImm.bitcastToAPInt();
+
+  if (Imm.extractBitsAsZExtValue(50, 0) != 0)
+    return -1;
+
+  bool Sign = Imm.extractBitsAsZExtValue(1, 63);
+  uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 50);
+  uint16_t Exp = Imm.extractBitsAsZExtValue(11, 52);
+
+  auto EMI = llvm::lower_bound(LoadFP64ImmArr, std::make_pair(Exp, Mantissa));
+  if (EMI == std::end(LoadFP64ImmArr) || EMI->first != Exp ||
       EMI->second != Mantissa)
     return -1;
 
   // Table doesn't have entry 0.
-  int Entry = std::distance(std::begin(LoadFPImmArr), EMI) + 1;
+  int Entry = std::distance(std::begin(LoadFP64ImmArr), EMI) + 1;
 
   // The only legal negative value is -1.0(entry 0). 1.0 is entry 16.
   if (Sign) {
@@ -259,8 +362,8 @@ float RISCVLoadFPImm::getFPImm(unsigned Imm) {
     Imm = 16;
   }
 
-  uint32_t Exp = LoadFPImmArr[Imm - 1].first;
-  uint32_t Mantissa = LoadFPImmArr[Imm - 1].second;
+  uint32_t Exp = LoadFP32ImmArr[Imm - 1].first;
+  uint32_t Mantissa = LoadFP32ImmArr[Imm - 1].second;
 
   uint32_t I = Sign << 31 | Exp << 23 | Mantissa << 21;
   return bit_cast<float>(I);

diff  --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 9b684a35418d6..091a080317a09 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -353,67 +353,17 @@ float getFPImm(unsigned Imm);
 /// getLoadFP32Imm - Return a 5-bit binary encoding of the 32-bit
 /// floating-point immediate value. If the value cannot be represented as a
 /// 5-bit binary encoding, then return -1.
-static inline int getLoadFP32Imm(const APInt &Imm) {
-  if (Imm.extractBitsAsZExtValue(21, 0) != 0)
-    return -1;
-
-  bool Sign = Imm.extractBitsAsZExtValue(1, 31);
-  uint8_t Exp = Imm.extractBitsAsZExtValue(8, 23);
-  uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 21);
-  return getLoadFPImm(Sign, Exp, Mantissa);
-}
-
-static inline int getLoadFP32Imm(const APFloat &FPImm) {
-  return getLoadFP32Imm(FPImm.bitcastToAPInt());
-}
+int getLoadFP32Imm(const APFloat &FPImm);
 
 /// getLoadFP64Imm - Return a 5-bit binary encoding of the 64-bit
 /// floating-point immediate value. If the value cannot be represented as a
 /// 5-bit binary encoding, then return -1.
-static inline int getLoadFP64Imm(const APInt &Imm) {
-  if (Imm.extractBitsAsZExtValue(50, 0) != 0)
-    return -1;
-
-  bool Sign = Imm.extractBitsAsZExtValue(1, 63);
-  uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 50);
-  uint8_t Exp;
-  if (Imm.extractBitsAsZExtValue(11, 52) == 1)
-    Exp = 0b00000001;
-  else if (Imm.extractBitsAsZExtValue(11, 52) == 2047)
-    Exp = 0b11111111;
-  else
-    Exp = Imm.extractBitsAsZExtValue(11, 52) - 1023 + 127;
-
-  return getLoadFPImm(Sign, Exp, Mantissa);
-}
-
-static inline int getLoadFP64Imm(const APFloat &FPImm) {
-  return getLoadFP64Imm(FPImm.bitcastToAPInt());
-}
+int getLoadFP64Imm(const APFloat &FPImm);
 
 /// getLoadFP16Imm - Return a 5-bit binary encoding of the 16-bit
 /// floating-point immediate value. If the value cannot be represented as a
 /// 5-bit binary encoding, then return -1.
-static inline int getLoadFP16Imm(const APInt &Imm) {
-  if (Imm.extractBitsAsZExtValue(8, 0) != 0)
-    return -1;
-
-  bool Sign = Imm.extractBitsAsZExtValue(1, 15);
-  uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 8);
-  uint8_t Exp;
-  if (Imm.extractBitsAsZExtValue(5, 10) == 1)
-    Exp = 0b00000001;
-  else if (Imm.extractBitsAsZExtValue(5, 10) == 31)
-    Exp = 0b11111111;
-  else
-    Exp = Imm.extractBitsAsZExtValue(5, 10) - 15 + 127;
-
-  return getLoadFPImm(Sign, Exp, Mantissa);
-}
-
-static inline int getLoadFP16Imm(const APFloat &FPImm) {
-  return getLoadFP16Imm(FPImm.bitcastToAPInt());
-}
+int getLoadFP16Imm(const APFloat &FPImm);
 } // namespace RISCVLoadFPImm
 
 namespace RISCVSysReg {

diff  --git a/llvm/test/CodeGen/RISCV/double-zfa.ll b/llvm/test/CodeGen/RISCV/double-zfa.ll
index 427c5b5c646b3..4b5b1f7c952d2 100644
--- a/llvm/test/CodeGen/RISCV/double-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/double-zfa.ll
@@ -78,11 +78,11 @@ define double @loadfpimm9() {
 }
 
 ; Negative test. This is 1 * 2^256.
-; FIXME: This should not use fli.d
 define double @loadfpimm10() {
 ; CHECK-LABEL: loadfpimm10:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    fli.d fa0, 2.0
+; CHECK-NEXT:    lui a0, %hi(.LCPI9_0)
+; CHECK-NEXT:    fld fa0, %lo(.LCPI9_0)(a0)
 ; CHECK-NEXT:    ret
   ret double 0x1000000000000000
 }

diff  --git a/llvm/test/CodeGen/RISCV/half-zfa-fli.ll b/llvm/test/CodeGen/RISCV/half-zfa-fli.ll
index 500c74cbd9118..7899fdb6c5ebc 100644
--- a/llvm/test/CodeGen/RISCV/half-zfa-fli.ll
+++ b/llvm/test/CodeGen/RISCV/half-zfa-fli.ll
@@ -136,12 +136,10 @@ define half @loadfpimm9() {
 }
 
 ; This is 1 * 2^-16
-; FIXME: this should use fli.h
 define half @loadfpimm10() {
 ; CHECK-LABEL: loadfpimm10:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    li a0, 256
-; CHECK-NEXT:    fmv.h.x fa0, a0
+; CHECK-NEXT:    fli.h fa0, 3.0517578125e-05
 ; CHECK-NEXT:    ret
 ;
 ; ZFHMIN-LABEL: loadfpimm10:
@@ -153,12 +151,10 @@ define half @loadfpimm10() {
 }
 
 ; This is 1 * 2^-15
-; FIXME: This should use fli.h
 define half @loadfpimm11() {
 ; CHECK-LABEL: loadfpimm11:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    li a0, 512
-; CHECK-NEXT:    fmv.h.x fa0, a0
+; CHECK-NEXT:    fli.h fa0, 1.52587890625e-05
 ; CHECK-NEXT:    ret
 ;
 ; ZFHMIN-LABEL: loadfpimm11:


        


More information about the llvm-commits mailing list