Skip to content

Draft implementation of real(16), imag(16), complex(32) #27010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions compiler/AST/primitive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ returnInfoReal64(CallExpr* call) {
static QualifiedType
returnInfoComplexField(CallExpr* call) { // for get real/imag primitives
Type *t = call->get(1)->getValType();
if (t == dtComplex[COMPLEX_SIZE_64]) {
if (t == dtComplex[COMPLEX_SIZE_32]) {
return QualifiedType(dtReal[FLOAT_SIZE_16]->refType, QUAL_REF);
} else if (t == dtComplex[COMPLEX_SIZE_64]) {
return QualifiedType(dtReal[FLOAT_SIZE_32]->refType, QUAL_REF);
} else if (t == dtComplex[COMPLEX_SIZE_128]) {
return QualifiedType(dtReal[FLOAT_SIZE_64]->refType, QUAL_REF);
Expand All @@ -156,10 +158,14 @@ returnInfoComplexField(CallExpr* call) { // for get real/imag primitives
static QualifiedType
returnInfoAbs(CallExpr* call) {
Type *t = call->get(1)->getValType();
if (t == dtComplex[COMPLEX_SIZE_64]) {
if (t == dtComplex[COMPLEX_SIZE_32]) {
return QualifiedType(dtReal[FLOAT_SIZE_16], QUAL_VAL);
} else if (t == dtComplex[COMPLEX_SIZE_64]) {
return QualifiedType(dtReal[FLOAT_SIZE_32], QUAL_VAL);
} else if (t == dtComplex[COMPLEX_SIZE_128]) {
return QualifiedType(dtReal[FLOAT_SIZE_64], QUAL_VAL);
} else if (t == dtImag[FLOAT_SIZE_16]) {
return QualifiedType(dtReal[FLOAT_SIZE_16], QUAL_VAL);
} else if (t == dtImag[FLOAT_SIZE_32]) {
return QualifiedType(dtReal[FLOAT_SIZE_32], QUAL_VAL);
} else if (t == dtImag[FLOAT_SIZE_64]) {
Expand Down
18 changes: 18 additions & 0 deletions compiler/AST/symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1862,6 +1862,10 @@ static VarSymbol* new_FloatSymbol(const char* num,
n[j] = '\0';

switch (size) {
case FLOAT_SIZE_16:
// TODO: Is there something more precise
imm.v_float16 = (_Float16)strtof(n, NULL);
break;
case FLOAT_SIZE_32:
imm.v_float32 = strtof(n, NULL);
break;
Expand Down Expand Up @@ -1911,6 +1915,16 @@ VarSymbol *new_RealSymbol(const char *n, IF1_float_type size) {
return new_FloatSymbol(n, size, NUM_KIND_REAL, dtReal[size]);
}

/*
VarSymbol *new_RealSymbol(_Float16 val) {
Immediate imm;
imm.v_float16 = val;
imm.const_kind = NUM_KIND_REAL;
imm.num_index = FLOAT_SIZE_16;
return new_ImmediateSymbol(&imm);
}
*/

VarSymbol *new_RealSymbol(float val) {
Immediate imm;
imm.v_float32 = val;
Expand All @@ -1935,6 +1949,10 @@ VarSymbol *new_ComplexSymbol(const char *n, long double r, long double i,
IF1_complex_type size) {
Immediate imm;
switch (size) {
case COMPLEX_SIZE_32:
imm.v_complex32.r = r;
imm.v_complex32.i = i;
break;
case COMPLEX_SIZE_64:
imm.v_complex64.r = r;
imm.v_complex64.i = i;
Expand Down
40 changes: 31 additions & 9 deletions compiler/AST/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ const char* FunctionType::intentToString(IntentTag intent) {
static const char* builtinTypeName(Type* vt) {
if (vt == dtInt[INT_SIZE_DEFAULT]) return "int";
if (vt == dtUInt[INT_SIZE_DEFAULT]) return "uint";
if (vt == dtReal[COMPLEX_SIZE_DEFAULT]) return "real";
if (vt == dtReal[FLOAT_SIZE_DEFAULT]) return "real";
if (vt == dtBool) return "bool";
if (vt == dtComplex[COMPLEX_SIZE_DEFAULT]) return "complex";
if (vt == dtImag[FLOAT_SIZE_DEFAULT]) return "imag";
Expand Down Expand Up @@ -1200,11 +1200,14 @@ void initPrimitiveTypes() {
INIT_PRIM_UINT( "uint(32)", 32);
INIT_PRIM_UINT( "uint", 64); // default size

INIT_PRIM_REAL( "real(16)", 16);
INIT_PRIM_REAL( "real(32)", 32);

INIT_PRIM_IMAG( "imag(16)", 16);
INIT_PRIM_IMAG( "imag(32)", 32);
INIT_PRIM_IMAG( "imag", 64); // default size

INIT_PRIM_COMPLEX( "complex(32)", 32);
INIT_PRIM_COMPLEX( "complex(64)", 64);
INIT_PRIM_COMPLEX( "complex", 128); // default size

Expand Down Expand Up @@ -1472,21 +1475,24 @@ bool is_signed(Type *t) {
bool is_real_type(Type *t) {
return
t == dtReal[FLOAT_SIZE_64] ||
t == dtReal[FLOAT_SIZE_32];
t == dtReal[FLOAT_SIZE_32] ||
t == dtReal[FLOAT_SIZE_16];
}


bool is_imag_type(Type *t) {
return
t == dtImag[FLOAT_SIZE_64] ||
t == dtImag[FLOAT_SIZE_32];
t == dtImag[FLOAT_SIZE_32] ||
t == dtImag[FLOAT_SIZE_16];
}


bool is_complex_type(Type *t) {
return
t == dtComplex[COMPLEX_SIZE_128] ||
t == dtComplex[COMPLEX_SIZE_64];
t == dtComplex[COMPLEX_SIZE_64] ||
t == dtComplex[COMPLEX_SIZE_32];
}


Expand Down Expand Up @@ -1514,12 +1520,15 @@ int get_width(Type *t) {
t == dtUInt[INT_SIZE_8])
return 8;
if (t == dtInt[INT_SIZE_16] ||
t == dtUInt[INT_SIZE_16])
t == dtUInt[INT_SIZE_16] ||
t == dtReal[FLOAT_SIZE_16] ||
t == dtImag[FLOAT_SIZE_16])
return 16;
if (t == dtInt[INT_SIZE_32] ||
t == dtUInt[INT_SIZE_32] ||
t == dtReal[FLOAT_SIZE_32] ||
t == dtImag[FLOAT_SIZE_32])
t == dtImag[FLOAT_SIZE_32] ||
t == dtComplex[COMPLEX_SIZE_32])
return 32;
if (t == dtInt[INT_SIZE_64] ||
t == dtUInt[INT_SIZE_64] ||
Expand All @@ -1543,7 +1552,12 @@ int get_component_width(Type *t) {
// numbers between -2**width .. 2**width
// will fit exactly in a floating-point representation.
int get_mantissa_width(Type *t) {
// FLOAT_SIZE_16 would have 11 bits of precision
if (t == dtReal[FLOAT_SIZE_16] ||
t == dtImag[FLOAT_SIZE_16] ||
t == dtComplex[COMPLEX_SIZE_32]
)
// mantissa for 32-bit float
return 11;
if (t == dtReal[FLOAT_SIZE_32] ||
t == dtImag[FLOAT_SIZE_32] ||
t == dtComplex[COMPLEX_SIZE_64])
Expand All @@ -1558,8 +1572,13 @@ int get_mantissa_width(Type *t) {
return 0;
}

int get_exponent_width(Type *t) {
// FLOAT_SIZE_16 would have 5 bits of exponent
int get_exponent_width(Type *t) {
if (t == dtReal[FLOAT_SIZE_16] ||
t == dtImag[FLOAT_SIZE_16] ||
t == dtComplex[COMPLEX_SIZE_32]
)
// exponent bits for 32-bit float
return 5;
if (t == dtReal[FLOAT_SIZE_32] ||
t == dtImag[FLOAT_SIZE_32] ||
t == dtComplex[COMPLEX_SIZE_64])
Expand Down Expand Up @@ -2131,12 +2150,15 @@ bool isPrimitiveScalar(Type* type) {
type == dtUInt[INT_SIZE_32] ||
type == dtUInt[INT_SIZE_64] ||

type == dtReal[FLOAT_SIZE_16] ||
type == dtReal[FLOAT_SIZE_32] ||
type == dtReal[FLOAT_SIZE_64] ||

type == dtImag[FLOAT_SIZE_16] ||
type == dtImag[FLOAT_SIZE_32] ||
type == dtImag[FLOAT_SIZE_64] ||

type == dtComplex[COMPLEX_SIZE_32] ||
type == dtComplex[COMPLEX_SIZE_64] ||
type == dtComplex[COMPLEX_SIZE_128]) {

Expand Down
41 changes: 32 additions & 9 deletions compiler/codegen/cg-expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1951,7 +1951,9 @@ GenRet codegenAdd(GenRet a, GenRet b)
if( av.chplType ) a_signed = is_signed(av.chplType);
if( bv.chplType ) b_signed = is_signed(bv.chplType);

if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
if (av.chplType == dtComplex[COMPLEX_SIZE_32]) {
ret = codegenCallExpr("complexAdd32", av, bv);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
ret = codegenCallExpr("complexAdd64", av, bv);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_128]) {
ret = codegenCallExpr("complexAdd128", av, bv);
Expand Down Expand Up @@ -2017,7 +2019,9 @@ GenRet codegenSub(GenRet a, GenRet b)
if( av.chplType ) a_signed = is_signed(av.chplType);
if( bv.chplType ) b_signed = is_signed(bv.chplType);

if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
if (av.chplType == dtComplex[COMPLEX_SIZE_32]) {
ret = codegenCallExpr("complexSubtract32", av, bv);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
ret = codegenCallExpr("complexSubtract64", av, bv);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_128]) {
ret = codegenCallExpr("complexSubtract128", av, bv);
Expand Down Expand Up @@ -2058,7 +2062,9 @@ GenRet codegenNeg(GenRet a)
else {
#ifdef HAVE_LLVM
llvm::Value *value = av.val;
if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
if (av.chplType == dtComplex[COMPLEX_SIZE_32]) {
ret = codegenCallExpr("complexUnaryMinus32", av);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
ret = codegenCallExpr("complexUnaryMinus64", av);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_128]) {
ret = codegenCallExpr("complexUnaryMinus128", av);
Expand Down Expand Up @@ -2098,7 +2104,9 @@ GenRet codegenMul(GenRet a, GenRet b)
bool b_signed = false;
if( av.chplType ) a_signed = is_signed(av.chplType);
if( bv.chplType ) b_signed = is_signed(bv.chplType);
if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
if (av.chplType == dtComplex[COMPLEX_SIZE_32]) {
ret = codegenCallExpr("complexMultiply32", av, bv);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
ret = codegenCallExpr("complexMultiply64", av, bv);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_128]) {
ret = codegenCallExpr("complexMultiply128", av, bv);
Expand Down Expand Up @@ -2132,7 +2140,9 @@ GenRet codegenDiv(GenRet a, GenRet b)
if( info->cfile ) ret.c = "(" + av.c + " / " + bv.c + ")";
else {
#ifdef HAVE_LLVM
if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
if (av.chplType == dtComplex[COMPLEX_SIZE_32]) {
ret = codegenCallExpr("complexDivide32", av, bv);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_64]) {
ret = codegenCallExpr("complexDivide64", av, bv);
} else if (av.chplType == dtComplex[COMPLEX_SIZE_128]) {
ret = codegenCallExpr("complexDivide128", av, bv);
Expand Down Expand Up @@ -2206,7 +2216,8 @@ static GenRet emitFmaForLlvm(GenRet av, GenRet bv, GenRet cv) {
GenInfo* info = gGenInfo;
INT_ASSERT(av.chplType == bv.chplType && bv.chplType == cv.chplType);
INT_ASSERT(av.chplType == dtReal[FLOAT_SIZE_64] ||
av.chplType == dtReal[FLOAT_SIZE_32]);
av.chplType == dtReal[FLOAT_SIZE_32] ||
av.chplType == dtReal[FLOAT_SIZE_16]);
auto ty = av.val->getType();
INT_ASSERT(ty);

Expand Down Expand Up @@ -2258,6 +2269,8 @@ static GenRet emitSqrtCMath(GenRet av) {
ret = codegenCallExpr("chpl_sqrt64", av);
} else if (av.chplType == dtReal[FLOAT_SIZE_32]) {
ret = codegenCallExpr("chpl_sqrt32", av);
} else if (av.chplType == dtReal[FLOAT_SIZE_16]) {
ret = codegenCallExpr("chpl_sqrt16", av);
} else {
INT_FATAL("The sqrt primitive can only evaluate floating point types!");
}
Expand All @@ -2269,7 +2282,8 @@ static GenRet emitSqrtLLVMIntrinsic(GenRet av) {
#ifdef HAVE_LLVM
GenInfo* info = gGenInfo;
INT_ASSERT(av.chplType == dtReal[FLOAT_SIZE_64] ||
av.chplType == dtReal[FLOAT_SIZE_32]);
av.chplType == dtReal[FLOAT_SIZE_32] ||
av.chplType == dtReal[FLOAT_SIZE_16]);
auto ty = av.val->getType();
INT_ASSERT(ty);

Expand Down Expand Up @@ -2305,6 +2319,8 @@ static GenRet emitAbsCMath(GenRet av) {
ret = codegenCallExpr("chpl_fabs64", av);
} else if (av.chplType == dtReal[FLOAT_SIZE_32]) {
ret = codegenCallExpr("chpl_fabs32", av);
} else if (av.chplType == dtReal[FLOAT_SIZE_16]) {
ret = codegenCallExpr("chpl_fabs16", av);
} else {
INT_FATAL("The abs primitive can only evaluate floating point types!");
}
Expand All @@ -2316,7 +2332,8 @@ static GenRet emitAbsLLVMIntrinsic(GenRet av) {
#ifdef HAVE_LLVM
GenInfo* info = gGenInfo;
INT_ASSERT(av.chplType == dtReal[FLOAT_SIZE_64] ||
av.chplType == dtReal[FLOAT_SIZE_32]);
av.chplType == dtReal[FLOAT_SIZE_32] ||
av.chplType == dtReal[FLOAT_SIZE_16]);
auto ty = av.val->getType();
INT_ASSERT(ty);

Expand Down Expand Up @@ -4222,12 +4239,18 @@ static GenRet codegen_prim_get_real(GenRet arg, Type* type, bool real) {
} else {
realOrImag = "Imag";
}
if (type == dtComplex[COMPLEX_SIZE_64]->refType) {
if (type == dtComplex[COMPLEX_SIZE_32]->refType) {
snprintf(fnName, 21, "complex32Get%sRef", realOrImag);
ret = codegenCallExpr(fnName, arg);
} else if (type == dtComplex[COMPLEX_SIZE_64]->refType) {
snprintf(fnName, 21, "complex64Get%sRef", realOrImag);
ret = codegenCallExpr(fnName, arg);
} else if (type == dtComplex[COMPLEX_SIZE_128]->refType) {
snprintf(fnName, 21, "complex128Get%sRef", realOrImag);
ret = codegenCallExpr(fnName, arg);
} else if (type == dtComplex[COMPLEX_SIZE_32]) {
snprintf(fnName, 21, "complex32Get%sRef", realOrImag);
ret = codegenCallExpr(fnName, codegenAddrOf(arg));
} else if (type == dtComplex[COMPLEX_SIZE_64]) {
snprintf(fnName, 21, "complex64Get%sRef", realOrImag);
ret = codegenCallExpr(fnName, codegenAddrOf(arg));
Expand Down
40 changes: 36 additions & 4 deletions compiler/codegen/cg-symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ llvm::Value* codegenImmediateLLVM(Immediate* i)
case NUM_KIND_REAL:
case NUM_KIND_IMAG:
switch(i->num_index) {
case FLOAT_SIZE_16:
ret = llvm::ConstantFP::get(
llvm::Type::getFloatTy(info->module->getContext()),
i->v_float16);
break;
case FLOAT_SIZE_32:
ret = llvm::ConstantFP::get(
llvm::Type::getFloatTy(info->module->getContext()),
Expand All @@ -437,6 +442,19 @@ llvm::Value* codegenImmediateLLVM(Immediate* i)
break;
case NUM_KIND_COMPLEX:
switch(i->num_index) {
case COMPLEX_SIZE_32: {
std::vector<llvm::Constant *> elements(2);
elements[0] = llvm::ConstantFP::get(
llvm::Type::getFloatTy(info->module->getContext()),
i->v_complex32.r);
elements[1] = llvm::ConstantFP::get(
llvm::Type::getFloatTy(info->module->getContext()),
i->v_complex32.i);
ret = llvm::ConstantStruct::get(
llvm::cast<llvm::StructType>(getTypeLLVM("_complex32")),
elements);
break;
}
case COMPLEX_SIZE_64: {
std::vector<llvm::Constant *> elements(2);
elements[0] = llvm::ConstantFP::get(
Expand Down Expand Up @@ -575,6 +593,9 @@ GenRet VarSymbol::codegenVarSymbol(bool lhsInSetReference) {
double value = immediate->real_value();
const char* castString = NULL;
switch (immediate->num_index) {
case FLOAT_SIZE_16:
castString = "REAL16(";
break;
case FLOAT_SIZE_32:
castString = "REAL32(";
break;
Expand All @@ -592,6 +613,10 @@ GenRet VarSymbol::codegenVarSymbol(bool lhsInSetReference) {
const char* chplComplexN = NULL;

switch(immediate->num_index) {
case COMPLEX_SIZE_32:
flType = FLOAT_SIZE_16;
chplComplexN = "_chpl_complex32";
break;
case COMPLEX_SIZE_64:
flType = FLOAT_SIZE_32;
chplComplexN = "_chpl_complex64";
Expand Down Expand Up @@ -1651,10 +1676,13 @@ void TypeSymbol::codegenMetadata() {
if (is_imag_type(type)) {
// At present, imaginary often aliases with real,
// so make real the parent of imaginary.
INT_ASSERT(type == dtImag[FLOAT_SIZE_32] ||
INT_ASSERT(type == dtImag[FLOAT_SIZE_16] ||
type == dtImag[FLOAT_SIZE_32] ||
type == dtImag[FLOAT_SIZE_64]);
TypeSymbol *re;
if (type == dtImag[FLOAT_SIZE_32]) {
if (type == dtImag[FLOAT_SIZE_16]) {
re = dtReal[FLOAT_SIZE_16]->symbol;
} else if (type == dtImag[FLOAT_SIZE_32]) {
re = dtReal[FLOAT_SIZE_32]->symbol;
} else {
re = dtReal[FLOAT_SIZE_64]->symbol;
Expand Down Expand Up @@ -1695,11 +1723,15 @@ void TypeSymbol::codegenCplxMetadata() {
llvm::LLVMContext& ctx = info->module->getContext();
const llvm::DataLayout& dl = info->module->getDataLayout();

INT_ASSERT(type == dtComplex[COMPLEX_SIZE_64] ||
INT_ASSERT(type == dtComplex[COMPLEX_SIZE_32] ||
type == dtComplex[COMPLEX_SIZE_64] ||
type == dtComplex[COMPLEX_SIZE_128]);

TypeSymbol *re, *im;
if (type == dtComplex[COMPLEX_SIZE_64]) {
if (type == dtComplex[COMPLEX_SIZE_32]) {
re = dtReal[FLOAT_SIZE_16]->symbol;
im = dtImag[FLOAT_SIZE_16]->symbol;
} else if (type == dtComplex[COMPLEX_SIZE_64]) {
re = dtReal[FLOAT_SIZE_32]->symbol;
im = dtImag[FLOAT_SIZE_32]->symbol;
} else {
Expand Down
Loading
Loading