Skip to content
Merged
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
19 changes: 12 additions & 7 deletions include/clspv/Option.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,25 @@ inline bool LanguageUsesGenericAddressSpace() {
clspv::FeatureMacro::__opencl_c_generic_address_space) > 0);
}

enum class RoundingModeRTE : uint32_t {
enum class FloatingPointType : uint32_t {
fp16,
fp32,
fp64,
};

// Returns true when the execution mode RoundingModeRTE should be set for a
// floating point type.
bool ExecutionModeRoundingModeRTE(RoundingModeRTE rm);
bool ExecutionModeRoundingModeRTE(FloatingPointType rm);

enum class DenormMode : uint32_t {
Comment thread
rjodinchr marked this conversation as resolved.
error,
preserve,
flush_to_zero,
unspecified,
};

// Returns the execution mode for a floating point type.
DenormMode ExecutionModeDenorm(FloatingPointType fpty);

// Return the SPIR-V binary version
enum class SPIRVVersion : uint32_t {
Expand Down Expand Up @@ -319,11 +329,6 @@ bool UntypedPointers();
// Returns true if untyped pointers are supported in aspace.
bool UntypedPointerAddressSpace(unsigned aspace);

enum class SpvKhrFma : uint32_t {
fp16,
fp32,
fp64,
};
// Returns true if OpFmaKHR is supported for the type size.
bool SupportsFmaKHR(uint32_t scalarSizeInBits);

Expand Down
82 changes: 77 additions & 5 deletions lib/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ static llvm::cl::opt<bool> cl_single_precision_constants(
llvm::cl::desc("Treat double precision floating-point constant as single "
"precision constant."));

// This option has not effect. Mainly because of lack of expresiveness. Instead
// use `-denorm-preserve` and `-denorm-flush-to-zero`.
static llvm::cl::opt<bool> cl_denorms_are_zero(
"cl-denorms-are-zero", llvm::cl::init(false),
Comment thread
rjodinchr marked this conversation as resolved.
llvm::cl::desc("If specified, denormalized floating point numbers may be "
Expand Down Expand Up @@ -317,8 +319,52 @@ int SetCompilerInstanceOptions(
instance.getLangOpts().NativeHalfType = true;
instance.getLangOpts().NativeHalfArgsAndReturns = true;
}
instance.getCodeGenOpts().FPDenormalMode = llvm::DenormalMode::getDynamic();
instance.getCodeGenOpts().FP32DenormalMode = llvm::DenormalMode::getDynamic();
// FP32 denormal mode
switch (clspv::Option::ExecutionModeDenorm(
clspv::Option::FloatingPointType::fp32)) {
case clspv::Option::DenormMode::preserve:
instance.getCodeGenOpts().FP32DenormalMode = llvm::DenormalMode::getIEEE();
break;
case clspv::Option::DenormMode::flush_to_zero:
instance.getCodeGenOpts().FP32DenormalMode =
llvm::DenormalMode::getPreserveSign();
break;
case clspv::Option::DenormMode::unspecified:
instance.getCodeGenOpts().FP32DenormalMode =
llvm::DenormalMode::getDynamic();
break;
case clspv::Option::DenormMode::error:
llvm_unreachable("Invalid DenormMode");
}

// FPDenormalMode (for 16 and 64)
clspv::Option::DenormMode mode = clspv::Option::DenormMode::error;
auto modefp16 = clspv::Option::ExecutionModeDenorm(
clspv::Option::FloatingPointType::fp16);
auto modefp64 = clspv::Option::ExecutionModeDenorm(
clspv::Option::FloatingPointType::fp64);
if (modefp16 == modefp64) {
mode = modefp16;
} else if (modefp16 == clspv::Option::DenormMode::unspecified) {
mode = modefp64;
} else if (modefp64 == clspv::Option::DenormMode::unspecified) {
mode = modefp16;
}
switch (mode) {
case clspv::Option::DenormMode::preserve:
instance.getCodeGenOpts().FPDenormalMode = llvm::DenormalMode::getIEEE();
break;
case clspv::Option::DenormMode::flush_to_zero:
instance.getCodeGenOpts().FPDenormalMode =
llvm::DenormalMode::getPreserveSign();
break;
case clspv::Option::DenormMode::unspecified:
instance.getCodeGenOpts().FPDenormalMode = llvm::DenormalMode::getDynamic();
break;
case clspv::Option::DenormMode::error:
llvm_unreachable("Invalid DenormMode");
}

instance.getCodeGenOpts().StackRealignment = true;
instance.getCodeGenOpts().SimplifyLibCalls = false;
instance.getCodeGenOpts().EmitOpenCLArgMetadata = false;
Expand All @@ -341,7 +387,6 @@ int SetCompilerInstanceOptions(

instance.getLangOpts().SinglePrecisionConstants =
cl_single_precision_constants;
// cl_denorms_are_zero ignored for now!
// cl_fp32_correctly_rounded_divide_sqrt ignored for now!
instance.getCodeGenOpts().LessPreciseFPMAD =
clspv::Option::ClMadEnable() || clspv::Option::UnsafeMath();
Expand Down Expand Up @@ -965,13 +1010,13 @@ int ParseOptions(const int argc, const char *const argv[]) {
}

if (!clspv::Option::FP16() &&
ExecutionModeRoundingModeRTE(clspv::Option::RoundingModeRTE::fp16)) {
ExecutionModeRoundingModeRTE(clspv::Option::FloatingPointType::fp16)) {
llvm::errs() << "error: Cannot set RoundingModeRTE for fp16 if fp16 is not "
"supported\n";
return -1;
}
if (!clspv::Option::FP64() &&
ExecutionModeRoundingModeRTE(clspv::Option::RoundingModeRTE::fp64)) {
ExecutionModeRoundingModeRTE(clspv::Option::FloatingPointType::fp64)) {
llvm::errs() << "error: Cannot set RoundingModeRTE for fp64 if fp64 is not "
"supported\n";
return -1;
Expand Down Expand Up @@ -1001,6 +1046,33 @@ int ParseOptions(const int argc, const char *const argv[]) {
clspv::Option::AddUseNativeBuiltins(clspv::Builtins::BuiltinType::kFma);
}

if (clspv::Option::FP16() &&
ExecutionModeDenorm(clspv::Option::FloatingPointType::fp16) ==
clspv::Option::DenormMode::error) {
llvm::errs()
<< "error: denorm preserve & flush to zero mode are exclusive (fp16)";
return -1;
}
if (ExecutionModeDenorm(clspv::Option::FloatingPointType::fp32) ==
clspv::Option::DenormMode::error) {
llvm::errs()
<< "error: denorm preserve & flush to zero mode are exclusive (fp32)";
return -1;
}
if (clspv::Option::FP64() &&
ExecutionModeDenorm(clspv::Option::FloatingPointType::fp64) ==
clspv::Option::DenormMode::error) {
llvm::errs()
<< "error: denorm preserve & flush to zero mode are exclusive (fp64)";
return -1;
}
if (clspv::Option::FP16() && clspv::Option::FP64() &&
(ExecutionModeDenorm(clspv::Option::FloatingPointType::fp16) !=
ExecutionModeDenorm(clspv::Option::FloatingPointType::fp64))) {
llvm::errs() << "error: fp16 & fp64 needs to share the same DenormMode";
return -1;
}

return 0;
}

Expand Down
79 changes: 66 additions & 13 deletions lib/Option.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,19 +296,46 @@ static llvm::cl::opt<bool> cluster_non_pointer_kernel_args(
"other arguments. Use this to reduce storage buffer "
"descriptors."));

static llvm::cl::list<clspv::Option::RoundingModeRTE> rounding_mode_rte(
static llvm::cl::list<clspv::Option::FloatingPointType> rounding_mode_rte(
"rounding-mode-rte",
llvm::cl::desc(
"Set execution mode RoundingModeRTE for a floating point type"),
llvm::cl::CommaSeparated, llvm::cl::ZeroOrMore,
llvm::cl::values(clEnumValN(clspv::Option::RoundingModeRTE::fp16, "16",
llvm::cl::values(clEnumValN(clspv::Option::FloatingPointType::fp16, "16",
"Set execution mode RoundingModeRTE for fp16")),
llvm::cl::values(clEnumValN(clspv::Option::RoundingModeRTE::fp32, "32",
llvm::cl::values(clEnumValN(clspv::Option::FloatingPointType::fp32, "32",
"Set execution mode RoundingModeRTE for fp32")),
llvm::cl::values(
clEnumValN(clspv::Option::RoundingModeRTE::fp64, "64",
clEnumValN(clspv::Option::FloatingPointType::fp64, "64",
"Set execution mode RoundingModeRTE for fp64")));

static llvm::cl::list<clspv::Option::FloatingPointType> denorm_preserve(
"denorm-preserve",
llvm::cl::desc(
"Set execution mode DenormPreserve for a floating point type"),
llvm::cl::CommaSeparated, llvm::cl::ZeroOrMore,
llvm::cl::values(clEnumValN(clspv::Option::FloatingPointType::fp16, "16",
"Set execution mode DenormPreserve for fp16")),
llvm::cl::values(clEnumValN(clspv::Option::FloatingPointType::fp32, "32",
"Set execution mode DenormPreserve for fp32")),
llvm::cl::values(clEnumValN(clspv::Option::FloatingPointType::fp64, "64",
"Set execution mode DenormPreserve for fp64")));

static llvm::cl::list<clspv::Option::FloatingPointType> denorm_flush_to_zero(
"denorm-flush-to-zero",
llvm::cl::desc(
"Set execution mode DenormFlushToZero for a floating point type"),
llvm::cl::CommaSeparated, llvm::cl::ZeroOrMore,
llvm::cl::values(
clEnumValN(clspv::Option::FloatingPointType::fp16, "16",
"Set execution mode DenormFlushToZero for fp16")),
llvm::cl::values(
clEnumValN(clspv::Option::FloatingPointType::fp32, "32",
"Set execution mode DenormFlushToZero for fp32")),
llvm::cl::values(
clEnumValN(clspv::Option::FloatingPointType::fp64, "64",
"Set execution mode DenormFlushToZero for fp64")));

static llvm::cl::list<clspv::Option::StorageClass> no_16bit_storage(
"no-16bit-storage",
llvm::cl::desc("Disable fine-grained 16-bit storage capabilities."),
Expand Down Expand Up @@ -453,15 +480,15 @@ static llvm::cl::opt<bool>
untyped_pointers("untyped-pointers", llvm::cl::init(false),
llvm::cl::desc("Enable SPV_KHR_untyped_pointers"));

static llvm::cl::list<clspv::Option::SpvKhrFma> spv_khr_fma(
static llvm::cl::list<clspv::Option::FloatingPointType> spv_khr_fma(
"spv-khr-fma",
llvm::cl::desc("Enable SPV_KHR_fma for a floating point type"),
llvm::cl::CommaSeparated, llvm::cl::ZeroOrMore,
llvm::cl::values(clEnumValN(clspv::Option::SpvKhrFma::fp16, "16",
llvm::cl::values(clEnumValN(clspv::Option::FloatingPointType::fp16, "16",
"Enable SPV_KHR_fma for fp16")),
llvm::cl::values(clEnumValN(clspv::Option::SpvKhrFma::fp32, "32",
llvm::cl::values(clEnumValN(clspv::Option::FloatingPointType::fp32, "32",
"Enable SPV_KHR_fma for fp32")),
llvm::cl::values(clEnumValN(clspv::Option::SpvKhrFma::fp64, "64",
llvm::cl::values(clEnumValN(clspv::Option::FloatingPointType::fp64, "64",
"Enable SPV_KHR_fma for fp64")));

} // namespace
Expand Down Expand Up @@ -518,7 +545,7 @@ bool NonUniformNDRangeSupported() {
}
bool ClusterPodKernelArgs() { return cluster_non_pointer_kernel_args; }

bool ExecutionModeRoundingModeRTE(RoundingModeRTE fp) {
bool ExecutionModeRoundingModeRTE(FloatingPointType fp) {
for (auto type : rounding_mode_rte) {
if (type == fp) {
return true;
Expand All @@ -527,6 +554,32 @@ bool ExecutionModeRoundingModeRTE(RoundingModeRTE fp) {
return false;
}

DenormMode ExecutionModeDenorm(FloatingPointType fpty) {
static std::unordered_map<FloatingPointType, DenormMode> modes;
auto mode = modes.find(fpty);
if (mode != modes.end()) {
return modes[fpty];
}

for (auto type : denorm_preserve) {
modes[type] = DenormMode::preserve;
}
for (auto type : denorm_flush_to_zero) {
if (modes.find(type) != modes.end()) {
modes[type] = DenormMode::error;
} else {
modes[type] = DenormMode::flush_to_zero;
}
}
for (auto type : {FloatingPointType::fp16, FloatingPointType::fp32,
FloatingPointType::fp64}) {
if (modes.find(type) == modes.end()) {
modes[type] = DenormMode::unspecified;
}
}
return modes[fpty];
}

bool Supports16BitStorageClass(StorageClass sc) {
// -no-16bit-storage removes storage capabilities.
for (auto storage_class : no_16bit_storage) {
Expand Down Expand Up @@ -625,16 +678,16 @@ bool UntypedPointerAddressSpace(unsigned aspace) {
}

bool SupportsFmaKHR(uint32_t scalarSizeInBits) {
SpvKhrFma fma;
FloatingPointType fma;
switch (scalarSizeInBits) {
case 16:
fma = clspv::Option::SpvKhrFma::fp16;
fma = clspv::Option::FloatingPointType::fp16;
break;
case 32:
fma = clspv::Option::SpvKhrFma::fp32;
fma = clspv::Option::FloatingPointType::fp32;
break;
case 64:
fma = clspv::Option::SpvKhrFma::fp64;
fma = clspv::Option::FloatingPointType::fp64;
break;
default:
return false;
Expand Down
Loading