[LLVMbugs] [Bug 14992] New: Tablegen incorrectly converts ARM tLDMIA_UPD pseudo to tLDMIA
bugzilla-daemon at llvm.org
bugzilla-daemon at llvm.org
Fri Jan 18 12:56:33 PST 2013
http://llvm.org/bugs/show_bug.cgi?id=14992
Bug #: 14992
Summary: Tablegen incorrectly converts ARM tLDMIA_UPD pseudo to
tLDMIA
Product: tools
Version: trunk
Platform: PC
OS/Version: Windows NT
Status: NEW
Severity: enhancement
Priority: P
Component: TableGen
AssignedTo: unassignedbugs at nondot.org
ReportedBy: dpeixott at codeaurora.org
CC: llvmbugs at cs.uiuc.edu
Classification: Unclassified
I'm seeing a problem in the ARM backend with an incorrect conversion between
the tLDMIA_UPD psuedo instruction and the tLDMIA instruction. The conversion is
duplicating a register when it generates the tLDMIA instruction, and the
duplicate register causes an assembler error. The problem looks like it is in
the c++ code that tablegen generates to convert between the two instructions.
We can demonstrate the problem with a small c program:
$ cat bug.c
void bar(int*);
int foo(int *a) {
int b = a[0];
int c = a[1];
bar(a+2);
return b+c;
}
$ clang -mcpu=cortex-a9 -mthumb -Os bug.c -S -o-
foo:
push {r4, r5, r7, lr}
ldm r0!, {r4, r4, r5}
add r7, sp, #8
bl bar
adds r0, r5, r4
pop {r4, r5, r7, pc}
The ldm instruction incorrectly lists r4 twice. If we try to assemble the file
with the gnu assembler using -no-integrated-as we get a warning like this:
/tmp/bug-8h7TgZ.s: Assembler messages:
/tmp/bug-8h7TgZ.s:21: Warning: duplicated register (r4) in register list
I believe the problem is in the PseudoLoweringEmitter::emitLoweringEmitter
function when it copies over the variable_ops (i.e. the reglist). The
tLDMIA_UPD pseudo instruction is a bit different than the other pseudo
instructions because it has more arguments that the instruction that it maps to
(tLDMIA). The _UPD version has an extra argument for the base register to
represent the writeback.
When we go to do the convert, we have a situation like this:
tLDMIA_UPD r0<def>, r0, pred, predreg, r4, r5
tLDMIA r0, pred, predreg, r4, r5
The conversion correctly copies the base register, predicate operands and the
r4 register. The problem is, when it goes to copy the remaining variable_ops
arguments, it starts copying at index 4 which is where the variable_ops for the
destination (tLDMIA) start, but the variable_ops of the source (tLDMIA_UPD)
start at index 5. This error causes the register r4 to be copied twice.
I think we can fix the problem by starting to copy the the variable_ops from
where they start in the source operand instead of where they start in the
destination operand. For most instructions it should not matter because they
have the same number of operands, but the tLDMIA_UPD is a special case. I
think this fix would be correct even if the source instruction has fewer
operands than the destination instruction, but I haven't seen any instructions
defined this way to test it out.
I tried the fix for the ARM backend and it correctly generates the ldm
instruction. It would be great to have someone that knows tablegen try the fix
and see if it is reasonable.
--
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.
More information about the llvm-bugs
mailing list