How to use AVX/pclmulqdq on Mac OS X - gcc

I am trying to compile a program that uses the pclmulqdq instruction present in new Intel processors. I've installed GCC 4.6 using macports but when I compile my program (which uses the intrinsic _mm_clmulepi64_si128), I get
/var/folders/ps/sfjmtgx5771_qbqnh4c9xclr0000gn/T//ccEAWWhd.s:16:no such
instruction: `pclmulqdq $0, %xmm0,%xmm1'
It seems that GCC is able to generate the correct assembly code from the instrinsic, but the assembler does not recognize the instruction.
I've installed binutils using macports, but the problem persists. How do I know which assembler gcc is using? The XCode assembler probably does not support it, but the binutils assembler should.

A simpler solution that fixed this problem for me was adding -Wa,-q to the compiler flags. From the man pages for as (version 1.38):
-q
Use the clang(1) integrated assembler instead of the GNU based system assembler.
The -Wa part passes it from the compiler driver to the assembler, much like -Wl passes arguments to the linker.

The GNU assembler (GAS) is not supported in Mac OS X.
In order to use AVX, I had to:
Install GCC using MacPorts;
Replace the native OS X assembler (/usr/bin/as) by a script which calls the clang assembler.
Compile the program with the installed GCC (e.g. gcc-mp-4.7)
The strange thing is that while the clang assembler supports AVX, the clang compiler does not recognize the AVX instrinsics, forcing the ugly workaround above.

The built in version of as is outdated. (In OS X 10.8.3)
/usr/libexec/as/x86_64/as -v
Apple Inc version cctools-839, GNU assembler version 1.38
There does not seem to exist a version of gas for OS X. (See:
Installing GNU Assembler in OSX)
Using the clang assembler via a script hack (as pointed out by Conrado PLG) is one workaround. However, it does require administrator privileges and overwrites OS X-bundled executables, causing a risk of it being overwritten by a new (yet possibly outdated) version of as bundled with a future version of OS X.
Is there then a better workaround?
As noted on Why does cross gcc invoke native 'as'? it seems to be possible to specify which "as"-executable and flags to use (using "-specs=..."). A cleaner workaround to the problem seems to be to pass the correct "-specs" flags to invoke the clang assembler. This does not require admin privileges and does not risk being broken by an OS X update. The exact details of how to perform this remains to be found out (anyone?).
If this workaround becomes trouble-free and transparent enough, it may be warranted to use those settings as a default (or at least variant) for the macport gcc (so that it supports "-march=native" and the like). There is such as configure.args setting ("--with-as=${prefix}/bin/as", as seen in https://trac.macports.org/browser/trunk/dports/lang/gcc48/Portfile ), which could be replaced.

Just use
as --version
AVX appeared around version 2.18.50 in gas/binutils.

It appears that I fixed my issue by using the gcc / asm syntax where asm{} function is passed a string consisting of assembler statements surrounded by quotes and separated by a backslash and newline or backslash and quoted string containing another assembler statement.
https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s3

Related

AVX and newer intrinsics with GCC on Mac; what assembler would one need?

I have been tweaking GCC 6.3.0 to get it to use the libc++ runtime instead of libstdc++ so that g++ can be used without worrying about C++ runtime incompatibilities:
https://github.com/RJVB/macstrop/tree/master/lang/gcc6
The tweak works, I can build and run KDE software using g++ against Qt5 and KF5 frameworks (and everything else) built with various clang versions.
What doesn't work is generating code that uses AVX and presumably most or all newer intrinsic instructions.
This is not a new issue that's never been invoked on here; it's answered here for instance: How to use AVX/pclmulqdq on Mac OS X
Evidently one can configure gcc to call the linked script instead of the actual as executable.
But can gcc not be configured to use another assembler altogether, like nasm, and would that solve this issue?

How to choose the assembler GCC uses?

Is there an option to GCC that changes the path of the assembler it uses? I'm getting errors from Solaris /usr/ccs/bin/as when using GCC to attempt to compile Haskell, but I've got a copy of GNU as in my path so when I type which as and as --version they use the GNU version, not the Solaris version. Unfortunately it seems GCC ignores the GNU version in the path and goes to the Solaris version. I'm trying to build Haskell on Solaris and I don't think it sits well with the Solaris assembler. I hope I can change this behaviour with a simple wrapper script so I don't have to recompile GCC.
Specifying the assembler to be used is not possible at run time. It has to be done when configuring gcc:
--with-gnu-as
Specify that the compiler should assume that the assembler it finds is the GNU
assembler. However, this does not modify the rules to find an assembler and will
result in confusion if the assembler found is not actually the GNU assembler.
(Confusion may also result if the compiler finds the GNU assembler but has not
been configured with --with-gnu-as.)
Note the part I've put in italics. Of course you could temporarily change /usr/ccs/bin/as to call the gnu assembler (provided you have the necessary permissions), but the above seems to suggest that you'll very likely run into problems. The gcc build process actually checks the features the assembler supports and generates code for exactly that assembler.
I suggest you build a new version of gcc first (configured to use the gnu tools), and then use that to build ghc.

Proper way to upgrade from llvm-g++-4.2 to g++-4.7 on Mac

I have Lion 10.7.3 with the Command-line tool installed. I wanted to experiment with C++11, so I used homebrew to install GCC 4.7 as documented here.
How can I now upgrade the /usr/bin/g++ to be the one installed by Homebrew? Is it as simple as symlinking it? I just want to double check and make sure. Thanks!
First, are you sure you need g++ 4.7? As you can see from the C++11 implementation status page, recent versions of clang support most of C++11 too. Of course there are still things that g++ handles and clang doesn't, but there are also still things that clang supports and g++ doesn't. And, more importantly, you already have a recent version of clang, from Apple, configured and ready to go, as your default compiler. Plus, g++ after 4.2 doesn't support Mac extensions like, say, -arch, which means you can't use it to build a whole lot of third-party software (because most configure scripts assume that if you're on a Mac, your compiler supports Mac extensions).
But if you want g++ 4.7, you can do it. Just not by trying to replace /usr/bin/g++ with a different version. Never replace anything in /usr/bin (or /System) with non-Apple stuff except in a few very rare cases (when you have a strong reassurance from someone who knows what they're talking about).
A better thing to do is to just install another compiler in parallel. Just let Homebrew install its favorite way (so it installs into some prefix like /usr/local/Cellar/gcc/4.7, then symlinks all the appropriate stuff into /usr/local/bin, etc.), and use it that way.
When compiling your code, instead of writing g++, write /usr/local/bin/g++, or g++-4.7.
If you get tired of doing that, put /usr/local/bin higher on your PATH that /usr/bin, or create a shell alias, or stick it in the environment variable CXX and write $CXX instead of g++.
If you're using a GUI IDE, you should be able to configure it to use your compiler by setting the path to it somewhere. (Unless you're using Xcode, which you can only configure to work with Apple-tested compilers.)
This is all you need for experimenting with your own code. If you want to compile third-party applications with this compiler, that may be a bit more complicated. You don't often actually compile each source file and link the result together; you just do configure && make and let them do the heavy lifting for you.
Fortunately, most packages will respect the standard environment variables, especially CXX for specifying a default C++ compiler and CC for a default C compiler. (That's why I suggested the name CXX above.)
Just remember that, again, g++ 4.7 doesn't support Mac extensions, so if you're not prepared to debug a bunch of autoconf-based configure scripts complaining that your compiler can't generate code because it assumed it could throw -arch x86_64 at any compiler on a Mac, etc., don't do this.

Installing GNU Assembler in OSX

No matter how hard I google, I can't seem to find a (relatively) easy-to-follow instruction on how to install the GNU Assembler on a mac.
I know I can use gcc -c (Apple Clang on a Mac) to assemble .s / .S files, but I want to use actual GNU Binutils as.
The GNU assembler cannot (yet) be used to create native object files (of Mach-O format). But you can of course use it to cross-assemble for some non-native object format, if that is what you want.
yasm works on Mac OSX (I got it from Homebrew), and it has a GNU as syntax parser which can be enabled with -p gas (it may be necessary to also add -r gas). It is not 100% complete, but it covers mostly everything. It can output to a variety of object formats (if cross-compiling is necessary), and in my opinion it's pretty cool. You can also use NASM syntax (which is completely supported) using -p nasm (again, -r nasm may be necessary).
Sorry about necroposting, but this is a still-relevant question and I believe that it needs an acceptable answer.
The gnu assembler is already installed on your mac (assuming that you installed the dev tools package). If you want to avoid XCode, you can invoke it from the command line with as, or with the preprocessor by using gcc yourfile.s $(OPTIONS).
Edit: as now points to the clang assembler; at the time this answer was written it pointed to (Apple's build of) the GNU assembler.
Maybe as instead of gas ? If you want to have gas as command invoke this: echo "alias gas=as" >> $HOME/.profile
It was installed on my Mac Lion when i opened the terminal and typed it. It might have been because of MacPorts and/or XCode as mentioned in the comments of a previous answer.

Does gcc work when the wrapper is a different version than the platform-specific binary?

The way I understand gcc, /usr/bin/gcc (and other bits related to gcc, like ld) is a small wrapper that delegates to a platform-specific binary somewhere else on the system.
So does compilation still work correctly if you have a cross compiler that is a couple of versions behind /usr/bin/gcc?
Yes, the whole Idea is to allow gcc to be installed in different versions and for different target platforms (in any combination) to be installed in parallel.
/usr/bin/gcc just uses fork+exec to call the actual compiler. The command line arguments given to gcc are just passed to the actual compiler with two exceptions: -V and -b. The latter selects the target platform the former the version of the compiler.
You won't use /usr/bin/gcc to cross-compile. Instead you'll install another compiler in another prefix. For instance if you're on debian/ubuntu you can install a ming (win32) cross-compiler by doing:
apt-get install mingw32
Which will work perfectly fine side by side with the normal gcc.

Resources