Before we were relying on the any extend of the s1 to s32, but for AAPCS we need to zero-extend it to at least s8.
Fixes PR36719
Differential D47425
[AArch64][GlobalISel] Zero-extend s1 values when returning. aemerson on May 27 2018, 9:14 AM. Authored by
Details Before we were relying on the any extend of the s1 to s32, but for AAPCS we need to zero-extend it to at least s8. Fixes PR36719
Diff Detail
Event TimelineComment Actions I got my branches mixed up, this patch is missing test updates. Will upload a new one soon.
Comment Actions If possible, GlobalISel's handling of booleans should match SelectionDAG's handling:
The third rule is arguably weird, but it avoids scattering special cases for i1 across legalization. I don't see any compelling reason for GlobalISel to diverge. The ABI rule for booleans on AArch64 is a little strange. The value must be passed/returned as if it were converted to unsigned char, but it doesn't need to be zero-extended beyond 8 bits. (See examples at https://bugs.llvm.org/show_bug.cgi?id=36719 .) This should be handled somewhere in the ABI code, not legalization. Comment Actions I'll re-do this patch to unconditionally zero-extend for returns and also fix up the G_STORE legalisation to always zero-extend too. Given we don't have any target hooks that give us the information we need, let's go with just matching SelectionDAG behaviour? As for the zeroext attributes, from what I can tell we've had the distinction between Darwin and non-Darwin with this since the beginning of the AArch64 target, which was contributed by @t.p.northover. I'd rather not be messing with that unless I have to. Comment Actions Yes, Apple ABI is different (documented at https://developer.apple.com/library/content/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html). Comment Actions New patch now only zero-extends for stores, removing the use of getBooleanContents. We already have test coverage for the store zero-extension. The return issue is fixed in AArch64CallLowering instead. Comment Actions Please take a look at the small nitpick, otherwise LGTM. Thanks!
|
I don't think this is the right way of achieving this and not the way we seem to be currently handling G_CONSTANTs signs across the Global ISel either.
The IR ConstantInt that is a part of G_CONSTANT's operand is basically a bag of bits, if it gets extended, the extend is pretty much an anyext, as different usages of it may need different extensions / may interpret the bits differently.
Therefore every use that is not happy with anyext is explicitly extending the value the right way.
Try ./bin/llc -O0 -mtriple aarch64-- div.ll -o - -stop-after=legalizer -simplify-mir on the following snippets for example:
There are other instructions that are sensitive to the extensions of constants, like all the shifts, for instance. They solve this problem the same way as divisions / remainders.
Technically, the same constant may have more than one usage that would interpret it differently WRT to sign as well.
So this is ABI boundary problem, not legalizing G_CONSTANTs problem, IMO.
I think we need to explicitly extend / mask values before storing them into memory / after loading them from memory, before or after returning them from functions / passing them into functions.
i1s are also a little special. The comment to TargetLowering::getBooleanContents suggests that it's only meaningful for i1 produced by a limited set of instructions and "not to be confused with general values promoted from i1", that's probably why some targets prefer to call such instructions producing i1 legal as soon as those values are immediately used by another instructions from the same subset of special instructions, and then just select the whole thing.
In other words, the flow of i1s is limited.
I think for the test case included this needs to be a change to AArch64CallLowering::lowerReturn method instead.
+ @aditya_nandakumar
+ @dsanders