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.
This commit is contained in:
Matt Pharr
2013-07-22 16:12:02 -07:00
parent abf43ad01d
commit 564e61c828
7 changed files with 267 additions and 270 deletions

View File

@@ -446,7 +446,7 @@ lCheckAllOffSafety(ASTNode *node, void *data) {
} }
int32_t indices[ISPC_MAX_NVEC]; int32_t indices[ISPC_MAX_NVEC];
int count = ce->AsInt32(indices); int count = ce->GetValues(indices);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if (indices[i] < 0 || indices[i] >= nElements) { if (indices[i] < 0 || indices[i] >= nElements) {
// Index is out of bounds -> not safe // Index is out of bounds -> not safe

445
expr.cpp
View File

@@ -180,7 +180,7 @@ lIsAllIntZeros(Expr *expr) {
return false; return false;
uint64_t vals[ISPC_MAX_NVEC]; uint64_t vals[ISPC_MAX_NVEC];
int count = ce->AsUInt64(vals); int count = ce->GetValues(vals);
if (count == 1) if (count == 1)
return (vals[0] == 0); return (vals[0] == 0);
else { else {
@@ -1161,6 +1161,16 @@ UnaryExpr::GetType() const {
} }
template <typename T> 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 * Expr *
UnaryExpr::Optimize() { UnaryExpr::Optimize() {
ConstExpr *constExpr = dynamic_cast<ConstExpr *>(expr); ConstExpr *constExpr = dynamic_cast<ConstExpr *>(expr);
@@ -1172,17 +1182,6 @@ UnaryExpr::Optimize() {
const Type *type = constExpr->GetType(); const Type *type = constExpr->GetType();
bool isEnumType = CastType<EnumType>(type) != NULL; bool isEnumType = CastType<EnumType>(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) { switch (op) {
case PreInc: case PreInc:
case PreDec: case PreDec:
@@ -1192,42 +1191,76 @@ UnaryExpr::Optimize() {
// An error will be issued elsewhere... // An error will be issued elsewhere...
return this; return this;
case Negate: { case Negate: {
// Since we currently only handle int32, floats, and doubles here, if (Type::EqualIgnoringConst(type, AtomicType::UniformInt64) ||
// it's safe to stuff whatever we have into a double, do the negate Type::EqualIgnoringConst(type, AtomicType::VaryingInt64)) {
// as a double, and then return a ConstExpr with the same type as int64_t v[ISPC_MAX_NVEC];
// the original... int count = constExpr->GetValues(v);
double v[ISPC_MAX_NVEC]; for (int i = 0; i < count; ++i)
int count = constExpr->AsDouble(v); v[i] = -v[i];
for (int i = 0; i < count; ++i) return new ConstExpr(type, v, pos);
v[i] = -v[i]; }
return new ConstExpr(constExpr, v); 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: { case BitNot: {
if (Type::EqualIgnoringConst(type, AtomicType::UniformInt32) || if (Type::EqualIgnoringConst(type, AtomicType::UniformInt8) ||
Type::EqualIgnoringConst(type, AtomicType::VaryingInt32)) { Type::EqualIgnoringConst(type, AtomicType::VaryingInt8)) {
int32_t v[ISPC_MAX_NVEC]; return lOptimizeBitNot<int8_t>(constExpr, type, pos);
int count = constExpr->AsInt32(v); }
for (int i = 0; i < count; ++i) else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt8) ||
v[i] = ~v[i]; Type::EqualIgnoringConst(type, AtomicType::VaryingUInt8)) {
return new ConstExpr(type, v, pos); return lOptimizeBitNot<uint8_t>(constExpr, type, pos);
}
else if (Type::EqualIgnoringConst(type, AtomicType::UniformInt16) ||
Type::EqualIgnoringConst(type, AtomicType::VaryingInt16)) {
return lOptimizeBitNot<int16_t>(constExpr, type, pos);
}
else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt16) ||
Type::EqualIgnoringConst(type, AtomicType::VaryingUInt16)) {
return lOptimizeBitNot<uint16_t>(constExpr, type, pos);
}
else if (Type::EqualIgnoringConst(type, AtomicType::UniformInt32) ||
Type::EqualIgnoringConst(type, AtomicType::VaryingInt32)) {
return lOptimizeBitNot<int32_t>(constExpr, type, pos);
} }
else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt32) || else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt32) ||
Type::EqualIgnoringConst(type, AtomicType::VaryingUInt32) || Type::EqualIgnoringConst(type, AtomicType::VaryingUInt32) ||
isEnumType == true) { isEnumType == true) {
uint32_t v[ISPC_MAX_NVEC]; return lOptimizeBitNot<uint32_t>(constExpr, type, pos);
int count = constExpr->AsUInt32(v); }
for (int i = 0; i < count; ++i) else if (Type::EqualIgnoringConst(type, AtomicType::UniformInt64) ||
v[i] = ~v[i]; Type::EqualIgnoringConst(type, AtomicType::VaryingInt64)) {
return new ConstExpr(type, v, pos); return lOptimizeBitNot<int64_t>(constExpr, type, pos);
}
else if (Type::EqualIgnoringConst(type, AtomicType::UniformUInt64) ||
Type::EqualIgnoringConst(type, AtomicType::VaryingUInt64) ||
isEnumType == true) {
return lOptimizeBitNot<uint64_t>(constExpr, type, pos);
} }
else else
FATAL("unexpected type in UnaryExpr::Optimize() / BitNot case"); FATAL("unexpected type in UnaryExpr::Optimize() / BitNot case");
} }
case LogicalNot: { case LogicalNot: {
AssertPos(pos, Type::EqualIgnoringConst(type, AtomicType::UniformBool) || AssertPos(pos, Type::EqualIgnoringConst(type, AtomicType::UniformBool) ||
Type::EqualIgnoringConst(type, AtomicType::VaryingBool)); Type::EqualIgnoringConst(type, AtomicType::VaryingBool));
bool v[ISPC_MAX_NVEC]; bool v[ISPC_MAX_NVEC];
int count = constExpr->AsBool(v); int count = constExpr->GetValues(v);
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
v[i] = !v[i]; v[i] = !v[i];
return new ConstExpr(type, v, pos); return new ConstExpr(type, v, pos);
@@ -2016,25 +2049,37 @@ BinaryExpr::GetType() const {
#define FOLD_OP(O, E) \ #define FOLD_OP(O, E) \
case O: \ case O: \
for (int i = 0; i < count; ++i) \ for (int i = 0; i < count; ++i) \
result[i] = (v0[i] E v1[i]); \ result[i] = (v0[i] E v1[i]); \
break 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 /** Constant fold the binary integer operations that aren't also applicable
to floating-point types. to floating-point types.
*/ */
template <typename T> static ConstExpr * template <typename T, typename TRef> static ConstExpr *
lConstFoldBinIntOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0) { lConstFoldBinaryIntOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0,
SourcePos pos) {
T result[ISPC_MAX_NVEC]; T result[ISPC_MAX_NVEC];
int count = carg0->Count(); int count = carg0->Count();
switch (op) { switch (op) {
FOLD_OP(BinaryExpr::Mod, %); FOLD_OP_REF(BinaryExpr::Mod, %, TRef);
FOLD_OP(BinaryExpr::Shl, <<); FOLD_OP_REF(BinaryExpr::Shl, <<, TRef);
FOLD_OP(BinaryExpr::Shr, >>); FOLD_OP_REF(BinaryExpr::Shr, >>, TRef);
FOLD_OP(BinaryExpr::BitAnd, &); FOLD_OP_REF(BinaryExpr::BitAnd, &, TRef);
FOLD_OP(BinaryExpr::BitXor, ^); FOLD_OP_REF(BinaryExpr::BitXor, ^, TRef);
FOLD_OP(BinaryExpr::BitOr, |); FOLD_OP_REF(BinaryExpr::BitOr, |, TRef);
default: default:
return NULL; return NULL;
} }
@@ -2046,7 +2091,8 @@ lConstFoldBinIntOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0
/** Constant fold the binary logical ops. /** Constant fold the binary logical ops.
*/ */
template <typename T> static ConstExpr * template <typename T> 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]; bool result[ISPC_MAX_NVEC];
int count = carg0->Count(); 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. /** Constant fold binary arithmetic ops.
*/ */
template <typename T> static ConstExpr * template <typename T, typename TRef> static ConstExpr *
lConstFoldBinArithOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0, lConstFoldBinaryArithOp(BinaryExpr::Op op, const T *v0, const T *v1, ConstExpr *carg0,
SourcePos pos) { SourcePos pos) {
T result[ISPC_MAX_NVEC]; T result[ISPC_MAX_NVEC];
int count = carg0->Count(); int count = carg0->Count();
switch (op) { switch (op) {
FOLD_OP(BinaryExpr::Add, +); FOLD_OP_REF(BinaryExpr::Add, +, TRef);
FOLD_OP(BinaryExpr::Sub, -); FOLD_OP_REF(BinaryExpr::Sub, -, TRef);
FOLD_OP(BinaryExpr::Mul, *); FOLD_OP_REF(BinaryExpr::Mul, *, TRef);
case BinaryExpr::Div: case BinaryExpr::Div:
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if (v1[i] == 0) { 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. /** Constant fold the various boolean binary ops.
*/ */
static ConstExpr * static ConstExpr *
lConstFoldBoolBinOp(BinaryExpr::Op op, const bool *v0, const bool *v1, lConstFoldBoolBinaryOp(BinaryExpr::Op op, const bool *v0, const bool *v1,
ConstExpr *carg0) { ConstExpr *carg0) {
bool result[ISPC_MAX_NVEC]; bool result[ISPC_MAX_NVEC];
int count = carg0->Count(); int count = carg0->Count();
@@ -2127,6 +2173,40 @@ lConstFoldBoolBinOp(BinaryExpr::Op op, const bool *v0, const bool *v1,
} }
template <typename T> 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<T, T>(op, v0, v1, constArg0, pos)) != NULL)
return ret;
else if ((ret = lConstFoldBinaryLogicalOp(op, v0, v1, constArg0)) != NULL)
return ret;
else
return origExpr;
}
template <typename T, typename TRef> 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<T, TRef>(op, v0, v1, constArg0, pos)) != NULL)
return ret;
else if ((ret = lConstFoldBinaryIntOp<T, TRef>(op, v0, v1, constArg0, pos)) != NULL)
return ret;
else if ((ret = lConstFoldBinaryLogicalOp(op, v0, v1, constArg0)) != NULL)
return ret;
else
return origExpr;
}
Expr * Expr *
BinaryExpr::Optimize() { BinaryExpr::Optimize() {
if (arg0 == NULL || arg1 == NULL) if (arg0 == NULL || arg1 == NULL)
@@ -2144,7 +2224,7 @@ BinaryExpr::Optimize() {
if (Type::EqualIgnoringConst(type1, AtomicType::UniformFloat) || if (Type::EqualIgnoringConst(type1, AtomicType::UniformFloat) ||
Type::EqualIgnoringConst(type1, AtomicType::VaryingFloat)) { Type::EqualIgnoringConst(type1, AtomicType::VaryingFloat)) {
float inv[ISPC_MAX_NVEC]; float inv[ISPC_MAX_NVEC];
int count = constArg1->AsFloat(inv); int count = constArg1->GetValues(inv);
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
inv[i] = 1.f / inv[i]; inv[i] = 1.f / inv[i];
Expr *einv = new ConstExpr(type1, inv, constArg1->pos); Expr *einv = new ConstExpr(type1, inv, constArg1->pos);
@@ -2198,70 +2278,53 @@ BinaryExpr::Optimize() {
const Type *type = arg0->GetType()->GetAsNonConstType(); const Type *type = arg0->GetType()->GetAsNonConstType();
if (Type::Equal(type, AtomicType::UniformFloat) || if (Type::Equal(type, AtomicType::UniformFloat) ||
Type::Equal(type, AtomicType::VaryingFloat)) { Type::Equal(type, AtomicType::VaryingFloat)) {
float v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; return lConstFoldBinaryFPOp<float>(constArg0, constArg1, op, this, pos);
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;
} }
if (Type::Equal(type, AtomicType::UniformDouble) || else if (Type::Equal(type, AtomicType::UniformDouble) ||
Type::Equal(type, AtomicType::VaryingDouble)) { Type::Equal(type, AtomicType::VaryingDouble)) {
double v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; return lConstFoldBinaryFPOp<double>(constArg0, constArg1, op, this, pos);
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;
} }
if (Type::Equal(type, AtomicType::UniformInt32) || else if (Type::Equal(type, AtomicType::UniformInt8) ||
Type::Equal(type, AtomicType::VaryingInt32)) { Type::Equal(type, AtomicType::VaryingInt8)) {
int32_t v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; return lConstFoldBinaryIntOp<int8_t, int64_t>(constArg0, constArg1, op, this, pos);
constArg0->AsInt32(v0); }
constArg1->AsInt32(v1); else if (Type::Equal(type, AtomicType::UniformUInt8) ||
ConstExpr *ret; Type::Equal(type, AtomicType::VaryingUInt8)) {
if ((ret = lConstFoldBinArithOp(op, v0, v1, constArg0, pos)) != NULL) return lConstFoldBinaryIntOp<uint8_t, uint64_t>(constArg0, constArg1, op, this, pos);
return ret; }
else if ((ret = lConstFoldBinIntOp(op, v0, v1, constArg0)) != NULL) else if (Type::Equal(type, AtomicType::UniformInt16) ||
return ret; Type::Equal(type, AtomicType::VaryingInt16)) {
else if ((ret = lConstFoldBinLogicalOp(op, v0, v1, constArg0)) != NULL) return lConstFoldBinaryIntOp<int16_t, int64_t>(constArg0, constArg1, op, this, pos);
return ret; }
else else if (Type::Equal(type, AtomicType::UniformUInt16) ||
return this; Type::Equal(type, AtomicType::VaryingUInt16)) {
return lConstFoldBinaryIntOp<uint16_t, uint64_t>(constArg0, constArg1, op, this, pos);
}
else if (Type::Equal(type, AtomicType::UniformInt32) ||
Type::Equal(type, AtomicType::VaryingInt32)) {
return lConstFoldBinaryIntOp<int32_t, int64_t>(constArg0, constArg1, op, this, pos);
} }
else if (Type::Equal(type, AtomicType::UniformUInt32) || else if (Type::Equal(type, AtomicType::UniformUInt32) ||
Type::Equal(type, AtomicType::VaryingUInt32) || Type::Equal(type, AtomicType::VaryingUInt32)) {
CastType<EnumType>(type) != NULL) { return lConstFoldBinaryIntOp<uint32_t, uint64_t>(constArg0, constArg1, op, this, pos);
uint32_t v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; }
constArg0->AsUInt32(v0); else if (Type::Equal(type, AtomicType::UniformInt64) ||
constArg1->AsUInt32(v1); Type::Equal(type, AtomicType::VaryingInt64)) {
ConstExpr *ret; return lConstFoldBinaryIntOp<int64_t, int64_t>(constArg0, constArg1, op, this, pos);
if ((ret = lConstFoldBinArithOp(op, v0, v1, constArg0, pos)) != NULL) }
return ret; else if (Type::Equal(type, AtomicType::UniformUInt64) ||
else if ((ret = lConstFoldBinIntOp(op, v0, v1, constArg0)) != NULL) Type::Equal(type, AtomicType::VaryingUInt64)) {
return ret; return lConstFoldBinaryIntOp<uint64_t, uint64_t>(constArg0, constArg1, op, this, pos);
else if ((ret = lConstFoldBinLogicalOp(op, v0, v1, constArg0)) != NULL)
return ret;
else
return this;
} }
else if (Type::Equal(type, AtomicType::UniformBool) || else if (Type::Equal(type, AtomicType::UniformBool) ||
Type::Equal(type, AtomicType::VaryingBool)) { Type::Equal(type, AtomicType::VaryingBool)) {
bool v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC]; bool v0[ISPC_MAX_NVEC], v1[ISPC_MAX_NVEC];
constArg0->AsBool(v0); constArg0->GetValues(v0);
constArg1->AsBool(v1); constArg1->GetValues(v1);
ConstExpr *ret; ConstExpr *ret;
if ((ret = lConstFoldBoolBinOp(op, v0, v1, constArg0)) != NULL) if ((ret = lConstFoldBoolBinaryOp(op, v0, v1, constArg0)) != NULL)
return ret; return ret;
else if ((ret = lConstFoldBinLogicalOp(op, v0, v1, constArg0)) != NULL) else if ((ret = lConstFoldBinaryLogicalOp(op, v0, v1, constArg0)) != NULL)
return ret; return ret;
else else
return this; return this;
@@ -3159,6 +3222,19 @@ SelectExpr::GetType() const {
} }
template <typename T> 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 * Expr *
SelectExpr::Optimize() { SelectExpr::Optimize() {
if (test == NULL || expr1 == NULL || expr2 == NULL) 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 // The test is a constant; see if we can resolve to one of the
// expressions.. // expressions..
bool bv[ISPC_MAX_NVEC]; bool bv[ISPC_MAX_NVEC];
int count = constTest->AsBool(bv); int count = constTest->GetValues(bv);
if (count == 1) if (count == 1)
// Uniform test value; return the corresponding expression // Uniform test value; return the corresponding expression
return (bv[0] == true) ? expr1 : expr2; return (bv[0] == true) ? expr1 : expr2;
@@ -3200,71 +3276,38 @@ SelectExpr::Optimize() {
const Type *exprType = constExpr1->GetType()->GetAsNonConstType(); const Type *exprType = constExpr1->GetType()->GetAsNonConstType();
AssertPos(pos, exprType->IsVaryingType()); AssertPos(pos, exprType->IsVaryingType());
// FIXME: it's annoying to have to have all of this replicated code. if (Type::Equal(exprType, AtomicType::VaryingInt8)) {
// FIXME: for completeness, it would also be nice to handle 8 and return lConstFoldSelect<int8_t>(bv, constExpr1, constExpr2, exprType, pos);
// 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::VaryingUInt32)) { else if (Type::Equal(exprType, AtomicType::VaryingUInt8)) {
uint32_t v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; return lConstFoldSelect<uint8_t>(bv, constExpr1, constExpr2, exprType, pos);
uint32_t result[ISPC_MAX_NVEC]; }
constExpr1->AsUInt32(v1); else if (Type::Equal(exprType, AtomicType::VaryingInt16)) {
constExpr2->AsUInt32(v2); return lConstFoldSelect<int16_t>(bv, constExpr1, constExpr2, exprType, pos);
for (int i = 0; i < count; ++i) }
result[i] = bv[i] ? v1[i] : v2[i]; else if (Type::Equal(exprType, AtomicType::VaryingUInt16)) {
return new ConstExpr(exprType, result, pos); return lConstFoldSelect<uint16_t>(bv, constExpr1, constExpr2, exprType, pos);
}
else if (Type::Equal(exprType, AtomicType::VaryingInt32)) {
return lConstFoldSelect<int32_t>(bv, constExpr1, constExpr2, exprType, pos);
}
else if (Type::Equal(exprType, AtomicType::VaryingUInt32)) {
return lConstFoldSelect<uint32_t>(bv, constExpr1, constExpr2, exprType, pos);
} }
else if (Type::Equal(exprType, AtomicType::VaryingInt64)) { else if (Type::Equal(exprType, AtomicType::VaryingInt64)) {
int64_t v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; return lConstFoldSelect<int64_t>(bv, constExpr1, constExpr2, exprType, pos);
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);
} }
else if (Type::Equal(exprType, AtomicType::VaryingUInt64)) { else if (Type::Equal(exprType, AtomicType::VaryingUInt64)) {
uint64_t v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; return lConstFoldSelect<uint64_t>(bv, constExpr1, constExpr2, exprType, pos);
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);
} }
else if (Type::Equal(exprType, AtomicType::VaryingFloat)) { else if (Type::Equal(exprType, AtomicType::VaryingFloat)) {
float v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; return lConstFoldSelect<float>(bv, constExpr1, constExpr2, exprType, pos);
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);
} }
else if (Type::Equal(exprType, AtomicType::VaryingDouble)) { else if (Type::Equal(exprType, AtomicType::VaryingDouble)) {
double v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; return lConstFoldSelect<bool>(bv, constExpr1, constExpr2, exprType, pos);
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);
} }
else if (Type::Equal(exprType, AtomicType::VaryingBool)) { else if (Type::Equal(exprType, AtomicType::VaryingBool)) {
bool v1[ISPC_MAX_NVEC], v2[ISPC_MAX_NVEC]; return lConstFoldSelect<double>(bv, constExpr1, constExpr2, exprType, pos);
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 this; return this;
@@ -4171,7 +4214,7 @@ lCheckIndicesVersusBounds(const Type *baseExprType, Expr *index) {
return; return;
int32_t indices[ISPC_MAX_NVEC]; int32_t indices[ISPC_MAX_NVEC];
int count = ce->AsInt32(indices); int count = ce->GetValues(indices);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if (indices[i] < 0 || indices[i] >= nElements) if (indices[i] < 0 || indices[i] >= nElements)
Warning(index->pos, "Array index \"%d\" may be out of bounds for %d " 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 int
ConstExpr::AsInt64(int64_t *ip, bool forceVarying) const { ConstExpr::GetValues(int64_t *ip, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsUInt64(uint64_t *up, bool forceVarying) const { ConstExpr::GetValues(uint64_t *up, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsDouble(double *d, bool forceVarying) const { ConstExpr::GetValues(double *d, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, d, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, d, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsFloat(float *fp, bool forceVarying) const { ConstExpr::GetValues(float *fp, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, fp, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, fp, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsBool(bool *b, bool forceVarying) const { ConstExpr::GetValues(bool *b, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, b, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, b, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsInt8(int8_t *ip, bool forceVarying) const { ConstExpr::GetValues(int8_t *ip, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsUInt8(uint8_t *up, bool forceVarying) const { ConstExpr::GetValues(uint8_t *up, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsInt16(int16_t *ip, bool forceVarying) const { ConstExpr::GetValues(int16_t *ip, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsUInt16(uint16_t *up, bool forceVarying) const { ConstExpr::GetValues(uint16_t *up, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsInt32(int32_t *ip, bool forceVarying) const { ConstExpr::GetValues(int32_t *ip, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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 int
ConstExpr::AsUInt32(uint32_t *up, bool forceVarying) const { ConstExpr::GetValues(uint32_t *up, bool forceVarying) const {
switch (getBasicType()) { switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break; case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, 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) || if (Type::Equal(type, AtomicType::UniformBool) ||
Type::Equal(type, AtomicType::VaryingBool)) { Type::Equal(type, AtomicType::VaryingBool)) {
bool bv[ISPC_MAX_NVEC]; bool bv[ISPC_MAX_NVEC];
AsBool(bv, type->IsVaryingType()); GetValues(bv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return bv[0] ? LLVMTrue : LLVMFalse; return bv[0] ? LLVMTrue : LLVMFalse;
else else
@@ -5788,7 +5831,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformInt8) || else if (Type::Equal(type, AtomicType::UniformInt8) ||
Type::Equal(type, AtomicType::VaryingInt8)) { Type::Equal(type, AtomicType::VaryingInt8)) {
int8_t iv[ISPC_MAX_NVEC]; int8_t iv[ISPC_MAX_NVEC];
AsInt8(iv, type->IsVaryingType()); GetValues(iv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMInt8(iv[0]); return LLVMInt8(iv[0]);
else else
@@ -5797,7 +5840,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformUInt8) || else if (Type::Equal(type, AtomicType::UniformUInt8) ||
Type::Equal(type, AtomicType::VaryingUInt8)) { Type::Equal(type, AtomicType::VaryingUInt8)) {
uint8_t uiv[ISPC_MAX_NVEC]; uint8_t uiv[ISPC_MAX_NVEC];
AsUInt8(uiv, type->IsVaryingType()); GetValues(uiv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMUInt8(uiv[0]); return LLVMUInt8(uiv[0]);
else else
@@ -5806,7 +5849,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformInt16) || else if (Type::Equal(type, AtomicType::UniformInt16) ||
Type::Equal(type, AtomicType::VaryingInt16)) { Type::Equal(type, AtomicType::VaryingInt16)) {
int16_t iv[ISPC_MAX_NVEC]; int16_t iv[ISPC_MAX_NVEC];
AsInt16(iv, type->IsVaryingType()); GetValues(iv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMInt16(iv[0]); return LLVMInt16(iv[0]);
else else
@@ -5815,7 +5858,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformUInt16) || else if (Type::Equal(type, AtomicType::UniformUInt16) ||
Type::Equal(type, AtomicType::VaryingUInt16)) { Type::Equal(type, AtomicType::VaryingUInt16)) {
uint16_t uiv[ISPC_MAX_NVEC]; uint16_t uiv[ISPC_MAX_NVEC];
AsUInt16(uiv, type->IsVaryingType()); GetValues(uiv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMUInt16(uiv[0]); return LLVMUInt16(uiv[0]);
else else
@@ -5824,7 +5867,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformInt32) || else if (Type::Equal(type, AtomicType::UniformInt32) ||
Type::Equal(type, AtomicType::VaryingInt32)) { Type::Equal(type, AtomicType::VaryingInt32)) {
int32_t iv[ISPC_MAX_NVEC]; int32_t iv[ISPC_MAX_NVEC];
AsInt32(iv, type->IsVaryingType()); GetValues(iv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMInt32(iv[0]); return LLVMInt32(iv[0]);
else else
@@ -5834,7 +5877,7 @@ ConstExpr::GetConstant(const Type *type) const {
Type::Equal(type, AtomicType::VaryingUInt32) || Type::Equal(type, AtomicType::VaryingUInt32) ||
CastType<EnumType>(type) != NULL) { CastType<EnumType>(type) != NULL) {
uint32_t uiv[ISPC_MAX_NVEC]; uint32_t uiv[ISPC_MAX_NVEC];
AsUInt32(uiv, type->IsVaryingType()); GetValues(uiv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMUInt32(uiv[0]); return LLVMUInt32(uiv[0]);
else else
@@ -5843,7 +5886,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformFloat) || else if (Type::Equal(type, AtomicType::UniformFloat) ||
Type::Equal(type, AtomicType::VaryingFloat)) { Type::Equal(type, AtomicType::VaryingFloat)) {
float fv[ISPC_MAX_NVEC]; float fv[ISPC_MAX_NVEC];
AsFloat(fv, type->IsVaryingType()); GetValues(fv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMFloat(fv[0]); return LLVMFloat(fv[0]);
else else
@@ -5852,7 +5895,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformInt64) || else if (Type::Equal(type, AtomicType::UniformInt64) ||
Type::Equal(type, AtomicType::VaryingInt64)) { Type::Equal(type, AtomicType::VaryingInt64)) {
int64_t iv[ISPC_MAX_NVEC]; int64_t iv[ISPC_MAX_NVEC];
AsInt64(iv, type->IsVaryingType()); GetValues(iv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMInt64(iv[0]); return LLVMInt64(iv[0]);
else else
@@ -5861,7 +5904,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformUInt64) || else if (Type::Equal(type, AtomicType::UniformUInt64) ||
Type::Equal(type, AtomicType::VaryingUInt64)) { Type::Equal(type, AtomicType::VaryingUInt64)) {
uint64_t uiv[ISPC_MAX_NVEC]; uint64_t uiv[ISPC_MAX_NVEC];
AsUInt64(uiv, type->IsVaryingType()); GetValues(uiv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMUInt64(uiv[0]); return LLVMUInt64(uiv[0]);
else else
@@ -5870,7 +5913,7 @@ ConstExpr::GetConstant(const Type *type) const {
else if (Type::Equal(type, AtomicType::UniformDouble) || else if (Type::Equal(type, AtomicType::UniformDouble) ||
Type::Equal(type, AtomicType::VaryingDouble)) { Type::Equal(type, AtomicType::VaryingDouble)) {
double dv[ISPC_MAX_NVEC]; double dv[ISPC_MAX_NVEC];
AsDouble(dv, type->IsVaryingType()); GetValues(dv, type->IsVaryingType());
if (type->IsUniformType()) if (type->IsUniformType())
return LLVMDouble(dv[0]); return LLVMDouble(dv[0]);
else else
@@ -5887,7 +5930,7 @@ ConstExpr::GetConstant(const Type *type) const {
} }
int64_t iv[ISPC_MAX_NVEC]; int64_t iv[ISPC_MAX_NVEC];
AsInt64(iv, type->IsVaryingType()); GetValues(iv, type->IsVaryingType());
for (int i = 0; i < Count(); ++i) for (int i = 0; i < Count(); ++i)
if (iv[i] != 0) if (iv[i] != 0)
// We'll issue an error about this later--trying to assign // We'll issue an error about this later--trying to assign
@@ -6976,64 +7019,64 @@ TypeCastExpr::Optimize() {
bool forceVarying = toType->IsVaryingType(); bool forceVarying = toType->IsVaryingType();
// All of the type conversion smarts we need is already in the // 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. // appropriate one for the type that this cast is converting to.
AtomicType::BasicType basicType = toAtomic ? toAtomic->basicType : AtomicType::BasicType basicType = toAtomic ? toAtomic->basicType :
AtomicType::TYPE_UINT32; AtomicType::TYPE_UINT32;
switch (basicType) { switch (basicType) {
case AtomicType::TYPE_BOOL: { case AtomicType::TYPE_BOOL: {
bool bv[ISPC_MAX_NVEC]; bool bv[ISPC_MAX_NVEC];
constExpr->AsBool(bv, forceVarying); constExpr->GetValues(bv, forceVarying);
return new ConstExpr(toType, bv, pos); return new ConstExpr(toType, bv, pos);
} }
case AtomicType::TYPE_INT8: { case AtomicType::TYPE_INT8: {
int8_t iv[ISPC_MAX_NVEC]; int8_t iv[ISPC_MAX_NVEC];
constExpr->AsInt8(iv, forceVarying); constExpr->GetValues(iv, forceVarying);
return new ConstExpr(toType, iv, pos); return new ConstExpr(toType, iv, pos);
} }
case AtomicType::TYPE_UINT8: { case AtomicType::TYPE_UINT8: {
uint8_t uv[ISPC_MAX_NVEC]; uint8_t uv[ISPC_MAX_NVEC];
constExpr->AsUInt8(uv, forceVarying); constExpr->GetValues(uv, forceVarying);
return new ConstExpr(toType, uv, pos); return new ConstExpr(toType, uv, pos);
} }
case AtomicType::TYPE_INT16: { case AtomicType::TYPE_INT16: {
int16_t iv[ISPC_MAX_NVEC]; int16_t iv[ISPC_MAX_NVEC];
constExpr->AsInt16(iv, forceVarying); constExpr->GetValues(iv, forceVarying);
return new ConstExpr(toType, iv, pos); return new ConstExpr(toType, iv, pos);
} }
case AtomicType::TYPE_UINT16: { case AtomicType::TYPE_UINT16: {
uint16_t uv[ISPC_MAX_NVEC]; uint16_t uv[ISPC_MAX_NVEC];
constExpr->AsUInt16(uv, forceVarying); constExpr->GetValues(uv, forceVarying);
return new ConstExpr(toType, uv, pos); return new ConstExpr(toType, uv, pos);
} }
case AtomicType::TYPE_INT32: { case AtomicType::TYPE_INT32: {
int32_t iv[ISPC_MAX_NVEC]; int32_t iv[ISPC_MAX_NVEC];
constExpr->AsInt32(iv, forceVarying); constExpr->GetValues(iv, forceVarying);
return new ConstExpr(toType, iv, pos); return new ConstExpr(toType, iv, pos);
} }
case AtomicType::TYPE_UINT32: { case AtomicType::TYPE_UINT32: {
uint32_t uv[ISPC_MAX_NVEC]; uint32_t uv[ISPC_MAX_NVEC];
constExpr->AsUInt32(uv, forceVarying); constExpr->GetValues(uv, forceVarying);
return new ConstExpr(toType, uv, pos); return new ConstExpr(toType, uv, pos);
} }
case AtomicType::TYPE_FLOAT: { case AtomicType::TYPE_FLOAT: {
float fv[ISPC_MAX_NVEC]; float fv[ISPC_MAX_NVEC];
constExpr->AsFloat(fv, forceVarying); constExpr->GetValues(fv, forceVarying);
return new ConstExpr(toType, fv, pos); return new ConstExpr(toType, fv, pos);
} }
case AtomicType::TYPE_INT64: { case AtomicType::TYPE_INT64: {
int64_t iv[ISPC_MAX_NVEC]; int64_t iv[ISPC_MAX_NVEC];
constExpr->AsInt64(iv, forceVarying); constExpr->GetValues(iv, forceVarying);
return new ConstExpr(toType, iv, pos); return new ConstExpr(toType, iv, pos);
} }
case AtomicType::TYPE_UINT64: { case AtomicType::TYPE_UINT64: {
uint64_t uv[ISPC_MAX_NVEC]; uint64_t uv[ISPC_MAX_NVEC];
constExpr->AsUInt64(uv, forceVarying); constExpr->GetValues(uv, forceVarying);
return new ConstExpr(toType, uv, pos); return new ConstExpr(toType, uv, pos);
} }
case AtomicType::TYPE_DOUBLE: { case AtomicType::TYPE_DOUBLE: {
double dv[ISPC_MAX_NVEC]; double dv[ISPC_MAX_NVEC];
constExpr->AsDouble(dv, forceVarying); constExpr->GetValues(dv, forceVarying);
return new ConstExpr(toType, dv, pos); return new ConstExpr(toType, dv, pos);
} }
default: default:

81
expr.h
View File

@@ -409,71 +409,22 @@ public:
Expr *Optimize(); Expr *Optimize();
int EstimateCost() const; int EstimateCost() const;
/** Return the ConstExpr's values as booleans, doing type conversion /** Return the ConstExpr's values as the given pointer type, doing type
from the actual type if needed. If forceVarying is true, then type conversion from the actual type if needed. If forceVarying is
convert to 'varying' so as to always return a number of values true, then type convert to 'varying' so as to always return a
equal to the target vector width into the given pointer. */ number of values equal to the target vector width into the given
int AsBool(bool *, bool forceVarying = false) const; pointer. */
int GetValues(bool *, bool forceVarying = false) const;
/** Return the ConstExpr's values as int8s, doing type conversion int GetValues(int8_t *, bool forceVarying = false) const;
from the actual type if needed. If forceVarying is true, then type int GetValues(uint8_t *, bool forceVarying = false) const;
convert to 'varying' so as to always return a number of values int GetValues(int16_t *, bool forceVarying = false) const;
equal to the target vector width into the given pointer. */ int GetValues(uint16_t *, bool forceVarying = false) const;
int AsInt8(int8_t *, bool forceVarying = false) const; int GetValues(int32_t *, bool forceVarying = false) const;
int GetValues(uint32_t *, bool forceVarying = false) const;
/** Return the ConstExpr's values as uint8s, doing type conversion int GetValues(float *, bool forceVarying = false) const;
from the actual type if needed. If forceVarying is true, then type int GetValues(int64_t *, bool forceVarying = false) const;
convert to 'varying' so as to always return a number of values int GetValues(uint64_t *, bool forceVarying = false) const;
equal to the target vector width into the given pointer. */ int GetValues(double *, bool forceVarying = false) const;
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 number of values in the ConstExpr; should be either 1, /** 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 if it has uniform type, or the target's vector width if it's

View File

@@ -1196,7 +1196,7 @@ lEmitEnumDecls(const std::vector<const EnumType *> &enumTypes, FILE *file) {
const Symbol *e = enumTypes[i]->GetEnumerator(j); const Symbol *e = enumTypes[i]->GetEnumerator(j);
Assert(e->constValue != NULL); Assert(e->constValue != NULL);
unsigned int enumValue; unsigned int enumValue;
int count = e->constValue->AsUInt32(&enumValue); int count = e->constValue->GetValues(&enumValue);
Assert(count == 1); Assert(count == 1);
// Always print an initializer to set the value. We could be // Always print an initializer to set the value. We could be

View File

@@ -2287,7 +2287,7 @@ lFinalizeEnumeratorSymbols(std::vector<Symbol *> &enums,
enums[i]->type = enumType; enums[i]->type = enumType;
if (enums[i]->constValue != NULL) { if (enums[i]->constValue != NULL) {
/* Already has a value, so first update nextVal with it. */ /* 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); AssertPos(enums[i]->pos, count == 1);
++nextVal; ++nextVal;

View File

@@ -0,0 +1,3 @@
// Binary expression with type "const uniform int8" can't represent value.
int8 v = (int8)64 * (int8)32;

View File

@@ -804,7 +804,7 @@ EnumType::GetDIType(llvm::DIDescriptor scope) const {
for (unsigned int i = 0; i < enumerators.size(); ++i) { for (unsigned int i = 0; i < enumerators.size(); ++i) {
unsigned int enumeratorValue; unsigned int enumeratorValue;
Assert(enumerators[i]->constValue != NULL); Assert(enumerators[i]->constValue != NULL);
int count = enumerators[i]->constValue->AsUInt32(&enumeratorValue); int count = enumerators[i]->constValue->GetValues(&enumeratorValue);
Assert(count == 1); Assert(count == 1);
llvm::Value *descriptor = llvm::Value *descriptor =