[llvm-bugs] [Bug 34107] New: (Windows) ARM division libcall handling broken - result registers clobbered?
llvm-bugs at lists.llvm.org
Mon Aug 7 12:53:15 PDT 2017
Bug ID: 34107
Summary: (Windows) ARM division libcall handling broken -
result registers clobbered?
Component: Backend: ARM
Assignee: unassignedbugs at nondot.org
Reporter: martin at martin.st
CC: llvm-bugs at lists.llvm.org
Since SVN r305625, libcalls to e.g. __rt_udiv64 for 64 bit division on Windows
on ARM, which place their results in r0-r1 (and the remainder in r2-r3), can
occasionally get broken.
I've bisected this regression down to the following commit:
RegScavenging: Add scavengeRegisterBackwards()
Re-apply r276044/r279124/r305516. Fixed a problem where we would refuse
to place spills as the very first instruciton of a basic block and thus
artifically increase pressure (test in
This is a variant of scavengeRegister() that works for
enterBasicBlockEnd()/backward(). The benefit of the backward mode is
that it is not affected by incomplete kill flags.
This patch also changes
PrologEpilogInserter::doScavengeFrameVirtualRegs() to use the register
scavenger in backwards mode.
Differential Revision: http://reviews.llvm.org/D21885
So far I've been able to reproduce the issue with a pretty big file.
An example of the output of a code snippet which I think might be part of the
issue I'm seeing is this:
3136: 00 f0 00 f8 bl #0
00003136: IMAGE_REL_ARM_BLX23T __rt_udiv64 <-- output
313a: 0d f5 86 61 add.w r1, sp, #1072 <-- clobbering r1 with an
313e: 4f f0 01 0e mov.w lr, #1
3142: 01 f5 89 2c add.w r12, r1, #280576
3146: 11 eb d0 72 adds.w r2, r1, r0, lsr #31 <-- using r1 from
the __rt_udiv64 call
The diff in the generated code for this segment from before and after this
commit is as follows:
00 f0 00 f8 bl #0
+ 0d f5 86 61 add.w r1, sp, #1072
4f f0 01 0e mov.w lr, #1
- cd f8 00 e0 str.w lr, [sp]
- 0d f5 86 6e add.w lr, sp, #1072
+ 01 f5 89 2c add.w r12, r1, #280576
11 eb d0 72 adds.w r2, r1, r0, lsr #31
16 bf itet ne
Thus, this clearly looks broken.
The output from the __rt_udiv64 call gets passed to the following function:
static av_always_inline av_const int32_t av_clipl_int32_arm(int64_t a)
int x, y;
__asm__ ("adds %1, %R2, %Q2, lsr #31 \n\t"
"itet ne \n\t"
"mvnne %1, #1<<31 \n\t"
"moveq %0, %Q2 \n\t"
"eorne %0, %1, %R2, asr #31 \n\t"
: "=r"(x), "=&r"(y) : "r"(a) : "cc");
Is this an issue with the division libcall itself, missing to flag that all of
these registers actually are used? Or is the inline assembly somehow losing
track of that both halves of the 64 bit variable are used? (When used as input
to the inline assembly snippet where it is passed with a "r" type, used via the
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the llvm-bugs