Eric Bentura
2015-Jul-13 12:41 UTC
[LLVMdev] ARM Jump table pcrelative relaxation in clang / llc
Hi, I have kept working on this and found the following (as llvm 3.5): 1) In the function MCObjectStreamer::EmitInstruction there is a check for the instruction being relaxable or not: if (!Assembler.getBackend().mayNeedRelaxation(Inst)) { EmitInstToData(Inst, STI); return; } At this stage, the instruction as been already selected to be ARM::ADR. The call to mayNeed 2015-07-07 18:06 GMT+03:00 Tim Northover <t.p.northover at gmail.com>:> On 7 July 2015 at 06:06, Eric Bentura <ebentura at gmail.com> wrote: > > I have created a small ll file to reproduce the problem. > > I used the intrinsic function llvm.arm.space to introduce space between > the > > beginning of the code and the jump table. > > It does look like the value in @llvm.arm.space is interpreted > incorrectly if it's bigger than INT_MAX, but that's well outside its > intended range and could inevitably be used to break ConstantIslands > (the longest ARM immediate branch is 26-bits; no indivisible entity in > .text can be bigger than that). It's probably an unrelated issue. > > Also, I know I said the backend should accept any size code, but 2GB > is definitely going to trigger more edge cases than average. > > Cheers. > > Tim. >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150713/602e32d9/attachment.html>
Eric Bentura
2015-Jul-13 12:57 UTC
[LLVMdev] ARM Jump table pcrelative relaxation in clang / llc
Hi, I have kept working on this and found the following (as llvm 3.5): 1) In the function MCObjectStreamer::EmitInstruction there is a check for the instruction being relaxable or not: if (!Assembler.getBackend().mayNeedRelaxation(Inst)) { EmitInstToData(Inst, STI); return; } At this stage, the instruction as been already selected to be ARM::ADR. The call to mayNeedRelaxation() resolve to ARMAsmBackend::getRelaxedOpcode(). There is no processing in there for ARM:ADR. I added the following line: *case ARM::ADR: return ARM::t2ADR;* As a result, if relaxation is enabled or bundling is enabled then the instruction is relaxed. And compilation to object passes. I am not familiar enough with this to understand why there is a condition to enter the relaxtion step : I had to set manually Assembler.setRelaxAll(true) to get into this step. 2) It seems that Fast instruction selection is enabled by default (even when using -O3). The problem does not appear when not using Fast sel (again used a hack in the code) although the same ADR instruction is selected since the offset to apply to the fixup is small enough. I am not sure I am on the right track, but as far as I understand: 1)ARM::ADR is not handled by relaxation 2)Relaxtion happens under some condition in the ObjectStreamer that I don't fully understand What do you think? Thanks, Eric 2015-07-13 15:41 GMT+03:00 Eric Bentura <ebentura at gmail.com>:> Hi, > I have kept working on this and found the following (as llvm 3.5): > 1) In the function MCObjectStreamer::EmitInstruction there is a check for > the instruction being relaxable or not: > if (!Assembler.getBackend().mayNeedRelaxation(Inst)) { > EmitInstToData(Inst, STI); > return; > } > At this stage, the instruction as been already selected to be ARM::ADR. > The call to mayNeed > > > 2015-07-07 18:06 GMT+03:00 Tim Northover <t.p.northover at gmail.com>: > >> On 7 July 2015 at 06:06, Eric Bentura <ebentura at gmail.com> wrote: >> > I have created a small ll file to reproduce the problem. >> > I used the intrinsic function llvm.arm.space to introduce space between >> the >> > beginning of the code and the jump table. >> >> It does look like the value in @llvm.arm.space is interpreted >> incorrectly if it's bigger than INT_MAX, but that's well outside its >> intended range and could inevitably be used to break ConstantIslands >> (the longest ARM immediate branch is 26-bits; no indivisible entity in >> .text can be bigger than that). It's probably an unrelated issue. >> >> Also, I know I said the backend should accept any size code, but 2GB >> is definitely going to trigger more edge cases than average. >> >> Cheers. >> >> Tim. >> > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150713/c8ba8b5c/attachment.html>
Tim Northover
2015-Jul-13 16:16 UTC
[LLVMdev] ARM Jump table pcrelative relaxation in clang / llc
> There is no processing in there for ARM:ADR. I added the following line: > case ARM::ADR: return ARM::t2ADR; > As a result, if relaxation is enabled or bundling is enabled then the instruction is relaxed.Unfortunately, that's not going to work at runtime, for a couple of reasons: 1. An ARM::ADR instruction is ARM-mode, but ARM::t2ADR is Thumb-mode. They can't be mixed in the same function (to a first approximation). It'll be interpreted as an entirely different ARM instruction if a CPU ever sees it. 2. Even if it did what you were hoping, it only staves of the issue: t2ADR has a limited range too, it's just longer than ADR.> I am not sure I am on the right track, but as far as I understand: > 1)ARM::ADR is not handled by relaxation > 2)Relaxtion happens under some condition in the ObjectStreamer that I don't fully understandAs suggested by the second problem above, relaxation is not the correct approach. There is no instruction that we can guarantee will reach the jump table. There are two plausible ways to fix it (that I could think of): 1. Enhance ARMConstantIslands.cpp to move the jump table in range if needed (this is what we did on trunk, see r238680). 2. Fuse the ADR to the jump-table with a pseudo-instruction when they're first created and expand them much later. This is uglier, but might be a simpler way to do it. Of course, the real solution is the usual recommendation to track trunk wherever possible. Getting stuck on 3.5 is a recipe for ongoing pain. Cheers. Tim.