tbaeder created this revision. tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik. Herald added a project: All. tbaeder requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D140805 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td
Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -300,6 +300,9 @@ def NarrowPtr : Opcode; // [Pointer] -> [Pointer] def ExpandPtr : Opcode; +// [Pointer, Offset] -> [Pointer] +def ArrayElemPtr : AluOpcode; +def ArrayElemPtrPop : AluOpcode; //===----------------------------------------------------------------------===// // Direct field accessors Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1369,6 +1369,36 @@ 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); Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -365,7 +365,7 @@ 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; @@ -373,10 +373,7 @@ 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) @@ -1115,16 +1112,11 @@ 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)) @@ -1150,31 +1142,22 @@ 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)) { @@ -1210,13 +1193,9 @@ // 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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits