How to get CLang array alloca alignments to be smaller than 16 bytes?

I am working on a custom LLVM backend for a 16 bit architecture.

For my architecture, I need smaller array alignments for arrays created on the stack.

For example, consider the following code at the start of a C function:

char localBuff[20];
char localBuff2[6];

this gets converted by Clang into this:

%localBuff = alloca [20 x i8], align 16
%localBuff2 = alloca [6 x i8], align 1

Note that char arrays smaller than 16 bytes are specified to be aligned to 1 byte, but bigger ones are aligned to 16 bytes.

On the LLVM backend, this creates bigger than necessary frame index offsets, which are undesirable for my architecture.

As a side note, my target machine is 16 bits, so I have already modified ‘TargetInfo.ccp’ with 16 bit ints and pointers, which works like a charm

PointerWidth = PointerAlign = 16;
IntWidth = IntAlign = 16;

The Question is:

  • How do I make CLang to emit code with smaller array alignment, say 2 or 4 byte aligned arrays?
  • Otherwise, is there a way to override that alignment on the LLVM backend implementation, particularly to get it create frame index offsets aligned by a smaller size, thus ignoring the clang specified alignment?

Joan Lluch

Hi Joan,

this gets converted by Clang into this:

  %localBuff = alloca [20 x i8], align 16
  %localBuff2 = alloca [6 x i8], align 1

Is that when Clang is compiling for your target, or maybe you copied
x86 code into your target?

Because this ought to be controlled by "LargeArrayMinSize" and
"LargeArrayAlign" in lib/Basic/Targets/XYZ.cpp, and only x86 and
WebAssembly seem to set the value to 16. The default never increases
the alignment as far as I can tell.

- Otherwise, is there a way to override that alignment on the LLVM backend implementation, particularly to get it create frame index offsets aligned by a smaller size, thus ignoring the clang specified alignment?

I don't think it's the kind of thing you can (or should) override in
the backend. Other bits of code could have been relying on it from the
start (e.g. to store 3 bits of whatever in the low part of a pointer),
and earlier optimizations might have made even more assumptions based
on that value.

Cheers.

Tim.

Hi Tim,

I have implemented all the steps to register a target backend for LLVM and so far I’m doing ok with it, but I do not know how to select a particular target on Clang. I just modified the “TargetInfo.cpp” file as I posted on my previous email to get 16 bit ints. So, any more insights will be appreciated.

On the other hand I’m unable to find LargeArrayMinSize in any project files (not even in lib/Basic/Targets/X86.cpp) and LargeArrayAlign is only in TargetInfo.h and TargetInfo.cpp which is set to a value of 0 (Zero)

I’m on version 7.0.1,

What am I missing?

Joan Lluch

Tel: 620 28 45 13

(Adding llvm-dev back in, in case someone else searches with similar
questions; though cfe-dev might be better for these issues).

I have implemented all the steps to register a target backend for LLVM and so far I’m doing ok with it, but I do not know how to select a particular target on Clang. I just modified the “TargetInfo.cpp” file as I posted on my previous email to get 16 bit ints. So, any more insights will be appreciated.

There are probably about 5-10 different places that need at least
basic modification for a new target in Clang. It's something done
pretty rarely so there's not really any documentation, I'd suggest
grepping the source for an existing target (e.g. aarch64) and
copy/pasting that with modifications for yours.

This will mostly involve creating a few new subclasses for your
target, and telling generic clang code about them in one or two spots,
but I'm afraid I don't recall exact files & lines.

If you can run "clang -target myarch-none-elf" and get a Module
targeting your CPU (i.e. with the correct "target triple" and
"datalayout") that's a good first step. At some point you'll want to
actually think about the ABI decisions you've made and perhaps modify
them (like this array issue), but to begin with you can leave it as
is.

On the other hand I’m unable to find LargeArrayMinSize in any project files (not even in lib/Basic/Targets/X86.cpp)

Sorry, I think that may actually be "LargeArrayMinWidth". I
investigated on a different computer to where I typed up my first
reply so didn't have the exact text on screen.

LargeArrayAlign is only in TargetInfo.h and TargetInfo.cpp which is set to a value of 0 (Zero)

The default is set to 0 in TargetInfo.cpp, but I see it overridden in
X86.h, even in the 7.0 branch (again, typo in my original comment,
where I said .cpp). You'll be creating the equivalent file as part of
adding support to Clang for your target.

Cheers.

Tim.

Hi Tim,

I appreciate your reply, but I can’t still find any relation with “LargeArrayMinWidth” and x86 target. This variable is only in the TargetInfo.cpp and TargetInfo.h files and it’s not even in any x86 related file. I think there should be something else that causes my issue. I have my backend very advanced and already producing good assembly code, but this supposedly simple thing has got me stuck. Are you sure there’s nothing else beyond LargeArrayMinWidth that causes this?

John

Tel: 620 28 45 13

I appreciate your reply, but I can’t still find any relation with “LargeArrayMinWidth” and x86 target.

Are you looking in Clang's source, and that from the same 7.0 version?
If not, you should be. It traces back to 2010; r105500 to be exact:
https://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20100531/030985.html

For a long while references were in a single file (Targets.cpp), but
they'd been split up into one file per target before 7.0
(Targets/XYZ.cpp).

I think there should be something else that causes my issue.

I think that's unlikely.

Are you sure there’s nothing else beyond LargeArrayMinWidth that causes this?

No, but I am sure the LargeArray stuff exists and behaviour I see from
multiple targets matches what I'd expect from the values I see set in
the source.

Cheers.

Tim.

Are you looking in Clang’s source, and that from the same 7.0 version?

Yes, I am, and it’s the same version (7.0.1).

“LargeArrayMinWidth” is only on the following files:

TargetInfo.cpp
TargetInfo.h

So I still think there’s something else that makes the difference on the x86 target.

Anyway, I will now investigate other targets as my temporary frontend. It is right that other targets do not create such big alignments.

Thanks for your help.

John

Tel: 620 28 45 13

OK, so I've downloaded the official Clang released source
(https://releases.llvm.org/7.0.0/cfe-7.0.0.src.tar.xz), and:

$ tar xvf Downloads/cfe-7.0.0.src.tar.xz
[...]
$ cd cfe-7.0.0.src/
$ grep -r LargeArrayMinWidth .
./include/clang/Basic/TargetInfo.h: unsigned char LargeArrayMinWidth,
LargeArrayAlign;
./include/clang/Basic/TargetInfo.h: // getLargeArrayMinWidth/Align -
Return the minimum array size that is
./include/clang/Basic/TargetInfo.h: unsigned getLargeArrayMinWidth()
const { return LargeArrayMinWidth; }
./lib/Basic/TargetInfo.cpp: LargeArrayMinWidth = 0;
./lib/Basic/Targets/Hexagon.h: LargeArrayMinWidth = 64;
./lib/Basic/Targets/NVPTX.cpp: // - LargeArrayMinWidth,
LargeArrayAlign: Not visible across the
./lib/Basic/Targets/X86.h: LargeArrayMinWidth = 128;
./lib/Basic/Targets/WebAssembly.h: LargeArrayMinWidth = 128;
./lib/AST/ASTContext.cpp: unsigned MinWidth =
Target->getLargeArrayMinWidth();

I'm afraid I don't know what actually is happening here, but I think
the best explanation has to be that you're not actually looking at
Clang 7.0 source. That would definitely be my primary line of
investigation.

Cheers.

Tim.

Hi Tim

I created an Xcode project with CMAKE, which should have the entire lot of files. Selecting the ‘install’ scheme Xcode compiles everything including all available targets for clang and llc, which then I can fully debug. So the Xcode project definitely has all the cpp files in it.

However, I now have found that for some reason the .h files in the lib/Basic/Targets directory were not included as part of the Xcode project. This is kind of weird, as this is the only case that I found of .h files not being added to the project. I assume this is a bug on one of the cmake install files. The entire thing compiles anyway because the compiler finds the .h files as they are included in the .cpp source.

I have been performing all searches in the convenience of the xCode environment, and since these particular files were missing from the project they didn’t appear in any searches. I suppose this can be reported as a bug of the Cmake configuration files for xCode.

John

However, I now have found that for some reason the .h files in the lib/Basic/Targets directory were not included as part of the Xcode project.

Ah. At least we now have a common view on the source, and hopefully
you can see what needs doing (even if Xcode won't reflect reality
properly for whatever reason).

I assume this is a bug on one of the cmake install files.

As far as I'm aware LLVM has little to no Xcode magic in its CMake
files. So the bug would be in either CMake (supplying inadequate
dependencies?) or Xcode (misinterpreting CMake output?).

I'm afraid I don't really know enough about either to say which is
responsible. It could even be LLVM, though from what I *have* seen of
CMake, I'd be surprised if we needed to declare headers.

Cheers.

Tim.

To be honest, I don’t either know what really happens under the hood when CMake creates the xCode project for CLang+LLVM. But there’s something really explicit going on there, because the project as it’s shown in xCode does not have the same file grouping structure than the actual physical folders. Not only the project file grouping doesn’t match the physical folder locations, but the group naming is different and generally more convenient and organised than the actual folder structure. What does all that, I have no idea, but cmake creates it all by just selecting xCode as the cmake “generator”.

John

Hi Joan:

I’m sure there are people that use the XCode generator, but I develop on a Mac and don’t use it – well, I did try it once and was underwhelmed by what it produced and gave up on it. So, I just use Ninja, which is fast and works great. Also, since it seems like a lot of people use it, it’s well tested, and you don’t have the issues you’re having with XCode. Plus it works the some on the other platforms I use, e.g., Linux.

I do use the XCode debugger from time to time – just setup an external project and it figures everything out.

hth…
don

Hi Don,

Thank you for your reply and pointers. I suppose everybody choses their tools based on previous experience or skills so that’s why I chose Xcode. I do not think that incremental builds are that slow, they take just a few seconds on my late 2009 iMac. Of course the full CLANG+LLVM build from ‘clean’ takes a while, 15 minutes on my old mac, but there’s no need to do so. There are two particular features that I love from Xcode. The totally integrated debugger and profiler tools, and the code sense features with live error checking (compiler errors as you type) that will save you a lot of failed compilation iterations. I do not know how common these features are if other IDEs, so I may well have a look at Ninja, but as said I’m used to Xcode which I find easy to use.

So back on topic, I made changes to create a CLang frontent configuration for my architecture. As a starting point, I based it on (I actually copied) the MSP430 implementation, because it’s the only genuinely 16 bit architecture available, and so far it’s working as I expect.

The underlying problem with LLVM is the lack of a set of documentation that would goes beyond just scratching the surface. Unfortunately this means that there’s a lot of trial an error and debugging through the existing code until you get to ever figure out how to implement things. It’s a pity that the usual scenario for everything open source, is that everybody wants documentation but nobody is interested in creating it.

John