##
##  Copyright (C) The Software Authors. All rights reserved.
##  Use of this source code is governed by a BSD-style
##  license that can be found in the LICENSE file.
##
##  \file     option.cmake
##  \author   Rainvan (Yunfeng.Xiao)
##  \date     Jan 2017
##  \version  1.0
##  \brief    Detail cmake build option script
##

## https://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures
## https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
## https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html

## Intel Microarchitectures
option(ENABLE_NEHALEM "Enable Intel Nehalem CPU microarchitecture" OFF)
option(ENABLE_SANDYBRIDGE "Enable Intel Sandy Bridge CPU microarchitecture" OFF)
option(ENABLE_HASWELL "Enable Intel Haswell CPU microarchitecture" OFF)
option(ENABLE_BROADWELL "Enable Intel Broadwell CPU microarchitecture" OFF)
option(ENABLE_SKYLAKE "Enable Intel Skylake CPU microarchitecture" OFF)
option(ENABLE_SKYLAKE_AVX512 "Enable Intel Skylake Server CPU microarchitecture" OFF)

## AMD Microarchitectures
option(ENABLE_ZEN1 "Enable AMD Zen+ Family 17h CPU microarchitecture" OFF)
option(ENABLE_ZEN2 "Enable AMD Zen 2 Family 17h CPU microarchitecture" OFF)
option(ENABLE_ZEN3 "Enable AMD Zen 3 Family 19h CPU microarchitecture" OFF)

## Intel Instructions
option(ENABLE_SSE "Enable Intel SSE instructions" OFF)
option(ENABLE_SSE2 "Enable Intel SSE2 instructions" OFF)
option(ENABLE_SSE3 "Enable Intel SSE3 instructions" OFF)
option(ENABLE_SSSE3 "Enable Intel SSSE3 instructions" OFF)
option(ENABLE_SSE4.1 "Enable Intel SSE4.1 instructions" OFF)
option(ENABLE_SSE4.2 "Enable Intel SSE4.2 instructions" OFF)
option(ENABLE_AVX  "Enable Intel AVX instructions" OFF)
option(ENABLE_AVX2 "Enable Intel AVX2 instructions" OFF)
option(ENABLE_AVX512F "Enable Intel AVX512F instructions" OFF)
option(ENABLE_AVX512BW "Enable Intel AVX512BW instructions" OFF)
option(ENABLE_AVX512CD "Enable Intel AVX512CD instructions" OFF)
option(ENABLE_AVX512DQ "Enable Intel AVX512DQ instructions" OFF)
option(ENABLE_AVX512ER "Enable Intel AVX512ER instructions" OFF)
option(ENABLE_AVX512IFMA52 "Enable Intel AVX512IFMA52 instructions" OFF)
option(ENABLE_AVX512PF "Enable Intel AVX512PF instructions" OFF)
option(ENABLE_AVX512VL "Enable Intel AVX512VL instructions" OFF)
option(ENABLE_AVX512VPOPCNTDQ "Enable Intel AVX512VPOPCNTDQ instructions" OFF)
option(ENABLE_AVX5124FMAPS "Enable Intel AVX5124FMAPS instructions" OFF)
option(ENABLE_AVX5124VNNIW "Enable Intel AVX5124VNNIW instructions" OFF)
option(ENABLE_AVX512BF16 "Enable Intel AVX512BF16 instructions" OFF)
option(ENABLE_AVX512BITALG "Enable Intel AVX512BITALG instructions" OFF)
option(ENABLE_AVX512VBMI "Enable Intel AVX512VBMI instructions" OFF)
option(ENABLE_AVX512VBMI2 "Enable Intel AVX512VBMI2 instructions" OFF)
option(ENABLE_AVX512VNNI "Enable Intel AVX512VNNI instructions" OFF)
option(ENABLE_AVX512VP2INTERSECT "Enable Intel AVX512VP2INTERSECT instructions" OFF)
option(ENABLE_AVX512FP16 "Enable Intel AVX512FP16 instructions" OFF)

option(ENABLE_AVXVNNI "Enable Intel AVXVNNI instructions" OFF)
option(ENABLE_FMA "Enable Intel FMA instructions" OFF)
option(ENABLE_F16C "Enable Intel F16C instructions" OFF)

## ARM architectures
option(ENABLE_ARMV8A "Enable ARMv8-a architecture" OFF)
option(ENABLE_ARMV8.1A "Enable ARMv8.1-a architecture" OFF)
option(ENABLE_ARMV8.2A "Enable ARMv8.2-a architecture" OFF)
option(ENABLE_ARMV8.3A "Enable ARMv8.3-a architecture" OFF)
option(ENABLE_ARMV8.4A "Enable ARMv8.4-a architecture" OFF)
option(ENABLE_ARMV8.5A "Enable ARMv8.5-a architecture" OFF)
option(ENABLE_ARMV8.6A "Enable ARMv8.6-a architecture" OFF)

## OpenMP option
option(ENABLE_OPENMP "Enable OpenMP support" OFF)

function(_AppendFlags _RESULT _FLAG)
  if(${_RESULT} AND NOT "${${_RESULT}}" MATCHES "${_FLAG}")
    set(${_RESULT} "${${_RESULT}} ${_FLAG}" PARENT_SCOPE)
  else()
    set(${_RESULT} "${_FLAG}" PARENT_SCOPE)
  endif()
endfunction()

include(CheckCCompilerFlag)
if(NOT MSVC)
  if(ENABLE_ARMV8.6A)
    CHECK_C_COMPILER_FLAG("-march=armv8.6-a" COMPILER_SUPPORT_ARMV8.6A)
    if(COMPILER_SUPPORT_ARMV8.6A)
      _AppendFlags(CMAKE_C_FLAGS -march=armv8.6-a)
      _AppendFlags(CMAKE_CXX_FLAGS -march=armv8.6-a)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=armv8.6-a\'.")
    endif()
  endif()

  if(ENABLE_ARMV8.5A)
    CHECK_C_COMPILER_FLAG("-march=armv8.5-a" COMPILER_SUPPORT_ARMV8.5A)
    if(COMPILER_SUPPORT_ARMV8.5A)
      _AppendFlags(CMAKE_C_FLAGS -march=armv8.5-a)
      _AppendFlags(CMAKE_CXX_FLAGS -march=armv8.5-a)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=armv8.5-a\'.")
    endif()
  endif()

  if(ENABLE_ARMV8.4A)
    CHECK_C_COMPILER_FLAG("-march=armv8.4-a" COMPILER_SUPPORT_ARMV8.4A)
    if(COMPILER_SUPPORT_ARMV8.4A)
      _AppendFlags(CMAKE_C_FLAGS -march=armv8.4-a)
      _AppendFlags(CMAKE_CXX_FLAGS -march=armv8.4-a)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=armv8.4-a\'.")
    endif()
  endif()

  if(ENABLE_ARMV8.3A)
    CHECK_C_COMPILER_FLAG("-march=armv8.3-a" COMPILER_SUPPORT_ARMV8.3A)
    if(COMPILER_SUPPORT_ARMV8.3A)
      _AppendFlags(CMAKE_C_FLAGS -march=armv8.3-a)
      _AppendFlags(CMAKE_CXX_FLAGS -march=armv8.3-a)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=armv8.3-a\'.")
    endif()
  endif()

  if(ENABLE_ARMV8.2A)
    CHECK_C_COMPILER_FLAG("-march=armv8.2-a" COMPILER_SUPPORT_ARMV8.2A)
    if(COMPILER_SUPPORT_ARMV8.2A)
      _AppendFlags(CMAKE_C_FLAGS -march=armv8.2-a)
      _AppendFlags(CMAKE_CXX_FLAGS -march=armv8.2-a)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=armv8.2-a\'.")
    endif()
  endif()

  if(ENABLE_ARMV8.1A)
    CHECK_C_COMPILER_FLAG("-march=armv8.1-a" COMPILER_SUPPORT_ARMV8.1A)
    if(COMPILER_SUPPORT_ARMV8.1A)
      _AppendFlags(CMAKE_C_FLAGS -march=armv8.1-a)
      _AppendFlags(CMAKE_CXX_FLAGS -march=armv8.1-a)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=armv8.1-a\'.")
    endif()
  endif()

  if(ENABLE_ARMV8A)
    CHECK_C_COMPILER_FLAG("-march=armv8-a" COMPILER_SUPPORT_ARMV8A)
    if(COMPILER_SUPPORT_ARMV8A)
      _AppendFlags(CMAKE_C_FLAGS -march=armv8-a)
      _AppendFlags(CMAKE_CXX_FLAGS -march=armv8-a)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=armv8-a\'.")
    endif()
  endif()

  if(ENABLE_ZEN1)
    CHECK_C_COMPILER_FLAG("-march=znver1" COMPILER_SUPPORT_ZEN1)
    if(COMPILER_SUPPORT_ZEN1)
      _AppendFlags(CMAKE_C_FLAGS -march=znver1)
      _AppendFlags(CMAKE_CXX_FLAGS -march=znver1)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=znver1\'.")
    endif()
  endif()

  if(ENABLE_ZEN2)
    CHECK_C_COMPILER_FLAG("-march=znver2" COMPILER_SUPPORT_ZEN2)
    if(COMPILER_SUPPORT_ZEN2)
      _AppendFlags(CMAKE_C_FLAGS -march=znver2)
      _AppendFlags(CMAKE_CXX_FLAGS -march=znver2)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=znver2\'.")
    endif()
  endif()

  if(ENABLE_ZEN3)
    CHECK_C_COMPILER_FLAG("-march=znver3" COMPILER_SUPPORT_ZEN3)
    if(COMPILER_SUPPORT_ZEN3)
      _AppendFlags(CMAKE_C_FLAGS -march=znver3)
      _AppendFlags(CMAKE_CXX_FLAGS -march=znver3)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=znver3\'.")
    endif()
  endif()

  if(ENABLE_NEHALEM)
    CHECK_C_COMPILER_FLAG("-march=nehalem" COMPILER_SUPPORT_NEHALEM)
    if(COMPILER_SUPPORT_NEHALEM)
      _AppendFlags(CMAKE_C_FLAGS -march=nehalem)
      _AppendFlags(CMAKE_CXX_FLAGS -march=nehalem)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=nehalem\'.")
    endif()
  endif()

  if(ENABLE_SANDYBRIDGE)
    CHECK_C_COMPILER_FLAG("-march=sandybridge" COMPILER_SUPPORT_SANDYBRIDGE)
    if(COMPILER_SUPPORT_SANDYBRIDGE)
      _AppendFlags(CMAKE_C_FLAGS -march=sandybridge)
      _AppendFlags(CMAKE_CXX_FLAGS -march=sandybridge)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=sandybridge\'.")
    endif()
  endif()

  if(ENABLE_HASWELL)
    CHECK_C_COMPILER_FLAG("-march=haswell" COMPILER_SUPPORT_HASWELL)
    if(COMPILER_SUPPORT_HASWELL)
      _AppendFlags(CMAKE_C_FLAGS -march=haswell)
      _AppendFlags(CMAKE_CXX_FLAGS -march=haswell)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=haswell\'.")
    endif()
  endif()

  if(ENABLE_BROADWELL)
    CHECK_C_COMPILER_FLAG("-march=broadwell" COMPILER_SUPPORT_BROADWELL)
    if(COMPILER_SUPPORT_BROADWELL)
      _AppendFlags(CMAKE_C_FLAGS -march=broadwell)
      _AppendFlags(CMAKE_CXX_FLAGS -march=broadwell)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=broadwell\'.")
    endif()
  endif()

  if(ENABLE_SKYLAKE)
    CHECK_C_COMPILER_FLAG("-march=skylake" COMPILER_SUPPORT_SKYLAKE)
    if(COMPILER_SUPPORT_SKYLAKE)
      _AppendFlags(CMAKE_C_FLAGS -march=skylake)
      _AppendFlags(CMAKE_CXX_FLAGS -march=skylake)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=skylake\'.")
    endif()
  endif()

  if(ENABLE_SKYLAKE_AVX512)
    CHECK_C_COMPILER_FLAG("-march=skylake-avx512" COMPILER_SUPPORT_SKYLAKE_AVX512)
    if(COMPILER_SUPPORT_SKYLAKE_AVX512)
      _AppendFlags(CMAKE_C_FLAGS -march=skylake-avx512)
      _AppendFlags(CMAKE_CXX_FLAGS -march=skylake-avx512)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-march=skylake-avx512\'.")
    endif()
  endif()

  if(ENABLE_AVX512BW)
    CHECK_C_COMPILER_FLAG("-mavx512bw" COMPILER_SUPPORT_AVX512BW)
    if(COMPILER_SUPPORT_AVX512BW)
      _AppendFlags(CMAKE_C_FLAGS -mavx512bw)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512bw)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512bw\'.")
    endif()
  endif()

  if(ENABLE_AVX512CD)
    CHECK_C_COMPILER_FLAG("-mavx512cd" COMPILER_SUPPORT_AVX512CD)
    if(COMPILER_SUPPORT_AVX512CD)
      _AppendFlags(CMAKE_C_FLAGS -mavx512cd)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512cd)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512cd\'.")
    endif()
  endif()

  if(ENABLE_AVX512DQ)
    CHECK_C_COMPILER_FLAG("-mavx512dq" COMPILER_SUPPORT_AVX512DQ)
    if(COMPILER_SUPPORT_AVX512DQ)
      _AppendFlags(CMAKE_C_FLAGS -mavx512dq)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512dq)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512dq\'.")
    endif()
  endif()

  if(ENABLE_AVX512ER)
    CHECK_C_COMPILER_FLAG("-mavx512er" COMPILER_SUPPORT_AVX512ER)
    if(COMPILER_SUPPORT_AVX512ER)
      _AppendFlags(CMAKE_C_FLAGS -mavx512er)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512er)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512er\'.")
    endif()
  endif()

  if(ENABLE_AVX512IFMA52)
    CHECK_C_COMPILER_FLAG("-mavx512ifma52" COMPILER_SUPPORT_AVX512IFMA52)
    if(COMPILER_SUPPORT_AVX512IFMA52)
      _AppendFlags(CMAKE_C_FLAGS -mavx512ifma52)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512ifma52)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512ifma52\'.")
    endif()
  endif()

  if(ENABLE_AVX512PF)
    CHECK_C_COMPILER_FLAG("-mavx512pf" COMPILER_SUPPORT_AVX512PF)
    if(COMPILER_SUPPORT_AVX512PF)
      _AppendFlags(CMAKE_C_FLAGS -mavx512pf)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512pf)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512pf\'.")
    endif()
  endif()

  if(ENABLE_AVX512VL)
    CHECK_C_COMPILER_FLAG("-mavx512vl" COMPILER_SUPPORT_AVX512VL)
    if(COMPILER_SUPPORT_AVX512VL)
      _AppendFlags(CMAKE_C_FLAGS -mavx512vl)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512vl)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512vl\'.")
    endif()
  endif()

  if(ENABLE_AVX512VPOPCNTDQ)
    CHECK_C_COMPILER_FLAG("-mavx512vpopcntdq" COMPILER_SUPPORT_AVX512VPOPCNTDQ)
    if(COMPILER_SUPPORT_AVX512VPOPCNTDQ)
      _AppendFlags(CMAKE_C_FLAGS -mavx512vpopcntdq)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512vpopcntdq)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512vpopcntdq\'.")
    endif()
  endif()

  if(ENABLE_AVX5124FMAPS)
    CHECK_C_COMPILER_FLAG("-mavx5124fmaps" COMPILER_SUPPORT_AVX5124FMAPS)
    if(COMPILER_SUPPORT_AVX5124FMAPS)
      _AppendFlags(CMAKE_C_FLAGS -mavx5124fmaps)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx5124fmaps)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx5124fmaps\'.")
    endif()
  endif()

  if(ENABLE_AVX5124VNNIW)
    CHECK_C_COMPILER_FLAG("-mavx5124vnniw" COMPILER_SUPPORT_AVX5124VNNIW)
    if(COMPILER_SUPPORT_AVX5124VNNIW)
      _AppendFlags(CMAKE_C_FLAGS -mavx5124vnniw)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx5124vnniw)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx5124vnniw\'.")
    endif()
  endif()

  if(ENABLE_AVX512BF16)
    CHECK_C_COMPILER_FLAG("-mavx512bf16" COMPILER_SUPPORT_AVX512BF16)
    if(COMPILER_SUPPORT_AVX512BF16)
      _AppendFlags(CMAKE_C_FLAGS -mavx512bf16)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512bf16)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512bf16\'.")
    endif()
  endif()

  if(ENABLE_AVX512BITALG)
    CHECK_C_COMPILER_FLAG("-mavx512bitalg" COMPILER_SUPPORT_AVX512BITALG)
    if(COMPILER_SUPPORT_AVX512BITALG)
      _AppendFlags(CMAKE_C_FLAGS -mavx512bitalg)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512bitalg)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512bitalg\'.")
    endif()
  endif()

  if(ENABLE_AVX512VBMI)
    CHECK_C_COMPILER_FLAG("-mavx512vbmi" COMPILER_SUPPORT_AVX512VBMI)
    if(COMPILER_SUPPORT_AVX512VBMI)
      _AppendFlags(CMAKE_C_FLAGS -mavx512vbmi)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512vbmi)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512vbmi\'.")
    endif()
  endif()

  if(ENABLE_AVX512VBMI2)
    CHECK_C_COMPILER_FLAG("-mavx512vbmi2" COMPILER_SUPPORT_AVX512VBMI2)
    if(COMPILER_SUPPORT_AVX512VBMI2)
      _AppendFlags(CMAKE_C_FLAGS -mavx512vbmi2)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512vbmi2)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512vbmi2\'.")
    endif()
  endif()

  if(ENABLE_AVX512VNNI)
    CHECK_C_COMPILER_FLAG("-mavx512vnni" COMPILER_SUPPORT_AVX512VNNI)
    if(COMPILER_SUPPORT_AVX512VNNI)
      _AppendFlags(CMAKE_C_FLAGS -mavx512vnni)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512vnni)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512vnni\'.")
    endif()
  endif()

  if(ENABLE_AVX512VP2INTERSECT)
    CHECK_C_COMPILER_FLAG("-mavx512vp2intersect" COMPILER_SUPPORT_AVX512VP2INTERSECT)
    if(COMPILER_SUPPORT_AVX512VP2INTERSECT)
      _AppendFlags(CMAKE_C_FLAGS -mavx512vp2intersect)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512vp2intersect)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512vp2intersect\'.")
    endif()
  endif()

  if(ENABLE_AVX512FP16)
    CHECK_C_COMPILER_FLAG("-mavx512fp16" COMPILER_SUPPORT_AVX512FP16)
    if(COMPILER_SUPPORT_AVX512FP16)
      _AppendFlags(CMAKE_C_FLAGS -mavx512fp16)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512fp16)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512fp16\'.")
    endif()
  endif()

  if(ENABLE_AVXVNNI)
    CHECK_C_COMPILER_FLAG("-mavxvnni" COMPILER_SUPPORT_AVXVNNI)
    if(COMPILER_SUPPORT_AVXVNNI)
      _AppendFlags(CMAKE_C_FLAGS -mavxvnni)
      _AppendFlags(CMAKE_CXX_FLAGS -mavxvnni)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavxvnni\'.")
    endif()
  endif()

  if(ENABLE_AVX512F)
    CHECK_C_COMPILER_FLAG("-mavx512f" COMPILER_SUPPORT_AVX512F)
    if(COMPILER_SUPPORT_AVX512F)
      _AppendFlags(CMAKE_C_FLAGS -mavx512f)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx512f)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx512f\'.")
    endif()
  elseif(ENABLE_AVX2)
    CHECK_C_COMPILER_FLAG("-mavx2" COMPILER_SUPPORT_AVX2)
    if(COMPILER_SUPPORT_AVX2)
      _AppendFlags(CMAKE_C_FLAGS -mavx2)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx2)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx2\'.")
    endif()
  elseif(ENABLE_AVX)
    CHECK_C_COMPILER_FLAG("-mavx" COMPILER_SUPPORT_AVX)
    if(COMPILER_SUPPORT_AVX)
      _AppendFlags(CMAKE_C_FLAGS -mavx)
      _AppendFlags(CMAKE_CXX_FLAGS -mavx)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mavx\'.")
    endif()
  elseif(ENABLE_SSE4.2)
    CHECK_C_COMPILER_FLAG("-msse4.2" COMPILER_SUPPORT_SSE4.2)
    if(COMPILER_SUPPORT_SSE4.2)
      _AppendFlags(CMAKE_C_FLAGS -msse4.2)
      _AppendFlags(CMAKE_CXX_FLAGS -msse4.2)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-msse4.2\'.")
    endif()
  elseif(ENABLE_SSE4.1)
    CHECK_C_COMPILER_FLAG("-msse4.1" COMPILER_SUPPORT_SSE4.1)
    if(COMPILER_SUPPORT_SSE4.1)
      _AppendFlags(CMAKE_C_FLAGS -msse4.1)
      _AppendFlags(CMAKE_CXX_FLAGS -msse4.1)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-msse4.1\'.")
    endif()
  elseif(ENABLE_SSSE3)
    CHECK_C_COMPILER_FLAG("-mssse3" COMPILER_SUPPORT_SSSE3)
    if(COMPILER_SUPPORT_SSSE3)
      _AppendFlags(CMAKE_C_FLAGS -mssse3)
      _AppendFlags(CMAKE_CXX_FLAGS -mssse3)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mssse3\'.")
    endif()
  elseif(ENABLE_SSE3)
    CHECK_C_COMPILER_FLAG("-msse3" COMPILER_SUPPORT_SSE3)
    if(COMPILER_SUPPORT_SSE3)
      _AppendFlags(CMAKE_C_FLAGS -msse3)
      _AppendFlags(CMAKE_CXX_FLAGS -msse3)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-msse3\'.")
    endif()
  elseif(ENABLE_SSE2)
    CHECK_C_COMPILER_FLAG("-msse2" COMPILER_SUPPORT_SSE2)
    if(COMPILER_SUPPORT_SSE2)
      _AppendFlags(CMAKE_C_FLAGS -msse2)
      _AppendFlags(CMAKE_CXX_FLAGS -msse2)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-msse2\'.")
    endif()
  elseif(ENABLE_SSE)
    CHECK_C_COMPILER_FLAG("-msse" COMPILER_SUPPORT_SSE)
    if(COMPILER_SUPPORT_SSE)
      _AppendFlags(CMAKE_C_FLAGS -msse)
      _AppendFlags(CMAKE_CXX_FLAGS -msse)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-msse\'.")
    endif()
  endif()

  if(ENABLE_FMA)
    CHECK_C_COMPILER_FLAG("-mfma" COMPILER_SUPPORT_FMA)
    if(COMPILER_SUPPORT_FMA)
      _AppendFlags(CMAKE_C_FLAGS -mfma)
      _AppendFlags(CMAKE_CXX_FLAGS -mfma)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mfma\'.")
    endif()
  endif()

  if(ENABLE_F16C)
    CHECK_C_COMPILER_FLAG("-mf16c" COMPILER_SUPPORT_F16C)
    if(COMPILER_SUPPORT_F16C)
      _AppendFlags(CMAKE_C_FLAGS -mf16c)
      _AppendFlags(CMAKE_CXX_FLAGS -mf16c)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'-mf16c\'.")
    endif()
  endif()
else()
  if(ENABLE_AVX512F OR ENABLE_AVX512CD OR ENABLE_AVX512BW OR ENABLE_AVX512DQ OR ENABLE_AVX512VL)
    CHECK_C_COMPILER_FLAG("/arch:AVX512" COMPILER_SUPPORT_AVX512F)
    if(COMPILER_SUPPORT_AVX512F)
      _AppendFlags(CMAKE_C_FLAGS /arch:AVX512)
      _AppendFlags(CMAKE_CXX_FLAGS /arch:AVX512)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'/arch:AVX512\'.")
    endif()
  elseif(ENABLE_AVX2)
    CHECK_C_COMPILER_FLAG("/arch:AVX2" COMPILER_SUPPORT_AVX2)
    if(COMPILER_SUPPORT_AVX2)
      _AppendFlags(CMAKE_C_FLAGS /arch:AVX2)
      _AppendFlags(CMAKE_CXX_FLAGS /arch:AVX2)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'/arch:AVX2\'.")
    endif()
  elseif(ENABLE_AVX)
    CHECK_C_COMPILER_FLAG("/arch:AVX" COMPILER_SUPPORT_AVX)
    if(COMPILER_SUPPORT_AVX)
      _AppendFlags(CMAKE_C_FLAGS /arch:AVX)
      _AppendFlags(CMAKE_CXX_FLAGS /arch:AVX)
    else()
      message(SEND_ERROR "Compiler cannot support flag \'/arch:AVX\'.")
    endif()
  elseif(ENABLE_SSE4.2 OR ENABLE_SSE4.1 OR ENABLE_SSE3 OR ENABLE_SSSE3 OR ENABLE_SSE2)
    CHECK_C_COMPILER_FLAG("/arch:SSE2" COMPILER_SUPPORT_SSE2)
    if(COMPILER_SUPPORT_SSE2)
      _AppendFlags(CMAKE_C_FLAGS /arch:SSE2)
      _AppendFlags(CMAKE_CXX_FLAGS /arch:SSE2)
    endif()
  elseif(ENABLE_SSE)
    CHECK_C_COMPILER_FLAG("/arch:SSE" COMPILER_SUPPORT_SSE)
    if(COMPILER_SUPPORT_SSE)
      _AppendFlags(CMAKE_C_FLAGS /arch:SSE)
      _AppendFlags(CMAKE_CXX_FLAGS /arch:SSE)
    endif()
  endif()
endif()

# OpenMP support
if(ENABLE_OPENMP)
  find_package(OpenMP REQUIRED)
  if(OPENMP_FOUND)
    _AppendFlags(CMAKE_C_FLAGS ${OpenMP_C_FLAGS})
    _AppendFlags(CMAKE_CXX_FLAGS ${OpenMP_CXX_FLAGS})
  endif()
endif()
