[llvm-dev] Automatically backing up and restoring x18 around function calls on AArch64?
Martin Storsjö via llvm-dev
llvm-dev at lists.llvm.org
Fri May 10 01:50:23 PDT 2019
On Fri, 26 Apr 2019, Tim Northover wrote:
> At a high level what you probably need to do is get x18 copied on
> function entry and propagated into every call (or, better, every call
> to a Windows function). Since it's all implicit the place to modify is
> AArch64ISelLowering.cpp.
>
> LowerFormalArguments could do a CopyFromReg to preserve the value on
> function entry, and probably CopyToReg it into a new virtual register
> so that other basic blocks can access it (via
> MachineRegisterInfo::createVirtualRegister). You'd save the value of
> this virtual register somewhere for later (in
> AArch64MachineFunctionInfo probably).
>
> LowerCall would then CopyToReg from that vreg andput it back into x18,
> then mark the call as using that register. (using the RegsToPass
> variable, or equivalent). Since you know which functions need x18, you
> can be specific there.
Thanks, I managed to implement this, and it looks pretty promising, and
not very invasive actually.
For enabling it, my PoC added a new target feature +protect-x18, which
invokes these codepaths. (This mechanism is what the driver level flag
-ffixed-x18 boils down to.) Is that sensible, or should I go for a
cl::opt<bool> like the existing ones in AArch64TargetMachine.cpp?
However, at -O0, global isel is used instead (or fast-isel if that's
requested). To opt out from global isel for these kinds of functions, I'd
need to return false in IRTranslator::translateCall (in
CodeGen/GlobalISel/IRTranslator.cpp).
Is there any hook mechanism to the target specific code, where I could
check the aarch64 specific feature and opt out from global isel? (If I add
an unconditional "return false" there, falling back on SelectionDAG seems
to work fine and I get the same behaviour I coded there.)
If fast isel is used and I try to return false from
AArch64FastISel::fastLowerCall (or if I try to implement the register
restoration there), I end up with a failed assertion like this:
../lib/CodeGen/TargetRegisterInfo.cpp:192: const
llvm::TargetRegisterClass*
llvm::TargetRegisterInfo::getMinimalPhysRegClass(unsigned int, llvm::MVT)
const: Assertion `isPhysicalRegister(reg) && "reg must be a physical
register"' failed.
Is there some part of the mechanism with virtual registers in the prologue
that don't quite work with fast isel?
I'll try to complete this, and a few other alternative PoCs, and present
for both Wine and LLVM to decide between the different ways forward.
// Martin
More information about the llvm-dev
mailing list