From c0019bd8e58f498e3a4e7f5fcaf4b8fb72c2758a Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Fri, 4 May 2012 13:14:17 -0700 Subject: [PATCH] Cache type and lvalue type in IndexExpr and MemberExpr This saves a bunch of redundant work and unnecessary duplicated memory allocations. --- expr.cpp | 81 ++++++++++++++++++++++++++++++++++++-------------------- expr.h | 7 +++++ 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/expr.cpp b/expr.cpp index d7c7d04c..47111936 100644 --- a/expr.cpp +++ b/expr.cpp @@ -447,9 +447,10 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr, } return false; } - else - return lDoTypeConv(new ReferenceType(fromType), toType, NULL, - failureOk, errorMsgBase, pos); + else { + ReferenceType rt(fromType); + return lDoTypeConv(&rt, toType, NULL, failureOk, errorMsgBase, pos); + } } else if (Type::Equal(toType, fromType->GetAsNonConstType())) // convert: const T -> T (as long as T isn't a reference) @@ -3799,6 +3800,7 @@ IndexExpr::IndexExpr(Expr *a, Expr *i, SourcePos p) : Expr(p) { baseExpr = a; index = i; + type = lvalueType = NULL; } @@ -3939,7 +3941,7 @@ IndexExpr::GetValue(FunctionEmitContext *ctx) const { llvm::Value *ptr = GetLValue(ctx); llvm::Value *mask = NULL; - const Type *lvalueType = GetLValueType(); + const Type *lvType = GetLValueType(); if (ptr == NULL) { // We may be indexing into a temporary that hasn't hit memory, so // get the full value and stuff it into temporary alloca'd space so @@ -3958,12 +3960,12 @@ IndexExpr::GetValue(FunctionEmitContext *ctx) const { // Get a pointer type to the underlying elements const SequentialType *st = CastType(baseExprType); Assert(st != NULL); - lvalueType = PointerType::GetUniform(st->GetElementType()); + lvType = PointerType::GetUniform(st->GetElementType()); // And do the indexing calculation into the temporary array in memory ptr = ctx->GetElementPtrInst(tmpPtr, LLVMInt32(0), index->GetValue(ctx), PointerType::GetUniform(baseExprType)); - ptr = lAddVaryingOffsetsIfNeeded(ctx, ptr, lvalueType); + ptr = lAddVaryingOffsetsIfNeeded(ctx, ptr, lvType); mask = LLVMMaskAllOn; } @@ -3974,12 +3976,15 @@ IndexExpr::GetValue(FunctionEmitContext *ctx) const { } ctx->SetDebugPos(pos); - return ctx->LoadInst(ptr, mask, lvalueType); + return ctx->LoadInst(ptr, mask, lvType); } const Type * IndexExpr::GetType() const { + if (type != NULL) + return type; + const Type *baseExprType, *indexType; if (!baseExpr || !index || ((baseExprType = baseExpr->GetType()) == NULL) || @@ -4015,9 +4020,11 @@ IndexExpr::GetType() const { // type. if (indexType->IsUniformType() && (pointerType == NULL || pointerType->IsUniformType())) - return elementType; + type = elementType; else - return elementType->GetAsVaryingType(); + type = elementType->GetAsVaryingType(); + + return type; } @@ -4089,8 +4096,7 @@ lCheckIndicesVersusBounds(const Type *baseExprType, Expr *index) { */ static llvm::Value * lConvertPtrToSliceIfNeeded(FunctionEmitContext *ctx, - llvm::Value *ptr, - const Type **type) { + llvm::Value *ptr, const Type **type) { Assert(*type != NULL); const PointerType *ptrType = CastType(*type); bool convertToSlice = (ptrType->GetBaseType()->IsSOAType() && @@ -4178,6 +4184,9 @@ IndexExpr::GetLValue(FunctionEmitContext *ctx) const { const Type * IndexExpr::GetLValueType() const { + if (lvalueType != NULL) + return lvalueType; + const Type *baseExprType, *baseExprLValueType, *indexType; if (baseExpr == NULL || index == NULL || ((baseExprType = baseExpr->GetType()) == NULL) || @@ -4215,19 +4224,18 @@ IndexExpr::GetLValueType() const { // The return type is uniform iff. the base is a uniform pointer / a // collection of uniform typed elements and the index is uniform. - const PointerType *retType; if (baseVarying == false && indexType->IsUniformType()) - retType = PointerType::GetUniform(elementType); + lvalueType = PointerType::GetUniform(elementType); else - retType = PointerType::GetVarying(elementType); + lvalueType = PointerType::GetVarying(elementType); // Finally, if we're indexing into an SOA type, then the resulting // pointer must (currently) be a slice pointer; we don't allow indexing // the soa-width-wide structs directly. if (elementType->IsSOAType()) - retType = retType->GetAsSlice(); + lvalueType = lvalueType->GetAsSlice(); - return retType; + return lvalueType; } @@ -4370,6 +4378,9 @@ StructMemberExpr::StructMemberExpr(Expr *e, const char *id, SourcePos p, const Type * StructMemberExpr::GetType() const { + if (type != NULL) + return type; + // It's a struct, and the result type is the element type, possibly // promoted to varying if the struct type / lvalue is varying. const Type *exprType, *lvalueType; @@ -4412,12 +4423,16 @@ StructMemberExpr::GetType() const { // result type must be the varying version of the element type. elementType = elementType->GetAsVaryingType(); - return elementType; + type = elementType; + return type; } const Type * StructMemberExpr::GetLValueType() const { + if (lvalueType != NULL) + return lvalueType; + if (expr == NULL) { Assert(m->errorCount > 0); return NULL; @@ -4446,7 +4461,8 @@ StructMemberExpr::GetLValueType() const { CastType(exprLValueType)->IsSlice()) ptrType = ptrType->GetAsFrozenSlice(); - return ptrType; + lvalueType = ptrType; + return lvalueType; } @@ -4548,25 +4564,28 @@ VectorMemberExpr::VectorMemberExpr(Expr *e, const char *id, SourcePos p, const Type * VectorMemberExpr::GetType() const { + if (type != NULL) + return type; + // For 1-element expressions, we have the base vector element // type. For n-element expressions, we have a shortvec type // with n > 1 elements. This can be changed when we get // type<1> -> type conversions. - const Type *type = (identifier.length() == 1) ? + type = (identifier.length() == 1) ? (const Type *)exprVectorType->GetElementType() : (const Type *)memberType; - const Type *lvalueType = GetLValueType(); - if (lvalueType != NULL) { - bool isSlice = (CastType(lvalueType) && - CastType(lvalueType)->IsSlice()); + const Type *lvType = GetLValueType(); + if (lvType != NULL) { + bool isSlice = (CastType(lvType) && + CastType(lvType)->IsSlice()); if (isSlice) { //CO Assert(type->IsSOAType()); - if (lvalueType->IsUniformType()) + if (lvType->IsUniformType()) type = type->GetAsUniformType(); } - if (lvalueType->IsVaryingType()) + if (lvType->IsVaryingType()) type = type->GetAsVaryingType(); } @@ -4586,6 +4605,9 @@ VectorMemberExpr::GetLValue(FunctionEmitContext* ctx) const { const Type * VectorMemberExpr::GetLValueType() const { + if (lvalueType != NULL) + return lvalueType; + if (identifier.length() == 1) { if (expr == NULL) { Assert(m->errorCount > 0); @@ -4608,7 +4630,7 @@ VectorMemberExpr::GetLValueType() const { // but a pointer to a float, etc. const Type *elementType = vt->GetElementType(); if (CastType(exprLValueType) != NULL) - return new ReferenceType(elementType); + lvalueType = new ReferenceType(elementType); else { const PointerType *ptrType = exprLValueType->IsUniformType() ? PointerType::GetUniform(elementType) : @@ -4617,11 +4639,11 @@ VectorMemberExpr::GetLValueType() const { if (CastType(exprLValueType) && CastType(exprLValueType)->IsSlice()) ptrType = ptrType->GetAsFrozenSlice(); - return ptrType; + lvalueType = ptrType; } } - else - return NULL; + + return lvalueType; } @@ -4775,6 +4797,7 @@ MemberExpr::MemberExpr(Expr *e, const char *id, SourcePos p, SourcePos idpos, expr = e; identifier = id; dereferenceExpr = derefLValue; + type = lvalueType = NULL; } diff --git a/expr.h b/expr.h index f7d112b9..d65bc8c3 100644 --- a/expr.h +++ b/expr.h @@ -284,6 +284,10 @@ public: int EstimateCost() const; Expr *baseExpr, *index; + +private: + mutable const Type *type; + mutable const PointerType *lvalueType; }; @@ -320,6 +324,9 @@ public: member is found. (i.e. this is true if the MemberExpr was a '->' operator, and is false if it was a '.' operator. */ bool dereferenceExpr; + +protected: + mutable const Type *type, *lvalueType; };