[clang] 6b5afda - [clang][Interp] Add ArrayElemPtr{,Pop} opcode

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 2 00:45:41 PST 2023


Author: Timm Bäder
Date: 2023-03-02T09:45:18+01:00
New Revision: 6b5afda61c4ad6890e62cb8572a13a538316d31c

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

LOG: [clang][Interp] Add ArrayElemPtr{,Pop} opcode

We usually access array elements in the same pattern, which uses
narrow(). Add an extra opcode for this. This saves us quite some
instructions and makes the bytecode easier to read.

Differential Revision: https://reviews.llvm.org/D140805

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/Interp.h
    clang/lib/AST/Interp/Opcodes.td

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 7b8253c6e193..1f5c4f6e1cd1 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -413,7 +413,7 @@ bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
   const Expr *Index = E->getIdx();
   PrimType IndexT = classifyPrim(Index->getType());
 
-  // Take pointer of LHS, add offset from RHS, narrow result.
+  // Take pointer of LHS, add offset from RHS.
   // What's left on the stack after this is a pointer.
   if (!this->visit(Base))
     return false;
@@ -421,10 +421,7 @@ bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
   if (!this->visit(Index))
     return false;
 
-  if (!this->emitAddOffset(IndexT, E))
-    return false;
-
-  if (!this->emitNarrowPtr(E))
+  if (!this->emitArrayElemPtrPop(IndexT, E))
     return false;
 
   if (DiscardResult)
@@ -1214,16 +1211,11 @@ bool ByteCodeExprGen<Emitter>::visitArrayInitializer(const Expr *Initializer) {
           return false;
       } else {
         // Advance the pointer currently on the stack to the given
-        // dimension and narrow().
-        if (!this->emitDupPtr(Init))
-          return false;
+        // dimension.
         if (!this->emitConstUint32(ElementIndex, Init))
           return false;
-        if (!this->emitAddOffsetUint32(Init))
+        if (!this->emitArrayElemPtrUint32(Init))
           return false;
-        if (!this->emitNarrowPtr(Init))
-          return false;
-
         if (!visitInitializer(Init))
           return false;
         if (!this->emitPopPtr(Init))
@@ -1249,31 +1241,22 @@ bool ByteCodeExprGen<Emitter>::visitArrayInitializer(const Expr *Initializer) {
     for (size_t I = 0; I != Size; ++I) {
       ArrayIndexScope<Emitter> IndexScope(this, I);
 
-      if (!this->emitDupPtr(SubExpr)) // LHS
-        return false;
-
       if (ElemT) {
         if (!this->visit(SubExpr))
           return false;
         if (!this->emitInitElem(*ElemT, I, Initializer))
           return false;
       } else {
-        // Narrow to our array element and recurse into visitInitializer()
+        // Get to our array element and recurse into visitInitializer()
         if (!this->emitConstUint64(I, SubExpr))
           return false;
-
-        if (!this->emitAddOffsetUint64(SubExpr))
-          return false;
-
-        if (!this->emitNarrowPtr(SubExpr))
+        if (!this->emitArrayElemPtrUint64(SubExpr))
           return false;
-
         if (!visitInitializer(SubExpr))
           return false;
+        if (!this->emitPopPtr(Initializer))
+          return false;
       }
-
-      if (!this->emitPopPtr(Initializer))
-        return false;
     }
     return true;
   } else if (const auto *IVIE = dyn_cast<ImplicitValueInitExpr>(Initializer)) {
@@ -1309,13 +1292,9 @@ bool ByteCodeExprGen<Emitter>::visitArrayInitializer(const Expr *Initializer) {
     // FIXME(perf): We're calling the constructor once per array element here,
     //   in the old intepreter we had a special-case for trivial constructors.
     for (size_t I = 0; I != NumElems; ++I) {
-      if (!this->emitDupPtr(Initializer))
-        return false;
       if (!this->emitConstUint64(I, Initializer))
         return false;
-      if (!this->emitAddOffsetUint64(Initializer))
-        return false;
-      if (!this->emitNarrowPtr(Initializer))
+      if (!this->emitArrayElemPtrUint64(Initializer))
         return false;
 
       // Constructor arguments.

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index fbf74b54e330..98561f0a9ce0 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1455,6 +1455,36 @@ inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
+// 1) Pops an integral value from the stack
+// 2) Peeks a pointer
+// 3) Pushes a new pointer that's a narrowed array
+//   element of the peeked pointer with the value
+//   from 1) added as offset.
+//
+// This leaves the original pointer on the stack and pushes a new one
+// with the offset applied and narrowed.
+template <PrimType Name, class T = typename PrimConv<Name>::T>
+inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
+  const T &Offset = S.Stk.pop<T>();
+  const Pointer &Ptr = S.Stk.peek<Pointer>();
+
+  if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
+    return false;
+
+  return NarrowPtr(S, OpPC);
+}
+
+template <PrimType Name, class T = typename PrimConv<Name>::T>
+inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
+  const T &Offset = S.Stk.pop<T>();
+  const Pointer &Ptr = S.Stk.pop<Pointer>();
+
+  if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
+    return false;
+
+  return NarrowPtr(S, OpPC);
+}
+
 inline bool CheckGlobalCtor(InterpState &S, CodePtr &PC) {
   const Pointer &Obj = S.Stk.peek<Pointer>();
   return CheckCtorCall(S, PC, Obj);

diff  --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 1e325055c417..80d5c652d8dd 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -306,6 +306,9 @@ def RVOPtr : Opcode;
 def NarrowPtr : Opcode;
 // [Pointer] -> [Pointer]
 def ExpandPtr : Opcode;
+// [Pointer, Offset] -> [Pointer]
+def ArrayElemPtr : AluOpcode;
+def ArrayElemPtrPop : AluOpcode;
 
 //===----------------------------------------------------------------------===//
 // Direct field accessors


        


More information about the cfe-commits mailing list