llvm::Triple support for haswell-enabled x86_64

I’m working on LLDB and we have a bunch of code that is manually manipulating triples and doing a bunch of nasty stuff to account for the fact that llvm::Triple doesn’t currently have a way to detect x86_64h.

Is this something that llvm::Triple could be modified to support? Either as a new ArchType, or a new SubArchType?

Sure, go for it. It’d be a fairly natural fit for a SubArchType.

Sounds good, I’ll give it a try sooner or later. I’ve never messed with triples, so is there anything I need to be aware of so I don’t break any code on other platforms? In particular, I want llvm::sys::getDefaultTargetTriple() to return me this new haswell-aware triple, so what do I need to do to ensure that I don’t break anyone else who is running one of these systems and previously had a different default triple?

That triple is currently only used on Darwin. Its exact meaning there can be seen in the clang driver where the subtarget features are passed to the target. Note that it’s not exactly equivalent to enabling -march=core-avx2. It’s really close, but not 100% the same. My main suggestion there is to make its meaning on other platforms be the same. Having the same triple mean slightly different things depending on platform would get really ugly really fast.

In theory, the tests in tree should help make sure things don’t break for Darwin. In practice, that’s true for the basics, but probably optimistic for subtleties. If you include myself and Quentin Colombet on phab (or cc us on the lists) for patches in the area, we can have a look and help anticipate issues.


What is the difference? and why? It seems really confusing to have this
divergence, or to be unable to replicate the *exact* behavior of this (very
weird, and IMO *bad* triple) with the standard triple of 'x86_64-...' and
an '-march' flag.

It just seems like a reinvention of i386, i486, and iN86, probably for all
of the same reasons. If you can encode all the important things in the
triple, you can have different library directories for distributions, etc.

The x86_64h triple is specifically targeted for a subclass of Haswell features. For instance, IIRC, unlike core-avx2, it does not have the AES feature.

This is basically a mix of x86_64, -march, and a few target features.


There’s a few more subtleties, but that’s a reasonable analogy. While the sub-arch is related to a -march= setting, it is very definitely not the same thing. It’s not even just the sub-arch. Consider, for example, that “thumb” and “arm” have separate top-level triple values.

Yes, this whole system of how the arch and sub arch triple stuff works is brittle and ugly. Now that we have module level attributes and such, it’s probably possible to design something more sane. It’s debatable whether it’s worth the effort, but it’s possible.

We had a little bit of discussion recently about treating triples as config file names. The triple would, in this model, *just* be a name and would define a file that contained a load of command-line options (-mabi, -mcpu, --sysroot, -B, and so on). We'd ship some, people wanting to ship their own SDKs could ship other ones.

Does this make sense to anyone else?


I’d love a way to only compile in the triples we need instead of having everyone pull in all of the strings from lib/Support/Triple.cpp even when we don’t include the backend, but I do not like the idea of forcing llvm to read a file. It is completely reasonable to have a sandboxed process that doesn’t have file access and can compile in and out of memory buffers via IPC. Taking a task that previously did not require access to a filesystem and adding that dependency seems wrong to me. I’m also uncomfortable with the notion of different compilers shipping with the same triple and it meaning different things, but I am not sure if you are proposing that.

Personally I would be a lot more comfortable with moving to a model where the backends register their triples with the compiler, that way when we compile without a backend we could avoid all of its strings, and it would move the meaning of the triples (particularly the sub targets) closer to what they impact. It would also get rid of what is essentially a thousand lines of switch statements in Triple.cpp.


The problem with this is the use case where you want to use the fact that the LLVM tools are intrinsically platform independent and ship a sysroot that contains your libraries, but don't want to have to bundle a copy of clang that is identical to the one that the user already has on their system. Currently, you can create a symlink to {triple}-clang and you have a clang that can target that triple, but the triple is not expressive enough for all of the stuff that you care about. At a minimum, you want:

- Sysroot location (this absolutely can not be baked in at compile time to be generally useful)
- Path to platform-specific tools (e.g. linker)

For things that embed LLVM for a specific purpose, there's no problem in baking the mapping from triples to something sane into the code, but for generic toolchain components (cc, c++, as, objdump, readelf, size, strings, strip, and so on), being able to construct target-specific variants by just providing a config file and have that automatically consulted by a specially named symlink is likely to be a win.

We currently have to implement this by having a shell script wrapper that execs the compiler, but the cost of the shell is quite measurable in compile times.


How complicated is the shell script? If the only concern is that the shell is slow then it seems like rewriting the shell script in C would solve your problems. We actually do something similar on OS X, /usr/bin/clang is not a copy of clang or a symlink, it is an executable that redirects to the currently configured toolchain.


Figuring out a better way to represent things that are currently all lumped into the triple sounds like a great thing. To make sure that all the folks who would be interested in such a discussion see it, a new thread with a more apropos subject line would probably help.

This is also starting to bring in concepts from the Universal Driver proposals that have come up from time to time. Figuring out how to factor these things and what logic belongs where is definitely a challenge.