Add support for int8/int16 types. Addresses issues #9 and #42.

This commit is contained in:
Matt Pharr
2011-07-21 06:57:40 +01:00
parent 2d573acd17
commit bba7211654
64 changed files with 2317 additions and 885 deletions

553
expr.cpp
View File

@@ -93,6 +93,10 @@ lMaybeIssuePrecisionWarning(const AtomicType *toAtomicType,
SourcePos pos, const char *errorMsgBase) {
switch (toAtomicType->basicType) {
case AtomicType::TYPE_BOOL:
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_UINT8:
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_UINT16:
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_UINT32:
case AtomicType::TYPE_FLOAT:
@@ -101,6 +105,10 @@ lMaybeIssuePrecisionWarning(const AtomicType *toAtomicType,
case AtomicType::TYPE_DOUBLE:
if ((int)toAtomicType->basicType < (int)fromAtomicType->basicType &&
toAtomicType->basicType != AtomicType::TYPE_BOOL &&
!(toAtomicType->basicType == AtomicType::TYPE_INT8 &&
fromAtomicType->basicType == AtomicType::TYPE_UINT8) &&
!(toAtomicType->basicType == AtomicType::TYPE_INT16 &&
fromAtomicType->basicType == AtomicType::TYPE_UINT16) &&
!(toAtomicType->basicType == AtomicType::TYPE_INT32 &&
fromAtomicType->basicType == AtomicType::TYPE_UINT32) &&
!(toAtomicType->basicType == AtomicType::TYPE_INT64 &&
@@ -363,15 +371,33 @@ lLLVMConstantValue(const Type *type, llvm::LLVMContext *ctx, double value) {
return (value != 0.) ? LLVMTrue : LLVMFalse;
else
return LLVMBoolVector(value != 0.);
case AtomicType::TYPE_UINT32: {
case AtomicType::TYPE_INT8: {
int i = (int)value;
assert((double)i == value);
return isUniform ? LLVMInt8(i) : LLVMInt8Vector(i);
}
case AtomicType::TYPE_UINT8: {
unsigned int i = (unsigned int)value;
return isUniform ? LLVMUInt32(i) : LLVMUInt32Vector(i);
return isUniform ? LLVMUInt8(i) : LLVMUInt8Vector(i);
}
case AtomicType::TYPE_INT16: {
int i = (int)value;
assert((double)i == value);
return isUniform ? LLVMInt16(i) : LLVMInt16Vector(i);
}
case AtomicType::TYPE_UINT16: {
unsigned int i = (unsigned int)value;
return isUniform ? LLVMUInt16(i) : LLVMUInt16Vector(i);
}
case AtomicType::TYPE_INT32: {
int i = (int)value;
assert((double)i == value);
return isUniform ? LLVMInt32(i) : LLVMInt32Vector(i);
}
case AtomicType::TYPE_UINT32: {
unsigned int i = (unsigned int)value;
return isUniform ? LLVMUInt32(i) : LLVMUInt32Vector(i);
}
case AtomicType::TYPE_FLOAT:
return isUniform ? LLVMFloat((float)value) :
LLVMFloatVector((float)value);
@@ -590,14 +616,13 @@ UnaryExpr::Optimize() {
const Type *type = constExpr->GetType();
bool isEnumType = dynamic_cast<const EnumType *>(type) != NULL;
if (type == AtomicType::UniformInt64 ||
type == AtomicType::VaryingInt64 ||
type == AtomicType::UniformUInt64 ||
type == AtomicType::VaryingUInt64 ||
type == AtomicType::UniformConstInt64 ||
type == AtomicType::VaryingConstInt64 ||
type == AtomicType::UniformConstUInt64 ||
type == AtomicType::VaryingConstUInt64)
const Type *baseType = type->GetAsNonConstType()->GetAsUniformType();
if (baseType == AtomicType::UniformInt8 ||
baseType == AtomicType::UniformUInt8 ||
baseType == AtomicType::UniformInt16 ||
baseType == AtomicType::UniformUInt16 ||
baseType == AtomicType::UniformInt64 ||
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;
@@ -3058,6 +3083,86 @@ MemberExpr::getCandidateNearMatches() const {
///////////////////////////////////////////////////////////////////////////
// ConstExpr
ConstExpr::ConstExpr(const Type *t, int8_t i, SourcePos p)
: Expr(p) {
type = t;
type = type->GetAsConstType();
assert(type == AtomicType::UniformConstInt8);
int8Val[0] = i;
}
ConstExpr::ConstExpr(const Type *t, int8_t *i, SourcePos p)
: Expr(p) {
type = t;
type = type->GetAsConstType();
assert(type == AtomicType::UniformConstInt8 ||
type == AtomicType::VaryingConstInt8);
for (int j = 0; j < Count(); ++j)
int8Val[j] = i[j];
}
ConstExpr::ConstExpr(const Type *t, uint8_t u, SourcePos p)
: Expr(p) {
type = t;
type = type->GetAsConstType();
assert(type == AtomicType::UniformUInt8);
uint8Val[0] = u;
}
ConstExpr::ConstExpr(const Type *t, uint8_t *u, SourcePos p)
: Expr(p) {
type = t;
type = type->GetAsConstType();
assert(type == AtomicType::UniformConstUInt8 ||
type == AtomicType::VaryingConstUInt8);
for (int j = 0; j < Count(); ++j)
uint8Val[j] = u[j];
}
ConstExpr::ConstExpr(const Type *t, int16_t i, SourcePos p)
: Expr(p) {
type = t;
type = type->GetAsConstType();
assert(type == AtomicType::UniformConstInt16);
int16Val[0] = i;
}
ConstExpr::ConstExpr(const Type *t, int16_t *i, SourcePos p)
: Expr(p) {
type = t;
type = type->GetAsConstType();
assert(type == AtomicType::UniformConstInt16 ||
type == AtomicType::VaryingConstInt16);
for (int j = 0; j < Count(); ++j)
int16Val[j] = i[j];
}
ConstExpr::ConstExpr(const Type *t, uint16_t u, SourcePos p)
: Expr(p) {
type = t;
type = type->GetAsConstType();
assert(type == AtomicType::UniformUInt16);
uint16Val[0] = u;
}
ConstExpr::ConstExpr(const Type *t, uint16_t *u, SourcePos p)
: Expr(p) {
type = t;
type = type->GetAsConstType();
assert(type == AtomicType::UniformConstUInt16 ||
type == AtomicType::VaryingConstUInt16);
for (int j = 0; j < Count(); ++j)
uint16Val[j] = u[j];
}
ConstExpr::ConstExpr(const Type *t, int32_t i, SourcePos p)
: Expr(p) {
type = t;
@@ -3212,6 +3317,22 @@ ConstExpr::ConstExpr(ConstExpr *old, double *v)
for (int i = 0; i < Count(); ++i)
boolVal[i] = (v[i] != 0.);
break;
case AtomicType::TYPE_INT8:
for (int i = 0; i < Count(); ++i)
int8Val[i] = (int)v[i];
break;
case AtomicType::TYPE_UINT8:
for (int i = 0; i < Count(); ++i)
uint8Val[i] = (unsigned int)v[i];
break;
case AtomicType::TYPE_INT16:
for (int i = 0; i < Count(); ++i)
int16Val[i] = (int)v[i];
break;
case AtomicType::TYPE_UINT16:
for (int i = 0; i < Count(); ++i)
uint16Val[i] = (unsigned int)v[i];
break;
case AtomicType::TYPE_INT32:
for (int i = 0; i < Count(); ++i)
int32Val[i] = (int)v[i];
@@ -3270,6 +3391,18 @@ ConstExpr::GetValue(FunctionEmitContext *ctx) const {
return LLVMBoolVector(boolVal);
else
return boolVal[0] ? LLVMTrue : LLVMFalse;
case AtomicType::TYPE_INT8:
return isVarying ? LLVMInt8Vector(int8Val) :
LLVMInt8(int8Val[0]);
case AtomicType::TYPE_UINT8:
return isVarying ? LLVMUInt8Vector(uint8Val) :
LLVMUInt8(uint8Val[0]);
case AtomicType::TYPE_INT16:
return isVarying ? LLVMInt16Vector(int16Val) :
LLVMInt16(int16Val[0]);
case AtomicType::TYPE_UINT16:
return isVarying ? LLVMUInt16Vector(uint16Val) :
LLVMUInt16(uint16Val[0]);
case AtomicType::TYPE_INT32:
return isVarying ? LLVMInt32Vector(int32Val) :
LLVMInt32(int32Val[0]);
@@ -3351,6 +3484,10 @@ int
ConstExpr::AsInt64(int64_t *ip, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, ip, Count(), forceVarying); break;
@@ -3368,6 +3505,10 @@ int
ConstExpr::AsUInt64(uint64_t *up, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, up, Count(), forceVarying); break;
@@ -3385,6 +3526,10 @@ int
ConstExpr::AsDouble(double *d, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, d, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, d, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, d, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, d, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, d, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, d, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, d, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, d, Count(), forceVarying); break;
@@ -3402,6 +3547,10 @@ int
ConstExpr::AsFloat(float *fp, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, fp, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, fp, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, fp, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, fp, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, fp, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, fp, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, fp, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, fp, Count(), forceVarying); break;
@@ -3419,6 +3568,10 @@ int
ConstExpr::AsBool(bool *b, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, b, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, b, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, b, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, b, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, b, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, b, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, b, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, b, Count(), forceVarying); break;
@@ -3432,10 +3585,98 @@ ConstExpr::AsBool(bool *b, bool forceVarying) const {
}
int
ConstExpr::AsInt8(int8_t *ip, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_DOUBLE: lConvert(doubleVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT64: lConvert(int64Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT64: lConvert(uint64Val, ip, Count(), forceVarying); break;
default:
FATAL("unimplemented const type");
}
return Count();
}
int
ConstExpr::AsUInt8(uint8_t *up, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_DOUBLE: lConvert(doubleVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT64: lConvert(int64Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT64: lConvert(uint64Val, up, Count(), forceVarying); break;
default:
FATAL("unimplemented const type");
}
return Count();
}
int
ConstExpr::AsInt16(int16_t *ip, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_DOUBLE: lConvert(doubleVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT64: lConvert(int64Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT64: lConvert(uint64Val, ip, Count(), forceVarying); break;
default:
FATAL("unimplemented const type");
}
return Count();
}
int
ConstExpr::AsUInt16(uint16_t *up, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_DOUBLE: lConvert(doubleVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT64: lConvert(int64Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT64: lConvert(uint64Val, up, Count(), forceVarying); break;
default:
FATAL("unimplemented const type");
}
return Count();
}
int
ConstExpr::AsInt32(int32_t *ip, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, ip, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, ip, Count(), forceVarying); break;
@@ -3453,6 +3694,10 @@ int
ConstExpr::AsUInt32(uint32_t *up, bool forceVarying) const {
switch (getBasicType()) {
case AtomicType::TYPE_BOOL: lConvert(boolVal, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT8: lConvert(int8Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT8: lConvert(uint8Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT16: lConvert(int16Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT16: lConvert(uint16Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_INT32: lConvert(int32Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_UINT32: lConvert(uint32Val, up, Count(), forceVarying); break;
case AtomicType::TYPE_FLOAT: lConvert(floatVal, up, Count(), forceVarying); break;
@@ -3488,6 +3733,40 @@ ConstExpr::GetConstant(const Type *type) const {
else
return LLVMBoolVector(bv);
}
else if (type == AtomicType::UniformInt8 || type == AtomicType::VaryingInt8) {
int8_t iv[ISPC_MAX_NVEC];
AsInt8(iv, type->IsVaryingType());
if (type->IsUniformType())
return LLVMInt8(iv[0]);
else
return LLVMInt8Vector(iv);
}
else if (type == AtomicType::UniformUInt8 || type == AtomicType::VaryingUInt8 ||
dynamic_cast<const EnumType *>(type) != NULL) {
uint8_t uiv[ISPC_MAX_NVEC];
AsUInt8(uiv, type->IsVaryingType());
if (type->IsUniformType())
return LLVMUInt8(uiv[0]);
else
return LLVMUInt8Vector(uiv);
}
else if (type == AtomicType::UniformInt16 || type == AtomicType::VaryingInt16) {
int16_t iv[ISPC_MAX_NVEC];
AsInt16(iv, type->IsVaryingType());
if (type->IsUniformType())
return LLVMInt16(iv[0]);
else
return LLVMInt16Vector(iv);
}
else if (type == AtomicType::UniformUInt16 || type == AtomicType::VaryingUInt16 ||
dynamic_cast<const EnumType *>(type) != NULL) {
uint16_t uiv[ISPC_MAX_NVEC];
AsUInt16(uiv, type->IsVaryingType());
if (type->IsUniformType())
return LLVMUInt16(uiv[0]);
else
return LLVMUInt16Vector(uiv);
}
else if (type == AtomicType::UniformInt32 || type == AtomicType::VaryingInt32) {
int32_t iv[ISPC_MAX_NVEC];
AsInt32(iv, type->IsVaryingType());
@@ -3564,6 +3843,18 @@ ConstExpr::Print() const {
case AtomicType::TYPE_BOOL:
printf("%s", boolVal[i] ? "true" : "false");
break;
case AtomicType::TYPE_INT8:
printf("%d", (int)int8Val[i]);
break;
case AtomicType::TYPE_UINT8:
printf("%u", (int)uint8Val[i]);
break;
case AtomicType::TYPE_INT16:
printf("%d", (int)int16Val[i]);
break;
case AtomicType::TYPE_UINT16:
printf("%u", (int)uint16Val[i]);
break;
case AtomicType::TYPE_INT32:
printf("%d", int32Val[i]);
break;
@@ -3637,11 +3928,15 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
cast = ctx->CastInst(llvm::Instruction::UIToFP, // unsigned int
exprVal, targetType, "bool2float");
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_INT64:
cast = ctx->CastInst(llvm::Instruction::SIToFP, // signed int to float
exprVal, targetType, "int2float");
break;
case AtomicType::TYPE_UINT8:
case AtomicType::TYPE_UINT16:
case AtomicType::TYPE_UINT32:
case AtomicType::TYPE_UINT64:
if (fromType->IsVaryingType())
@@ -3675,11 +3970,15 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
cast = ctx->CastInst(llvm::Instruction::UIToFP, // unsigned int to double
exprVal, targetType, "bool2double");
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_INT64:
cast = ctx->CastInst(llvm::Instruction::SIToFP, // signed int
exprVal, targetType, "int2double");
break;
case AtomicType::TYPE_UINT8:
case AtomicType::TYPE_UINT16:
case AtomicType::TYPE_UINT32:
case AtomicType::TYPE_UINT64:
if (fromType->IsVaryingType())
@@ -3699,6 +3998,170 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
}
break;
}
case AtomicType::TYPE_INT8: {
LLVM_TYPE_CONST llvm::Type *targetType =
fromType->IsUniformType() ? LLVMTypes::Int8Type :
LLVMTypes::Int8VectorType;
switch (fromType->basicType) {
case AtomicType::TYPE_BOOL:
if (fromType->IsVaryingType() &&
LLVMTypes::BoolVectorType == LLVMTypes::Int32VectorType)
exprVal = ctx->TruncInst(exprVal, LLVMTypes::Int1VectorType, "bool_to_i1");
cast = ctx->ZExtInst(exprVal, targetType, "bool2int");
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_UINT8:
cast = exprVal;
break;
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_UINT16:
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_UINT32:
case AtomicType::TYPE_INT64:
case AtomicType::TYPE_UINT64:
cast = ctx->TruncInst(exprVal, targetType, "int64_to_int8");
break;
case AtomicType::TYPE_FLOAT:
cast = ctx->CastInst(llvm::Instruction::FPToSI, // signed int
exprVal, targetType, "float2int");
break;
case AtomicType::TYPE_DOUBLE:
cast = ctx->CastInst(llvm::Instruction::FPToSI, // signed int
exprVal, targetType, "double2int");
break;
default:
FATAL("unimplemented");
}
break;
}
case AtomicType::TYPE_UINT8: {
LLVM_TYPE_CONST llvm::Type *targetType =
fromType->IsUniformType() ? LLVMTypes::Int8Type :
LLVMTypes::Int8VectorType;
switch (fromType->basicType) {
case AtomicType::TYPE_BOOL:
if (fromType->IsVaryingType() &&
LLVMTypes::BoolVectorType == LLVMTypes::Int32VectorType)
exprVal = ctx->TruncInst(exprVal, LLVMTypes::Int1VectorType, "bool_to_i1");
cast = ctx->ZExtInst(exprVal, targetType, "bool2uint");
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_UINT8:
cast = exprVal;
break;
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_UINT16:
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_UINT32:
case AtomicType::TYPE_INT64:
case AtomicType::TYPE_UINT64:
cast = ctx->TruncInst(exprVal, targetType, "int64_to_uint8");
break;
case AtomicType::TYPE_FLOAT:
if (fromType->IsVaryingType())
PerformanceWarning(pos, "Conversion from float to unsigned int is slow. "
"Use \"int\" if possible");
cast = ctx->CastInst(llvm::Instruction::FPToUI, // unsigned int
exprVal, targetType, "float2uint");
break;
case AtomicType::TYPE_DOUBLE:
if (fromType->IsVaryingType())
PerformanceWarning(pos, "Conversion from double to unsigned int is slow. "
"Use \"int\" if possible");
cast = ctx->CastInst(llvm::Instruction::FPToUI, // unsigned int
exprVal, targetType, "double2uint");
break;
default:
FATAL("unimplemented");
}
break;
}
case AtomicType::TYPE_INT16: {
LLVM_TYPE_CONST llvm::Type *targetType =
fromType->IsUniformType() ? LLVMTypes::Int16Type :
LLVMTypes::Int16VectorType;
switch (fromType->basicType) {
case AtomicType::TYPE_BOOL:
if (fromType->IsVaryingType() &&
LLVMTypes::BoolVectorType == LLVMTypes::Int32VectorType)
exprVal = ctx->TruncInst(exprVal, LLVMTypes::Int1VectorType, "bool_to_i1");
cast = ctx->ZExtInst(exprVal, targetType, "bool2int");
break;
case AtomicType::TYPE_INT8:
cast = ctx->SExtInst(exprVal, targetType, "int2int16");
break;
case AtomicType::TYPE_UINT8:
cast = ctx->ZExtInst(exprVal, targetType, "uint2uint16");
break;
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_UINT16:
cast = exprVal;
break;
case AtomicType::TYPE_FLOAT:
cast = ctx->CastInst(llvm::Instruction::FPToSI, // signed int
exprVal, targetType, "float2int");
break;
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_UINT32:
case AtomicType::TYPE_INT64:
case AtomicType::TYPE_UINT64:
cast = ctx->TruncInst(exprVal, targetType, "int64_to_int16");
break;
case AtomicType::TYPE_DOUBLE:
cast = ctx->CastInst(llvm::Instruction::FPToSI, // signed int
exprVal, targetType, "double2int");
break;
default:
FATAL("unimplemented");
}
break;
}
case AtomicType::TYPE_UINT16: {
LLVM_TYPE_CONST llvm::Type *targetType =
fromType->IsUniformType() ? LLVMTypes::Int16Type :
LLVMTypes::Int16VectorType;
switch (fromType->basicType) {
case AtomicType::TYPE_BOOL:
if (fromType->IsVaryingType() &&
LLVMTypes::BoolVectorType == LLVMTypes::Int32VectorType)
exprVal = ctx->TruncInst(exprVal, LLVMTypes::Int1VectorType, "bool_to_i1");
cast = ctx->ZExtInst(exprVal, targetType, "bool2uint16");
break;
case AtomicType::TYPE_INT8:
cast = ctx->SExtInst(exprVal, targetType, "uint2uint16");
break;
case AtomicType::TYPE_UINT8:
cast = ctx->ZExtInst(exprVal, targetType, "uint2uint16");
break;
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_UINT16:
cast = exprVal;
break;
case AtomicType::TYPE_FLOAT:
if (fromType->IsVaryingType())
PerformanceWarning(pos, "Conversion from float to unsigned int is slow. "
"Use \"int\" if possible");
cast = ctx->CastInst(llvm::Instruction::FPToUI, // unsigned int
exprVal, targetType, "float2uint");
break;
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_UINT32:
case AtomicType::TYPE_INT64:
case AtomicType::TYPE_UINT64:
cast = ctx->TruncInst(exprVal, targetType, "int64_to_uint16");
break;
case AtomicType::TYPE_DOUBLE:
if (fromType->IsVaryingType())
PerformanceWarning(pos, "Conversion from double to unsigned int is slow. "
"Use \"int\" if possible");
cast = ctx->CastInst(llvm::Instruction::FPToUI, // unsigned int
exprVal, targetType, "double2uint");
break;
default:
FATAL("unimplemented");
}
break;
}
case AtomicType::TYPE_INT32: {
LLVM_TYPE_CONST llvm::Type *targetType =
fromType->IsUniformType() ? LLVMTypes::Int32Type :
@@ -3710,6 +4173,14 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
exprVal = ctx->TruncInst(exprVal, LLVMTypes::Int1VectorType, "bool_to_i1");
cast = ctx->ZExtInst(exprVal, targetType, "bool2int");
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_INT16:
cast = ctx->SExtInst(exprVal, targetType, "int2int32");
break;
case AtomicType::TYPE_UINT8:
case AtomicType::TYPE_UINT16:
cast = ctx->ZExtInst(exprVal, targetType, "uint2uint32");
break;
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_UINT32:
cast = exprVal;
@@ -3742,6 +4213,14 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
exprVal = ctx->TruncInst(exprVal, LLVMTypes::Int1VectorType, "bool_to_i1");
cast = ctx->ZExtInst(exprVal, targetType, "bool2uint");
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_INT16:
cast = ctx->SExtInst(exprVal, targetType, "uint2uint");
break;
case AtomicType::TYPE_UINT8:
case AtomicType::TYPE_UINT16:
cast = ctx->ZExtInst(exprVal, targetType, "uint2uint");
break;
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_UINT32:
cast = exprVal;
@@ -3780,11 +4259,15 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
exprVal = ctx->TruncInst(exprVal, LLVMTypes::Int1VectorType, "bool_to_i1");
cast = ctx->ZExtInst(exprVal, targetType, "bool2int64");
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_INT32:
cast = ctx->SExtInst(exprVal, targetType, "int32_to_int64");
cast = ctx->SExtInst(exprVal, targetType, "int_to_int64");
break;
case AtomicType::TYPE_UINT8:
case AtomicType::TYPE_UINT16:
case AtomicType::TYPE_UINT32:
cast = ctx->ZExtInst(exprVal, targetType, "uint32_to_int64");
cast = ctx->ZExtInst(exprVal, targetType, "uint_to_int64");
break;
case AtomicType::TYPE_FLOAT:
cast = ctx->CastInst(llvm::Instruction::FPToSI, // signed int
@@ -3796,7 +4279,7 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
break;
case AtomicType::TYPE_DOUBLE:
cast = ctx->CastInst(llvm::Instruction::FPToSI, // signed int
exprVal, targetType, "double2int");
exprVal, targetType, "double2int64");
break;
default:
FATAL("unimplemented");
@@ -3814,11 +4297,15 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
exprVal = ctx->TruncInst(exprVal, LLVMTypes::Int1VectorType, "bool_to_i1");
cast = ctx->ZExtInst(exprVal, targetType, "bool2uint");
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_INT32:
cast = ctx->SExtInst(exprVal, targetType, "int32_to_uint64");
cast = ctx->SExtInst(exprVal, targetType, "int_to_uint64");
break;
case AtomicType::TYPE_UINT8:
case AtomicType::TYPE_UINT16:
case AtomicType::TYPE_UINT32:
cast = ctx->ZExtInst(exprVal, targetType, "uint32_to_uint64");
cast = ctx->ZExtInst(exprVal, targetType, "uint_to_uint64");
break;
case AtomicType::TYPE_FLOAT:
if (fromType->IsVaryingType())
@@ -3848,6 +4335,22 @@ lTypeConvAtomic(FunctionEmitContext *ctx, llvm::Value *exprVal,
case AtomicType::TYPE_BOOL:
cast = exprVal;
break;
case AtomicType::TYPE_INT8:
case AtomicType::TYPE_UINT8: {
llvm::Value *zero = fromType->IsUniformType() ? (llvm::Value *)LLVMInt8(0) :
(llvm::Value *)LLVMInt8Vector((int8_t)0);
cast = ctx->CmpInst(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_NE,
exprVal, zero, "cmpi0");
break;
}
case AtomicType::TYPE_INT16:
case AtomicType::TYPE_UINT16: {
llvm::Value *zero = fromType->IsUniformType() ? (llvm::Value *)LLVMInt16(0) :
(llvm::Value *)LLVMInt16Vector((int16_t)0);
cast = ctx->CmpInst(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_NE,
exprVal, zero, "cmpi0");
break;
}
case AtomicType::TYPE_INT32:
case AtomicType::TYPE_UINT32: {
llvm::Value *zero = fromType->IsUniformType() ? (llvm::Value *)LLVMInt32(0) :
@@ -4195,6 +4698,26 @@ TypeCastExpr::Optimize() {
constExpr->AsBool(bv, forceVarying);
return new ConstExpr(toType, bv, pos);
}
case AtomicType::TYPE_INT8: {
int8_t iv[ISPC_MAX_NVEC];
constExpr->AsInt8(iv, forceVarying);
return new ConstExpr(toType, iv, pos);
}
case AtomicType::TYPE_UINT8: {
uint8_t uv[ISPC_MAX_NVEC];
constExpr->AsUInt8(uv, forceVarying);
return new ConstExpr(toType, uv, pos);
}
case AtomicType::TYPE_INT16: {
int16_t iv[ISPC_MAX_NVEC];
constExpr->AsInt16(iv, forceVarying);
return new ConstExpr(toType, iv, pos);
}
case AtomicType::TYPE_UINT16: {
uint16_t uv[ISPC_MAX_NVEC];
constExpr->AsUInt16(uv, forceVarying);
return new ConstExpr(toType, uv, pos);
}
case AtomicType::TYPE_INT32: {
int32_t iv[ISPC_MAX_NVEC];
constExpr->AsInt32(iv, forceVarying);