Clang generates errors when I try to use AVX features - c++

I'm on Windows 10, with Clang version 5 (recently installed). When I compile the following
#define __AVX__
#define __AVX2__
#include <immintrin.h>
int main(void) {
__m256i a, b, result;
result = _mm256_add_epi64(a, b);
return 0;
}
I get the following error:
error: always_inline function '_mm256_add_epi64' requires target
feature 'avx2', but would be inlined into function 'main' that is
compiled without support for 'avx2'
result = _mm256_add_epi64(a, b);
^
MSVC compiles it just fine. What compiler option do I need to use in order to get Clang to compile this? Or is there something else going on?

If you are native compiling (host and target being the same machine so, not cross-compilation), then consider passing -march=native to clang
See also the user manual of the Clang compiler.
Notice that the Clang compiler is open source. You are allowed to download its source code and improve it.

Related

C++ error: intrinsic function was not declared in scope

I want to compile code that uses the intrinsic function _mm256_undefined_si256() (returns a vector of 8 packed double word integers). Here is the reduced snipped of the affected function from the header file:
// test.hpp
#include "immintrin.h"
namespace {
inline __m256i foo(__m256i a, __m256i b) {
__m256i res = _mm256_undefined_si256();
// some inline asm stuff
// __asm__(...);
return res;
}
}
Compiling via gcc -march=native -mavx2 -O3 -std=c++11 test.cpp -o app throws the following error >>_mm256_undefined_si256<< was not declared in this scope.
I can not explain why this intrinsic function is not defined, since there are other intrinsics used in the header file which work properly.
Your code works in GCC4.9 and newer (https://godbolt.org/z/bajMsKvK9). GCC4.9 was released in April 2014, close to a decade ago, and the most recent release of GCC4.8.5 was in June 2015. So it's about time to upgrade your compiler!
GCC4.8 was missing that intrinsic, and didn't even know about -march=sandybridge (let alone tuning options for Haswell which had AVX2), although it did know about the less meaningful -march=corei7-avx.
It does happen that GCC misses some of the more obscure intrinsics that Intel adds along with support for a new instruction set, so support for _mm256_add_epi32 won't always imply _mm256_undefined_si256().
e.g. it took until GCC11 for them to add _mm_load_si32(void*) unaligned aliasing-safe movd (which I think Intel introduced around the same time as AVX-512 stuff), so that's multiple years late. (And until GCC12 / 11.3 for GCC to implement it correctly, Bug 99754, and still not aliasing-safe for _mm_load_ss(float*) (Bug 84508).
But fortunately for the _mm256_undefined_si256, it's supported by non-ancient versions of all the mainstream compilers.

cmath error on MacOS c++17: call to abs ambiguous

Having this error using c++17 on Mac OS.
As far as I can tell, code is correct and should work fine (compiles without issue w/ g++ and clang++ on linux).
Also, as far as I can tell, the current default mac version of clang [10.0.1] should support c++17 (full version info printout below).
So, my question is: is this actually a bug in my code, but it works by fluke on linux? Or is it an issue with MacOS clang e.g., not full c++17 implementation?
From cppref:
Defined in header (since C++17):
int abs( int n );
Other c++17 features seem to work completely fine.
#include <cmath>
// #include <cstdlib> //works if included
int main() {
int i = 1;
// return std::abs(1); // Works fine
return std::abs(i); // Fails
}
Compile with:
clang++ -std=c++17 test.cpp
Get this error:
test.cpp:7:10: error: call to 'abs' is ambiguous
return std::abs(i);
^~~~~~~~
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:761:1: note:
candidate function
abs(float __lcpp_x) _NOEXCEPT {return ::fabsf(__lcpp_x);}
^
(... etc.)
1 error generated.
If you #include <cstdlib>, it works without error.
using -std=gnu++17 or -std=c++1z doesn't remove the problem either.
In the actual code (which is obviously more complex than the above, and actually uses c++17 features), the error happens depending on the order of my include files.
I can't replicate that in the simple example, but I assume it boils down to calling the cstdlib version instead of the cmath version.
Currently, my 'workaround' is to just put the header includes into the order that works..but this is hardly a long-term solution.
Does anyone know the cause?
Version info (error not specific to this MacOS version, also happens on my students' laptops):
Bens-iMac:test ben$ clang++ -v
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
See LWG Issue 2912
This has been fixed in libc++ trunk. I don't know if Apple has shipped this fix yet. As you found, including <cstdlib> is a workaround.

Compiler can't find 'aligned_alloc' function

I'm trying to launch the example code from aligned alloc:
#include <cstdio>
#include <cstdlib>
int main()
{
int* p1 = static_cast<int*>(std::malloc(10*sizeof *p1));
std::printf("default-aligned address: %p\n", static_cast<void*>(p1));
std::free(p1);
int* p2 = static_cast<int*>(std::aligned_alloc(1024, 1024));
std::printf("1024-byte aligned address: %p\n", static_cast<void*>(p2));
std::free(p2);
}
My compilers give me this error:
$ g++-mp-8 main.cpp -std=c++17
main.cpp:10:38: error: no member named 'aligned_alloc' in namespace 'std'
int* p2 = static_cast<int*>(std::aligned_alloc(1024, 1024));
I am working with macOS High Sierra 10.13.6 and tried to compile this code with Macport's GCC 7.3.0, 8.2.0 and CLang (Apple LLVM version 10.0.0), they all produce the same error.
Edit: It doesn't work with either std:: present or not.
Edit2: I installed macOS Mojave and that did not fix the problem. I hoped it'll reinstall macOS's toolchain but it didn't. So I guess I cannot accept provided answers until I get a more specific one.
I am not using macOS but I have similar problems on linux using a custom g++. If you look at the cstdlib header, there is something like
#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)
using ::aligned_alloc;
#endif
So aligned_alloc is only pulled into the std namespace if C++17 is available and glibcxx supports it. You can check x86_64-linux-gnu/bits/c++config.h (or something similar on macOS) if _GLIBCXX_HAVE_ALIGNED_ALLOCis defined. If not your glibc version is too old.
For clang and the libc++ implementation aligned_alloc is available if _LIBCPP_HAS_C11_FEATURES is defined which again depends on a recent version of glibc.
As an alternative you can use boost.
As the accepted answer mentions it, using boost::align::aligned_alloc solves the problem.
To fix the error without source modification, just add the following on top of the file:
#ifdef __APPLE__
#include <boost/align/aligned_alloc.hpp>
using boost::alignment::aligned_alloc;
#endif

Intel code coverage -> undefined reference to `std::string::_S_compare(unsigned long, unsigned long)

I compile code under Redhat 6 using the intel compiler icc/icpc with the flag -prof-gen:srcpos in order to perform a code coverage analysis. This works fine for some parts of my code, but I have problems in a few libraries.
I get the error
undefined reference to std::string::_S_compare(unsigned long, unsigned long)
I link againt the /usr/lib64/libstdc++.so.6.0.13.
Unfortunately, I am unable to identify the difference between code that can be compiled and code that cant. One lib that does not compile is statically build and linked.
Best regards, Georg
I am using the intel compiler version 15.0.3 20150407 and 4.4.7 20120313 (Red Hat 4.4.7-17).
After updating to gcc 4.8.2 20140120 it is working fine. In the old gcc version the required function is not provided.
I have struggled with the same error. Below is a fix to be able to compile the same code on RHEL5 and RHEL6 and not get the error you listed when generating Intel coverage reports. Just place this snippet in the .cpp file that the compiler complains is missing the symbol.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// NOTE: The block below is ONLY needed for building with the
// Intel code-coverage flags turned on. For some reason,
// this comes up as an un-resolved symbol. So, for CODE
// COVERAGE BUILDS ONLY, this symbol is defined here.
#if defined __INTEL_CODE_COVERAGE__ && defined __GLIBC__
// Specify that 2.6 is required because we know that 2.5 does NOT need this.
// The macro tests for >=. Will need to tune this if other glibc versions are in use.
// We have RHEL5 using 2.5, RHEL6 using 2.12.
#if __GLIBC_PREREQ(2,6)
namespace std {
template int string::_S_compare(size_type, size_type);
}
#endif /* glibc version >= 2.6 */
#endif /* intel code coverage and using glibc */
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

GCC C++11 Fails to See #if windows And #if linux (Re-ask)

When using the #if windows/#if linux compilers features in Debian GCC version 4.7.2, I have been unable to get them work when using std11.
Independently, I can get the compiler to accept the if-defines without complaint. I can also get the compiler to use the same code with c++ 11, without any if-defines (and thus not conditionally). But when I run the conditional defines through the same compiler, with the tag for c++ 11, the code is rejected.
Below I have included a simple example, with two alternate mains, and the error I get. The only difference between the two mains are the commented out lines.
Runs:
g++ main.cpp -std=c++11 -o test
The above uses the c++ 11 standard. When running commented main it works perfectly. But when running uncommented main, it fails entirely, giving the error at the far end of this post.
g++ main.cpp -o test
The above does not use the c++ 11 standard. When running either commented main or uncommented main it works perfectly.
Below are the code examples.
Commented main.cpp:
#include <iostream>
//#if windows
//#include "WindowsSolution.hpp"
//#endif
//#if linux
#include "LinuxSolution.hpp"
//#endif
int main()
{
std::cout << myGlobalSolution.out() << std::endl;
return 0;
}
LinuxSolution.hpp:
class LinSolution{
public:
LinSolution(){
}
std::string out(){
std::string ret("Linux solution");
return ret;
}
};
LinSolution myGlobalSolution;
WindowsSolution.hpp:
class WinSolution{
private:
WinSolution(){
}
std::string out(){
std::string ret("Windows solution");
return ret;
}
};
WinSolution myGlobalSolution;
Uncommented main.cpp:
#include <iostream>
#if windows
#include "WindowsSolution.hpp"
#endif
#if linux
#include "LinuxSolution.hpp"
#endif
int main()
{
std::cout << myGlobalSolution.out() << std::endl;
return 0;
}
Below is the error I get when compiling with the uncommented main.cpp, using the c++ 11 flag.
main.cpp: In function ‘int main()’:
main.cpp:13:15: error: ‘myGlobalSolution’ was not declared in this scope
The simple constant linux is a GCC extension and not an official OS constant. The proper constant for Debian is probably __gnu_linux__; you can find a list of them for various systems here. Usually official predefined constants follow the convention of using __ at the start.
Your code works without the standard flag because by default GCC compiles in a GNU language mode (GNU C++) rather than a standard language mode (ISO C++); the GNU language includes extensions (extra language features, and in this case, legacy OS constants). When you pass the -std=c++11 flag you are requesting ISO language mode, which means GNU extensions are disabled, including GNU-only constants. To get both GNU extensions and a specific set of ISO features, try requesting a GNU language standard version instead (e.g. -std=gnu++11 works fine).