From: Timm Bäder Date: Sat, 31 Dec 2022 16:06:52 +0000 (+0100) Subject: [clang][Interp] Add ArrayElemPtr{,Pop} opcode X-Git-Tag: upstream/17.0.6~16079 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6b5afda61c4ad6890e62cb8572a13a538316d31c;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 7b8253c..1f5c4f6 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -413,7 +413,7 @@ bool ByteCodeExprGen::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::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::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::visitArrayInitializer(const Expr *Initializer) { for (size_t I = 0; I != Size; ++I) { ArrayIndexScope 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(Initializer)) { @@ -1309,13 +1292,9 @@ bool ByteCodeExprGen::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 fbf74b5..98561f0 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 ::T> +inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { + const T &Offset = S.Stk.pop(); + const Pointer &Ptr = S.Stk.peek(); + + if (!OffsetHelper(S, OpPC, Offset, Ptr)) + return false; + + return NarrowPtr(S, OpPC); +} + +template ::T> +inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { + const T &Offset = S.Stk.pop(); + const Pointer &Ptr = S.Stk.pop(); + + if (!OffsetHelper(S, OpPC, Offset, Ptr)) + return false; + + return NarrowPtr(S, OpPC); +} + inline bool CheckGlobalCtor(InterpState &S, CodePtr &PC) { const Pointer &Obj = S.Stk.peek(); return CheckCtorCall(S, PC, Obj); diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index 1e32505..80d5c652 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