[PATCH] D96317: [TableGen][SelectionDAG] Improve efficiency of encoding negative immediates for isel's CheckInteger opcode.

Craig Topper via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 8 21:52:07 PST 2021


craig.topper created this revision.
craig.topper added reviewers: RKSimon, Paul-C-Anagnostopoulos.
Herald added subscribers: ecnelises, hiraditya.
craig.topper requested review of this revision.
Herald added a project: LLVM.

CheckInteger uses an int64_t encoded using a variable width encoding
that is optimized for encoding a number with a lot of leading zeros.
Negative numbers have no leading zeros so use the largest encoding
requiring 9 bytes.

I believe its most like we want to check for positive and negative
numbers near 0. -1 is quite common due to its use in the 'not'
idiom.

To optimize for this, we can borrow an idea from the bitcode format
and move the sign bit to bit 0 with the magnitude stored in the
upper bits. This will drastically increase the number of leading
zeros for small magnitudes. Then we can run this value through
VBR encoding.

This gives a small reduction in the table size on all in tree
targets except VE where size increased by about 300 bytes due
to intrinsic ids now requiring 3 bytes instead of 2. Since the
intrinsic enum space is shared by all targets this an unfortunate
consquence of where VE is currently located in the range.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D96317

Files:
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
  llvm/test/TableGen/dag-isel-regclass-emit-enum.td
  llvm/test/TableGen/dag-isel-subregs.td
  llvm/utils/TableGen/DAGISelMatcherEmitter.cpp


Index: llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
===================================================================
--- llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -206,6 +206,18 @@
   return NumBytes+1;
 }
 
+/// Emit the specified signed value as a VBR. To improve compression we encode
+/// positive numbers shifted left by 1 and negative numbers negated and shifted
+/// left by 1 with bit 0 set.
+static unsigned EmitSignedVBRValue(uint64_t Val, raw_ostream &OS) {
+  if ((int64_t)Val >= 0)
+    Val = Val << 1;
+  else
+    Val = (-Val << 1) | 1;
+
+  return EmitVBRValue(Val, OS);
+}
+
 // This is expensive and slow.
 static std::string getIncludePath(const Record *R) {
   std::string str;
@@ -579,15 +591,16 @@
 
   case Matcher::CheckInteger: {
     OS << "OPC_CheckInteger, ";
-    unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
+    unsigned Bytes =
+        1 + EmitSignedVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
     OS << '\n';
     return Bytes;
   }
   case Matcher::CheckChildInteger: {
     OS << "OPC_CheckChild" << cast<CheckChildIntegerMatcher>(N)->getChildNo()
        << "Integer, ";
-    unsigned Bytes=1+EmitVBRValue(cast<CheckChildIntegerMatcher>(N)->getValue(),
-                                  OS);
+    unsigned Bytes = 1 + EmitSignedVBRValue(
+                             cast<CheckChildIntegerMatcher>(N)->getValue(), OS);
     OS << '\n';
     return Bytes;
   }
Index: llvm/test/TableGen/dag-isel-subregs.td
===================================================================
--- llvm/test/TableGen/dag-isel-subregs.td
+++ llvm/test/TableGen/dag-isel-subregs.td
@@ -8,7 +8,7 @@
 def : Pat<(v2i32 (extract_subvector v32i32:$src, (i32 0))),
           (EXTRACT_SUBREG GPR_1024:$src, sub0_sub1)>;
 
-// CHECK: OPC_CheckChild1Integer, 15,
+// CHECK: OPC_CheckChild1Integer, 30,
 // CHECK: OPC_EmitInteger, MVT::i32, 5|128,1/*133*/,
 def : Pat<(v2i32 (extract_subvector v32i32:$src, (i32 15))),
           (EXTRACT_SUBREG GPR_1024:$src, sub30_sub31)>;
Index: llvm/test/TableGen/dag-isel-regclass-emit-enum.td
===================================================================
--- llvm/test/TableGen/dag-isel-regclass-emit-enum.td
+++ llvm/test/TableGen/dag-isel-regclass-emit-enum.td
@@ -31,7 +31,7 @@
 def : Pat<(i32 (add i32:$src, (i32 0))),
           (COPY_TO_REGCLASS GPRAbove127, GPR0:$src)>;
 
-// CHECK:      OPC_CheckChild1Integer, 1,
+// CHECK:      OPC_CheckChild1Integer, 2,
 // CHECK-NEXT: OPC_EmitInteger, MVT::i32, TestNamespace::GPR127RegClassID,
 // CHECK-NEXT: OPC_MorphNodeTo1, TARGET_VAL(TargetOpcode::COPY_TO_REGCLASS), 0,
 // CHECK-NEXT:     MVT::i32, 2/*#Ops*/, 1, 0,
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2579,6 +2579,17 @@
   return VT == MVT::iPTR && cast<VTSDNode>(N)->getVT() == TLI->getPointerTy(DL);
 }
 
+// Bit 0 stores the sign of the immediate. The upper bits contain the magnitude
+// shifted left by 1.
+static uint64_t decodeSignRotatedValue(uint64_t V) {
+  if ((V & 1) == 0)
+    return V >> 1;
+  if (V != 1)
+    return -(V >> 1);
+  // There is no such thing as -0 with integers.  "-0" really means MININT.
+  return 1ULL << 63;
+}
+
 LLVM_ATTRIBUTE_ALWAYS_INLINE static bool
 CheckInteger(const unsigned char *MatcherTable, unsigned &MatcherIndex,
              SDValue N) {
@@ -2586,6 +2597,8 @@
   if (Val & 128)
     Val = GetVBR(Val, MatcherTable, MatcherIndex);
 
+  Val = decodeSignRotatedValue(Val);
+
   ConstantSDNode *C = dyn_cast<ConstantSDNode>(N);
   return C && C->getSExtValue() == Val;
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D96317.322286.patch
Type: text/x-patch
Size: 3789 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210209/a3572d59/attachment.bin>


More information about the llvm-commits mailing list