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:
2
ast.cpp
2
ast.cpp
@@ -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
445
expr.cpp
@@ -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
81
expr.h
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
2
parse.yy
2
parse.yy
@@ -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;
|
||||||
|
|
||||||
|
|||||||
3
tests_errors/const-too-large.ispc
Normal file
3
tests_errors/const-too-large.ispc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Binary expression with type "const uniform int8" can't represent value.
|
||||||
|
|
||||||
|
int8 v = (int8)64 * (int8)32;
|
||||||
2
type.cpp
2
type.cpp
@@ -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 =
|
||||||
|
|||||||
Reference in New Issue
Block a user