From 564e61c8286c6c1963dc0cc598aa0ac80904a4eb Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Mon, 22 Jul 2013 16:12:02 -0700 Subject: [PATCH] Improvements to constant folding. We can now do constant folding with all basic datatypes (the previous implementation handled int32 well, but had limited, if any, coverage for other datatypes.) Reduced a bit of repeated code in the constant folding implementation through template helper functions. --- ast.cpp | 2 +- expr.cpp | 445 ++++++++++++++++-------------- expr.h | 81 ++---- module.cpp | 2 +- parse.yy | 2 +- tests_errors/const-too-large.ispc | 3 + type.cpp | 2 +- 7 files changed, 267 insertions(+), 270 deletions(-) create mode 100644 tests_errors/const-too-large.ispc diff --git a/ast.cpp b/ast.cpp index 3bd77e9b..83ee207d 100644 --- a/ast.cpp +++ b/ast.cpp @@ -446,7 +446,7 @@ lCheckAllOffSafety(ASTNode *node, void *data) { } int32_t indices[ISPC_MAX_NVEC]; - int count = ce->AsInt32(indices); + int count = ce->GetValues(indices); for (int i = 0; i < count; ++i) { if (indices[i] < 0 || indices[i] >= nElements) { // Index is out of bounds -> not safe diff --git a/expr.cpp b/expr.cpp index cdc845c0..fc3d295a 100644 --- a/expr.cpp +++ b/expr.cpp @@ -180,7 +180,7 @@ lIsAllIntZeros(Expr *expr) { return false; uint64_t vals[ISPC_MAX_NVEC]; - int count = ce->AsUInt64(vals); + int count = ce->GetValues(vals); if (count == 1) return (vals[0] == 0); else { @@ -1161,6 +1161,16 @@ UnaryExpr::GetType() const { } +template static Expr * +lOptimizeBitNot(ConstExpr *constExpr, const Type *type, SourcePos pos) { + T v[ISPC_MAX_NVEC]; + int count = constExpr->GetValues(v); + for (int i = 0; i < count; ++i) + v[i] = ~v[i]; + return new ConstExpr(type, v, pos); +} + + Expr * UnaryExpr::Optimize() { ConstExpr *constExpr = dynamic_cast(expr); @@ -1172,17 +1182,6 @@ UnaryExpr::Optimize() { const Type *type = constExpr->GetType(); bool isEnumType = CastType(type) != NULL; - const Type *baseType = type->GetAsNonConstType()->GetAsUniformType(); - if (Type::Equal(baseType, AtomicType::UniformInt8) || - Type::Equal(baseType, AtomicType::UniformUInt8) || - Type::Equal(baseType, AtomicType::UniformInt16) || - Type::Equal(baseType, AtomicType::UniformUInt16) || - Type::Equal(baseType, AtomicType::UniformInt64) || - Type::Equal(baseType, AtomicType::UniformUInt64)) - // FIXME: should handle these at some point; for now we only do - // constant folding for bool, int32 and float types... - return this; - switch (op) { case PreInc: case PreDec: @@ -1192,42 +1191,76 @@ UnaryExpr::Optimize() { // An error will be issued elsewhere... return this; case Negate: { - // Since we currently only handle int32, floats, and doubles here, - // it's safe to stuff whatever we have into a double, do the negate - // as a double, and then return a ConstExpr with the same type as - // the original... - double v[ISPC_MAX_NVEC]; - int count = constExpr->AsDouble(v); - for (int i = 0; i < count; ++i) - v[i] = -v[i]; - return new ConstExpr(constExpr, v); + if (Type::EqualIgnoringConst(type, AtomicType::UniformInt64) || + Type::EqualIgnoringConst(type, AtomicType::VaryingInt64)) { + int64_t v[ISPC_MAX_NVEC]; + int count = constExpr->GetValues(v); + for (int i = 0; i < count; ++i) + v[i] = -v[i]; + return new ConstExpr(type, v, pos); + } + else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt64) || + Type::EqualIgnoringConst(type, AtomicType::VaryingUInt64)) { + uint64_t v[ISPC_MAX_NVEC]; + int count = constExpr->GetValues(v); + for (int i = 0; i < count; ++i) + v[i] = -v[i]; + return new ConstExpr(type, v, pos); + } + else { + // For all the other types, it's safe to stuff whatever we have + // into a double, do the negate as a double, and then return a + // ConstExpr with the same type as the original... + double v[ISPC_MAX_NVEC]; + int count = constExpr->GetValues(v); + for (int i = 0; i < count; ++i) + v[i] = -v[i]; + return new ConstExpr(constExpr, v); + } } case BitNot: { - if (Type::EqualIgnoringConst(type, AtomicType::UniformInt32) || - Type::EqualIgnoringConst(type, AtomicType::VaryingInt32)) { - int32_t v[ISPC_MAX_NVEC]; - int count = constExpr->AsInt32(v); - for (int i = 0; i < count; ++i) - v[i] = ~v[i]; - return new ConstExpr(type, v, pos); + if (Type::EqualIgnoringConst(type, AtomicType::UniformInt8) || + Type::EqualIgnoringConst(type, AtomicType::VaryingInt8)) { + return lOptimizeBitNot(constExpr, type, pos); + } + else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt8) || + Type::EqualIgnoringConst(type, AtomicType::VaryingUInt8)) { + return lOptimizeBitNot(constExpr, type, pos); + } + else if (Type::EqualIgnoringConst(type, AtomicType::UniformInt16) || + Type::EqualIgnoringConst(type, AtomicType::VaryingInt16)) { + return lOptimizeBitNot(constExpr, type, pos); + } + else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt16) || + Type::EqualIgnoringConst(type, AtomicType::VaryingUInt16)) { + return lOptimizeBitNot(constExpr, type, pos); + } + else if (Type::EqualIgnoringConst(type, AtomicType::UniformInt32) || + Type::EqualIgnoringConst(type, AtomicType::VaryingInt32)) { + return lOptimizeBitNot(constExpr, type, pos); } else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt32) || Type::EqualIgnoringConst(type, AtomicType::VaryingUInt32) || isEnumType == true) { - uint32_t v[ISPC_MAX_NVEC]; - int count = constExpr->AsUInt32(v); - for (int i = 0; i < count; ++i) - v[i] = ~v[i]; - return new ConstExpr(type, v, pos); + return lOptimizeBitNot(constExpr, type, pos); + } + else if (Type::EqualIgnoringConst(type, AtomicType::UniformInt64) || + Type::EqualIgnoringConst(type, AtomicType::VaryingInt64)) { + return lOptimizeBitNot(constExpr, type, pos); + } + else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt64) || + Type::EqualIgnoringConst(type, AtomicType::VaryingUInt64) || + isEnumType == true) { + return lOptimizeBitNot(constExpr, type, pos); } else FATAL("unexpected type in UnaryExpr::Optimize() / BitNot case"); } case LogicalNot: { AssertPos(pos, Type::EqualIgnoringConst(type, AtomicType::UniformBool) || - Type::EqualIgnoringConst(type, AtomicType::VaryingBool)); + Type::EqualIgnoringConst(type, AtomicType::VaryingBool)); bool v[ISPC_MAX_NVEC]; - int count = constExpr->AsBool(v); + int count = constExpr->GetValues(v); for (int i = 0; i < count; ++i) v[i] = !v[i]; return new ConstExpr(type, v, pos); @@ -2016,25 +2049,37 @@ BinaryExpr::GetType() const { #define FOLD_OP(O, E) \ case O: \ - for (int i = 0; i < count; ++i) \ - result[i] = (v0[i] E v1[i]); \ - break + for (int i = 0; i < count; ++i) \ + result[i] = (v0[i] E v1[i]); \ + break + +#define FOLD_OP_REF(O, E, TRef) \ + case O: \ + for (int i = 0; i < count; ++i) { \ + result[i] = (v0[i] E v1[i]); \ + TRef r = (TRef)v0[i] E (TRef)v1[i]; \ + if (result[i] != r) \ + Warning(pos, "Binary expression with type \"%s\" can't represent value.", \ + carg0->GetType()->GetString().c_str()); \ + } \ + break /** Constant fold the binary integer operations that aren't also applicable to floating-point types. */ -template static ConstExpr * -lConstFoldBinIntOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0) { +template static ConstExpr * +lConstFoldBinaryIntOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0, + SourcePos pos) { T result[ISPC_MAX_NVEC]; int count = carg0->Count(); switch (op) { - FOLD_OP(BinaryExpr::Mod, %); - FOLD_OP(BinaryExpr::Shl, <<); - FOLD_OP(BinaryExpr::Shr, >>); - FOLD_OP(BinaryExpr::BitAnd, &); - FOLD_OP(BinaryExpr::BitXor, ^); - FOLD_OP(BinaryExpr::BitOr, |); + FOLD_OP_REF(BinaryExpr::Mod, %, TRef); + FOLD_OP_REF(BinaryExpr::Shl, <<, TRef); + FOLD_OP_REF(BinaryExpr::Shr, >>, TRef); + FOLD_OP_REF(BinaryExpr::BitAnd, &, TRef); + FOLD_OP_REF(BinaryExpr::BitXor, ^, TRef); + FOLD_OP_REF(BinaryExpr::BitOr, |, TRef); default: return NULL; } @@ -2046,7 +2091,8 @@ lConstFoldBinIntOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0 /** Constant fold the binary logical ops. */ template static ConstExpr * -lConstFoldBinLogicalOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0) { +lConstFoldBinaryLogicalOp(BinaryExpr::Op op, const T *v0, const T *v1, + ConstExpr *carg0) { bool result[ISPC_MAX_NVEC]; int count = carg0->Count(); @@ -2071,16 +2117,16 @@ lConstFoldBinLogicalOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *c /** Constant fold binary arithmetic ops. */ -template static ConstExpr * -lConstFoldBinArithOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0, - SourcePos pos) { +template static ConstExpr * +lConstFoldBinaryArithOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0, + SourcePos pos) { T result[ISPC_MAX_NVEC]; int count = carg0->Count(); switch (op) { - FOLD_OP(BinaryExpr::Add, +); - FOLD_OP(BinaryExpr::Sub, -); - FOLD_OP(BinaryExpr::Mul, *); + FOLD_OP_REF(BinaryExpr::Add, +, TRef); + FOLD_OP_REF(BinaryExpr::Sub, -, TRef); + FOLD_OP_REF(BinaryExpr::Mul, *, TRef); case BinaryExpr::Div: for (int i = 0; i < count; ++i) { if (v1[i] == 0) { @@ -2102,8 +2148,8 @@ lConstFoldBinArithOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *car /** Constant fold the various boolean binary ops. */ static ConstExpr * -lConstFoldBoolBinOp(BinaryExpr::Op op, const bool *v0, const bool *v1, - ConstExpr *carg0) { +lConstFoldBoolBinaryOp(BinaryExpr::Op op, const bool *v0, const bool *v1, + ConstExpr *carg0) { bool result[ISPC_MAX_NVEC]; int count = carg0->Count(); @@ -2127,6 +2173,40 @@ lConstFoldBoolBinOp(BinaryExpr::Op op, const bool *v0, const bool *v1, } +template static Expr * +lConstFoldBinaryFPOp(ConstExpr *constArg0, ConstExpr *constArg1, + BinaryExpr::Op op, BinaryExpr *origExpr, SourcePos pos) { + T v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; + constArg0->GetValues(v0); + constArg1->GetValues(v1); + ConstExpr *ret; + if ((ret = lConstFoldBinaryArithOp(op, v0, v1, constArg0, pos)) != NULL) + return ret; + else if ((ret = lConstFoldBinaryLogicalOp(op, v0, v1, constArg0)) != NULL) + return ret; + else + return origExpr; +} + + +template static Expr * +lConstFoldBinaryIntOp(ConstExpr *constArg0, ConstExpr *constArg1, + BinaryExpr::Op op, BinaryExpr *origExpr, SourcePos pos) { + T v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; + constArg0->GetValues(v0); + constArg1->GetValues(v1); + ConstExpr *ret; + if ((ret = lConstFoldBinaryArithOp(op, v0, v1, constArg0, pos)) != NULL) + return ret; + else if ((ret = lConstFoldBinaryIntOp(op, v0, v1, constArg0, pos)) != NULL) + return ret; + else if ((ret = lConstFoldBinaryLogicalOp(op, v0, v1, constArg0)) != NULL) + return ret; + else + return origExpr; +} + + Expr * BinaryExpr::Optimize() { if (arg0 == NULL || arg1 == NULL) @@ -2144,7 +2224,7 @@ BinaryExpr::Optimize() { if (Type::EqualIgnoringConst(type1, AtomicType::UniformFloat) || Type::EqualIgnoringConst(type1, AtomicType::VaryingFloat)) { float inv[ISPC_MAX_NVEC]; - int count = constArg1->AsFloat(inv); + int count = constArg1->GetValues(inv); for (int i = 0; i < count; ++i) inv[i] = 1.f / inv[i]; Expr *einv = new ConstExpr(type1, inv, constArg1->pos); @@ -2198,70 +2278,53 @@ BinaryExpr::Optimize() { const Type *type = arg0->GetType()->GetAsNonConstType(); if (Type::Equal(type, AtomicType::UniformFloat) || Type::Equal(type, AtomicType::VaryingFloat)) { - float v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; - constArg0->AsFloat(v0); - constArg1->AsFloat(v1); - ConstExpr *ret; - if ((ret = lConstFoldBinArithOp(op, v0, v1, constArg0, pos)) != NULL) - return ret; - else if ((ret = lConstFoldBinLogicalOp(op, v0, v1, constArg0)) != NULL) - return ret; - else - return this; + return lConstFoldBinaryFPOp(constArg0, constArg1, op, this, pos); } - if (Type::Equal(type, AtomicType::UniformDouble) || - Type::Equal(type, AtomicType::VaryingDouble)) { - double v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; - constArg0->AsDouble(v0); - constArg1->AsDouble(v1); - ConstExpr *ret; - if ((ret = lConstFoldBinArithOp(op, v0, v1, constArg0, pos)) != NULL) - return ret; - else if ((ret = lConstFoldBinLogicalOp(op, v0, v1, constArg0)) != NULL) - return ret; - else - return this; + else if (Type::Equal(type, AtomicType::UniformDouble) || + Type::Equal(type, AtomicType::VaryingDouble)) { + return lConstFoldBinaryFPOp(constArg0, constArg1, op, this, pos); } - if (Type::Equal(type, AtomicType::UniformInt32) || - Type::Equal(type, AtomicType::VaryingInt32)) { - int32_t v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; - constArg0->AsInt32(v0); - constArg1->AsInt32(v1); - ConstExpr *ret; - if ((ret = lConstFoldBinArithOp(op, v0, v1, constArg0, pos)) != NULL) - return ret; - else if ((ret = lConstFoldBinIntOp(op, v0, v1, constArg0)) != NULL) - return ret; - else if ((ret = lConstFoldBinLogicalOp(op, v0, v1, constArg0)) != NULL) - return ret; - else - return this; + else if (Type::Equal(type, AtomicType::UniformInt8) || + Type::Equal(type, AtomicType::VaryingInt8)) { + return lConstFoldBinaryIntOp(constArg0, constArg1, op, this, pos); + } + else if (Type::Equal(type, AtomicType::UniformUInt8) || + Type::Equal(type, AtomicType::VaryingUInt8)) { + return lConstFoldBinaryIntOp(constArg0, constArg1, op, this, pos); + } + else if (Type::Equal(type, AtomicType::UniformInt16) || + Type::Equal(type, AtomicType::VaryingInt16)) { + return lConstFoldBinaryIntOp(constArg0, constArg1, op, this, pos); + } + else if (Type::Equal(type, AtomicType::UniformUInt16) || + Type::Equal(type, AtomicType::VaryingUInt16)) { + return lConstFoldBinaryIntOp(constArg0, constArg1, op, this, pos); + } + else if (Type::Equal(type, AtomicType::UniformInt32) || + Type::Equal(type, AtomicType::VaryingInt32)) { + return lConstFoldBinaryIntOp(constArg0, constArg1, op, this, pos); } else if (Type::Equal(type, AtomicType::UniformUInt32) || - Type::Equal(type, AtomicType::VaryingUInt32) || - CastType(type) != NULL) { - uint32_t v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; - constArg0->AsUInt32(v0); - constArg1->AsUInt32(v1); - ConstExpr *ret; - if ((ret = lConstFoldBinArithOp(op, v0, v1, constArg0, pos)) != NULL) - return ret; - else if ((ret = lConstFoldBinIntOp(op, v0, v1, constArg0)) != NULL) - return ret; - else if ((ret = lConstFoldBinLogicalOp(op, v0, v1, constArg0)) != NULL) - return ret; - else - return this; + Type::Equal(type, AtomicType::VaryingUInt32)) { + return lConstFoldBinaryIntOp(constArg0, constArg1, op, this, pos); + } + else if (Type::Equal(type, AtomicType::UniformInt64) || + Type::Equal(type, AtomicType::VaryingInt64)) { + return lConstFoldBinaryIntOp(constArg0, constArg1, op, this, pos); + } + else if (Type::Equal(type, AtomicType::UniformUInt64) || + Type::Equal(type, AtomicType::VaryingUInt64)) { + return lConstFoldBinaryIntOp(constArg0, constArg1, op, this, pos); } else if (Type::Equal(type, AtomicType::UniformBool) || Type::Equal(type, AtomicType::VaryingBool)) { bool v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; - constArg0->AsBool(v0); - constArg1->AsBool(v1); + constArg0->GetValues(v0); + constArg1->GetValues(v1); ConstExpr *ret; - if ((ret = lConstFoldBoolBinOp(op, v0, v1, constArg0)) != NULL) + if ((ret = lConstFoldBoolBinaryOp(op, v0, v1, constArg0)) != NULL) return ret; - else if ((ret = lConstFoldBinLogicalOp(op, v0, v1, constArg0)) != NULL) + else if ((ret = lConstFoldBinaryLogicalOp(op, v0, v1, constArg0)) != NULL) return ret; else return this; @@ -3159,6 +3222,19 @@ SelectExpr::GetType() const { } +template Expr * +lConstFoldSelect(const bool bv[], ConstExpr *constExpr1, ConstExpr *constExpr2, + const Type *exprType, SourcePos pos) { + T v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; + T result[ISPC_MAX_NVEC]; + int count = constExpr1->GetValues(v1); + constExpr2->GetValues(v2); + for (int i = 0; i < count; ++i) + result[i] = bv[i] ? v1[i] : v2[i]; + return new ConstExpr(exprType, result, pos); +} + + Expr * SelectExpr::Optimize() { if (test == NULL || expr1 == NULL || expr2 == NULL) @@ -3171,7 +3247,7 @@ SelectExpr::Optimize() { // The test is a constant; see if we can resolve to one of the // expressions.. bool bv[ISPC_MAX_NVEC]; - int count = constTest->AsBool(bv); + int count = constTest->GetValues(bv); if (count == 1) // Uniform test value; return the corresponding expression return (bv[0] == true) ? expr1 : expr2; @@ -3200,71 +3276,38 @@ SelectExpr::Optimize() { const Type *exprType = constExpr1->GetType()->GetAsNonConstType(); AssertPos(pos, exprType->IsVaryingType()); - // FIXME: it's annoying to have to have all of this replicated code. - // FIXME: for completeness, it would also be nice to handle 8 and - // 16 bit types... - if (Type::Equal(exprType, AtomicType::VaryingInt32)) { - int32_t v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; - int32_t result[ISPC_MAX_NVEC]; - constExpr1->AsInt32(v1); - constExpr2->AsInt32(v2); - for (int i = 0; i < count; ++i) - result[i] = bv[i] ? v1[i] : v2[i]; - return new ConstExpr(exprType, result, pos); + if (Type::Equal(exprType, AtomicType::VaryingInt8)) { + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); } - if (Type::Equal(exprType, AtomicType::VaryingUInt32)) { - uint32_t v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; - uint32_t result[ISPC_MAX_NVEC]; - constExpr1->AsUInt32(v1); - constExpr2->AsUInt32(v2); - for (int i = 0; i < count; ++i) - result[i] = bv[i] ? v1[i] : v2[i]; - return new ConstExpr(exprType, result, pos); + else if (Type::Equal(exprType, AtomicType::VaryingUInt8)) { + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); + } + else if (Type::Equal(exprType, AtomicType::VaryingInt16)) { + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); + } + else if (Type::Equal(exprType, AtomicType::VaryingUInt16)) { + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); + } + else if (Type::Equal(exprType, AtomicType::VaryingInt32)) { + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); + } + else if (Type::Equal(exprType, AtomicType::VaryingUInt32)) { + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); } else if (Type::Equal(exprType, AtomicType::VaryingInt64)) { - int64_t v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; - int64_t result[ISPC_MAX_NVEC]; - constExpr1->AsInt64(v1); - constExpr2->AsInt64(v2); - for (int i = 0; i < count; ++i) - result[i] = bv[i] ? v1[i] : v2[i]; - return new ConstExpr(exprType, result, pos); + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); } else if (Type::Equal(exprType, AtomicType::VaryingUInt64)) { - uint64_t v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; - uint64_t result[ISPC_MAX_NVEC]; - constExpr1->AsUInt64(v1); - constExpr2->AsUInt64(v2); - for (int i = 0; i < count; ++i) - result[i] = bv[i] ? v1[i] : v2[i]; - return new ConstExpr(exprType, result, pos); + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); } else if (Type::Equal(exprType, AtomicType::VaryingFloat)) { - float v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; - float result[ISPC_MAX_NVEC]; - constExpr1->AsFloat(v1); - constExpr2->AsFloat(v2); - for (int i = 0; i < count; ++i) - result[i] = bv[i] ? v1[i] : v2[i]; - return new ConstExpr(exprType, result, pos); + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); } else if (Type::Equal(exprType, AtomicType::VaryingDouble)) { - double v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; - double result[ISPC_MAX_NVEC]; - constExpr1->AsDouble(v1); - constExpr2->AsDouble(v2); - for (int i = 0; i < count; ++i) - result[i] = bv[i] ? v1[i] : v2[i]; - return new ConstExpr(exprType, result, pos); + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); } else if (Type::Equal(exprType, AtomicType::VaryingBool)) { - bool v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; - bool result[ISPC_MAX_NVEC]; - constExpr1->AsBool(v1); - constExpr2->AsBool(v2); - for (int i = 0; i < count; ++i) - result[i] = bv[i] ? v1[i] : v2[i]; - return new ConstExpr(exprType, result, pos); + return lConstFoldSelect(bv, constExpr1, constExpr2, exprType, pos); } return this; @@ -4171,7 +4214,7 @@ lCheckIndicesVersusBounds(const Type *baseExprType, Expr *index) { return; int32_t indices[ISPC_MAX_NVEC]; - int count = ce->AsInt32(indices); + int count = ce->GetValues(indices); for (int i = 0; i < count; ++i) { if (indices[i] < 0 || indices[i] >= nElements) Warning(index->pos, "Array index \"%d\" may be out of bounds for %d " @@ -5532,7 +5575,7 @@ lConvert(const From *from, To *to, int count, bool forceVarying) { int -ConstExpr::AsInt64(int64_t *ip, bool forceVarying) const { +ConstExpr::GetValues(int64_t *ip, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, ip, Count(), forceVarying); break; @@ -5553,7 +5596,7 @@ ConstExpr::AsInt64(int64_t *ip, bool forceVarying) const { int -ConstExpr::AsUInt64(uint64_t *up, bool forceVarying) const { +ConstExpr::GetValues(uint64_t *up, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, up, Count(), forceVarying); break; @@ -5574,7 +5617,7 @@ ConstExpr::AsUInt64(uint64_t *up, bool forceVarying) const { int -ConstExpr::AsDouble(double *d, bool forceVarying) const { +ConstExpr::GetValues(double *d, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, d, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, d, Count(), forceVarying); break; @@ -5595,7 +5638,7 @@ ConstExpr::AsDouble(double *d, bool forceVarying) const { int -ConstExpr::AsFloat(float *fp, bool forceVarying) const { +ConstExpr::GetValues(float *fp, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, fp, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, fp, Count(), forceVarying); break; @@ -5616,7 +5659,7 @@ ConstExpr::AsFloat(float *fp, bool forceVarying) const { int -ConstExpr::AsBool(bool *b, bool forceVarying) const { +ConstExpr::GetValues(bool *b, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, b, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, b, Count(), forceVarying); break; @@ -5637,7 +5680,7 @@ ConstExpr::AsBool(bool *b, bool forceVarying) const { int -ConstExpr::AsInt8(int8_t *ip, bool forceVarying) const { +ConstExpr::GetValues(int8_t *ip, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, ip, Count(), forceVarying); break; @@ -5658,7 +5701,7 @@ ConstExpr::AsInt8(int8_t *ip, bool forceVarying) const { int -ConstExpr::AsUInt8(uint8_t *up, bool forceVarying) const { +ConstExpr::GetValues(uint8_t *up, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, up, Count(), forceVarying); break; @@ -5679,7 +5722,7 @@ ConstExpr::AsUInt8(uint8_t *up, bool forceVarying) const { int -ConstExpr::AsInt16(int16_t *ip, bool forceVarying) const { +ConstExpr::GetValues(int16_t *ip, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, ip, Count(), forceVarying); break; @@ -5700,7 +5743,7 @@ ConstExpr::AsInt16(int16_t *ip, bool forceVarying) const { int -ConstExpr::AsUInt16(uint16_t *up, bool forceVarying) const { +ConstExpr::GetValues(uint16_t *up, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, up, Count(), forceVarying); break; @@ -5721,7 +5764,7 @@ ConstExpr::AsUInt16(uint16_t *up, bool forceVarying) const { int -ConstExpr::AsInt32(int32_t *ip, bool forceVarying) const { +ConstExpr::GetValues(int32_t *ip, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, ip, Count(), forceVarying); break; @@ -5742,7 +5785,7 @@ ConstExpr::AsInt32(int32_t *ip, bool forceVarying) const { int -ConstExpr::AsUInt32(uint32_t *up, bool forceVarying) const { +ConstExpr::GetValues(uint32_t *up, bool forceVarying) const { switch (getBasicType()) { case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break; case AtomicType::TYPE_INT8: lConvert(int8Val, up, Count(), forceVarying); break; @@ -5779,7 +5822,7 @@ ConstExpr::GetConstant(const Type *type) const { if (Type::Equal(type, AtomicType::UniformBool) || Type::Equal(type, AtomicType::VaryingBool)) { bool bv[ISPC_MAX_NVEC]; - AsBool(bv, type->IsVaryingType()); + GetValues(bv, type->IsVaryingType()); if (type->IsUniformType()) return bv[0] ? LLVMTrue : LLVMFalse; else @@ -5788,7 +5831,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformInt8) || Type::Equal(type, AtomicType::VaryingInt8)) { int8_t iv[ISPC_MAX_NVEC]; - AsInt8(iv, type->IsVaryingType()); + GetValues(iv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMInt8(iv[0]); else @@ -5797,7 +5840,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformUInt8) || Type::Equal(type, AtomicType::VaryingUInt8)) { uint8_t uiv[ISPC_MAX_NVEC]; - AsUInt8(uiv, type->IsVaryingType()); + GetValues(uiv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMUInt8(uiv[0]); else @@ -5806,7 +5849,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformInt16) || Type::Equal(type, AtomicType::VaryingInt16)) { int16_t iv[ISPC_MAX_NVEC]; - AsInt16(iv, type->IsVaryingType()); + GetValues(iv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMInt16(iv[0]); else @@ -5815,7 +5858,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformUInt16) || Type::Equal(type, AtomicType::VaryingUInt16)) { uint16_t uiv[ISPC_MAX_NVEC]; - AsUInt16(uiv, type->IsVaryingType()); + GetValues(uiv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMUInt16(uiv[0]); else @@ -5824,7 +5867,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformInt32) || Type::Equal(type, AtomicType::VaryingInt32)) { int32_t iv[ISPC_MAX_NVEC]; - AsInt32(iv, type->IsVaryingType()); + GetValues(iv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMInt32(iv[0]); else @@ -5834,7 +5877,7 @@ ConstExpr::GetConstant(const Type *type) const { Type::Equal(type, AtomicType::VaryingUInt32) || CastType(type) != NULL) { uint32_t uiv[ISPC_MAX_NVEC]; - AsUInt32(uiv, type->IsVaryingType()); + GetValues(uiv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMUInt32(uiv[0]); else @@ -5843,7 +5886,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformFloat) || Type::Equal(type, AtomicType::VaryingFloat)) { float fv[ISPC_MAX_NVEC]; - AsFloat(fv, type->IsVaryingType()); + GetValues(fv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMFloat(fv[0]); else @@ -5852,7 +5895,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformInt64) || Type::Equal(type, AtomicType::VaryingInt64)) { int64_t iv[ISPC_MAX_NVEC]; - AsInt64(iv, type->IsVaryingType()); + GetValues(iv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMInt64(iv[0]); else @@ -5861,7 +5904,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformUInt64) || Type::Equal(type, AtomicType::VaryingUInt64)) { uint64_t uiv[ISPC_MAX_NVEC]; - AsUInt64(uiv, type->IsVaryingType()); + GetValues(uiv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMUInt64(uiv[0]); else @@ -5870,7 +5913,7 @@ ConstExpr::GetConstant(const Type *type) const { else if (Type::Equal(type, AtomicType::UniformDouble) || Type::Equal(type, AtomicType::VaryingDouble)) { double dv[ISPC_MAX_NVEC]; - AsDouble(dv, type->IsVaryingType()); + GetValues(dv, type->IsVaryingType()); if (type->IsUniformType()) return LLVMDouble(dv[0]); else @@ -5887,7 +5930,7 @@ ConstExpr::GetConstant(const Type *type) const { } int64_t iv[ISPC_MAX_NVEC]; - AsInt64(iv, type->IsVaryingType()); + GetValues(iv, type->IsVaryingType()); for (int i = 0; i < Count(); ++i) if (iv[i] != 0) // We'll issue an error about this later--trying to assign @@ -6976,64 +7019,64 @@ TypeCastExpr::Optimize() { bool forceVarying = toType->IsVaryingType(); // All of the type conversion smarts we need is already in the - // ConstExpr::AsBool(), etc., methods, so we just need to call the + // ConstExpr::GetValues(), etc., methods, so we just need to call the // appropriate one for the type that this cast is converting to. AtomicType::BasicType basicType = toAtomic ? toAtomic->basicType : AtomicType::TYPE_UINT32; switch (basicType) { case AtomicType::TYPE_BOOL: { bool bv[ISPC_MAX_NVEC]; - constExpr->AsBool(bv, forceVarying); + constExpr->GetValues(bv, forceVarying); return new ConstExpr(toType, bv, pos); } case AtomicType::TYPE_INT8: { int8_t iv[ISPC_MAX_NVEC]; - constExpr->AsInt8(iv, forceVarying); + constExpr->GetValues(iv, forceVarying); return new ConstExpr(toType, iv, pos); } case AtomicType::TYPE_UINT8: { uint8_t uv[ISPC_MAX_NVEC]; - constExpr->AsUInt8(uv, forceVarying); + constExpr->GetValues(uv, forceVarying); return new ConstExpr(toType, uv, pos); } case AtomicType::TYPE_INT16: { int16_t iv[ISPC_MAX_NVEC]; - constExpr->AsInt16(iv, forceVarying); + constExpr->GetValues(iv, forceVarying); return new ConstExpr(toType, iv, pos); } case AtomicType::TYPE_UINT16: { uint16_t uv[ISPC_MAX_NVEC]; - constExpr->AsUInt16(uv, forceVarying); + constExpr->GetValues(uv, forceVarying); return new ConstExpr(toType, uv, pos); } case AtomicType::TYPE_INT32: { int32_t iv[ISPC_MAX_NVEC]; - constExpr->AsInt32(iv, forceVarying); + constExpr->GetValues(iv, forceVarying); return new ConstExpr(toType, iv, pos); } case AtomicType::TYPE_UINT32: { uint32_t uv[ISPC_MAX_NVEC]; - constExpr->AsUInt32(uv, forceVarying); + constExpr->GetValues(uv, forceVarying); return new ConstExpr(toType, uv, pos); } case AtomicType::TYPE_FLOAT: { float fv[ISPC_MAX_NVEC]; - constExpr->AsFloat(fv, forceVarying); + constExpr->GetValues(fv, forceVarying); return new ConstExpr(toType, fv, pos); } case AtomicType::TYPE_INT64: { int64_t iv[ISPC_MAX_NVEC]; - constExpr->AsInt64(iv, forceVarying); + constExpr->GetValues(iv, forceVarying); return new ConstExpr(toType, iv, pos); } case AtomicType::TYPE_UINT64: { uint64_t uv[ISPC_MAX_NVEC]; - constExpr->AsUInt64(uv, forceVarying); + constExpr->GetValues(uv, forceVarying); return new ConstExpr(toType, uv, pos); } case AtomicType::TYPE_DOUBLE: { double dv[ISPC_MAX_NVEC]; - constExpr->AsDouble(dv, forceVarying); + constExpr->GetValues(dv, forceVarying); return new ConstExpr(toType, dv, pos); } default: diff --git a/expr.h b/expr.h index 1ea44c4b..42fdff45 100644 --- a/expr.h +++ b/expr.h @@ -409,71 +409,22 @@ public: Expr *Optimize(); int EstimateCost() const; - /** Return the ConstExpr's values as booleans, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsBool(bool *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as int8s, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsInt8(int8_t *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as uint8s, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsUInt8(uint8_t *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as int16s, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsInt16(int16_t *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as uint16s, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsUInt16(uint16_t *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as int32s, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsInt32(int32_t *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as uint32s, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsUInt32(uint32_t *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as floats, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsFloat(float *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as int64s, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsInt64(int64_t *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as uint64s, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsUInt64(uint64_t *, bool forceVarying = false) const; - - /** Return the ConstExpr's values as doubles, doing type conversion - from the actual type if needed. If forceVarying is true, then type - convert to 'varying' so as to always return a number of values - equal to the target vector width into the given pointer. */ - int AsDouble(double *, bool forceVarying = false) const; + /** Return the ConstExpr's values as the given pointer type, doing type + conversion from the actual type if needed. If forceVarying is + true, then type convert to 'varying' so as to always return a + number of values equal to the target vector width into the given + pointer. */ + int GetValues(bool *, bool forceVarying = false) const; + int GetValues(int8_t *, bool forceVarying = false) const; + int GetValues(uint8_t *, bool forceVarying = false) const; + int GetValues(int16_t *, bool forceVarying = false) const; + int GetValues(uint16_t *, bool forceVarying = false) const; + int GetValues(int32_t *, bool forceVarying = false) const; + int GetValues(uint32_t *, bool forceVarying = false) const; + int GetValues(float *, bool forceVarying = false) const; + int GetValues(int64_t *, bool forceVarying = false) const; + int GetValues(uint64_t *, bool forceVarying = false) const; + int GetValues(double *, bool forceVarying = false) const; /** Return the number of values in the ConstExpr; should be either 1, if it has uniform type, or the target's vector width if it's diff --git a/module.cpp b/module.cpp index fe82be37..d4521d66 100644 --- a/module.cpp +++ b/module.cpp @@ -1196,7 +1196,7 @@ lEmitEnumDecls(const std::vector &enumTypes, FILE *file) { const Symbol *e = enumTypes[i]->GetEnumerator(j); Assert(e->constValue != NULL); unsigned int enumValue; - int count = e->constValue->AsUInt32(&enumValue); + int count = e->constValue->GetValues(&enumValue); Assert(count == 1); // Always print an initializer to set the value. We could be diff --git a/parse.yy b/parse.yy index 7c33e53c..3ad815cf 100644 --- a/parse.yy +++ b/parse.yy @@ -2287,7 +2287,7 @@ lFinalizeEnumeratorSymbols(std::vector &enums, enums[i]->type = enumType; if (enums[i]->constValue != NULL) { /* Already has a value, so first update nextVal with it. */ - int count = enums[i]->constValue->AsUInt32(&nextVal); + int count = enums[i]->constValue->GetValues(&nextVal); AssertPos(enums[i]->pos, count == 1); ++nextVal; diff --git a/tests_errors/const-too-large.ispc b/tests_errors/const-too-large.ispc new file mode 100644 index 00000000..80594b78 --- /dev/null +++ b/tests_errors/const-too-large.ispc @@ -0,0 +1,3 @@ +// Binary expression with type "const uniform int8" can't represent value. + +int8 v = (int8)64 * (int8)32; diff --git a/type.cpp b/type.cpp index 2875eaec..5fa1845b 100644 --- a/type.cpp +++ b/type.cpp @@ -804,7 +804,7 @@ EnumType::GetDIType(llvm::DIDescriptor scope) const { for (unsigned int i = 0; i < enumerators.size(); ++i) { unsigned int enumeratorValue; Assert(enumerators[i]->constValue != NULL); - int count = enumerators[i]->constValue->AsUInt32(&enumeratorValue); + int count = enumerators[i]->constValue->GetValues(&enumeratorValue); Assert(count == 1); llvm::Value *descriptor =