1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

Elide repeated register operand in Thumb1 instructions

This patch makes the ARM backend transform 3 operand instructions such as
'adds/subs' to the 2 operand version of the same instruction if the first
two register operands are the same.

Example: 'adds r0, r0, #1' will is transformed to 'adds r0, #1'.

Currently for some instructions such as 'adds' if you try to assemble
'adds r0, r0, #8' for thumb v6m the assembler would throw an error message
because the immediate cannot be encoded using 3 bits.

The backend should be smart enough to transform the instruction to
'adds r0, #8', which allows for larger immediate constants.

Patch by Ranjeet Singh.

llvm-svn: 218521
This commit is contained in:
Renato Golin 2014-09-26 16:14:29 +00:00
parent c61458a223
commit eb17383852
2 changed files with 95 additions and 1 deletions

View File

@ -5674,6 +5674,48 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
}
}
// If first 2 operands of a 3 operand instruction are the same
// then transform to 2 operand version of the same instruction
// e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1'
// FIXME: We would really like to be able to tablegen'erate this.
if (isThumbOne() && Operands.size() == 6 &&
(Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" ||
Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" ||
Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic")) {
ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
ARMOperand &Op4 = static_cast<ARMOperand &>(*Operands[4]);
ARMOperand &Op5 = static_cast<ARMOperand &>(*Operands[5]);
// If both registers are the same then remove one of them from
// the operand list.
if (Op3.isReg() && Op4.isReg() && Op3.getReg() == Op4.getReg()) {
// If 3rd operand (variable Op5) is a register and the instruction is adds/sub
// then do not transform as the backend already handles this instruction
// correctly.
if (!Op5.isReg() || !((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub")) {
Operands.erase(Operands.begin() + 3);
if (Mnemonic == "add" && !CarrySetting) {
// Special case for 'add' (not 'adds') instruction must
// remove the CCOut operand as well.
Operands.erase(Operands.begin() + 1);
}
}
}
}
// If instruction is 'add' and first two register operands
// use SP register, then remove one of the SP registers from
// the instruction.
// FIXME: We would really like to be able to tablegen'erate this.
if (isThumbOne() && Operands.size() == 5 && Mnemonic == "add" && !CarrySetting) {
ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
if (Op2.isReg() && Op3.isReg() && Op2.getReg() == ARM::SP && Op3.getReg() == ARM::SP) {
Operands.erase(Operands.begin() + 2);
}
}
// GNU Assembler extension (compatibility)
if ((Mnemonic == "ldrd" || Mnemonic == "strd")) {
ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
@ -8180,7 +8222,7 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
}
// Some high-register supporting Thumb1 encodings only allow both registers
// to be from r0-r7 when in Thumb2.
else if (Opc == ARM::tADDhirr && isThumbOne() &&
else if (Opc == ARM::tADDhirr && isThumbOne() && !hasV6MOps() &&
isARMLowRegister(Inst.getOperand(1).getReg()) &&
isARMLowRegister(Inst.getOperand(2).getReg()))
return Match_RequiresThumb2;

View File

@ -0,0 +1,52 @@
@ RUN: llvm-mc -triple thumbv6m -show-encoding < %s | FileCheck %s
adds r0, r0, #8
@ CHECK: adds r0, #8 @ encoding: [0x08,0x30]
adds r0, r0, r0
@ CHECK: adds r0, r0, r0 @ encoding: [0x00,0x18]
add r0, r0, r8
@ CHECK: add r0, r8 @ encoding: [0x40,0x44]
add sp, sp, r0
@ CHECK: add sp, r0 @ encoding: [0x85,0x44]
add r0, r0, r1
@ CHECK: add r0, r1 @ encoding: [0x08,0x44]
add r2, r2, r3
@ CHECK: add r2, r3 @ encoding: [0x1a,0x44]
subs r0, r0, r0
@ CHECK: subs r0, r0, r0 @ encoding: [0x00,0x1a]
ands r0, r0, r1
@ CHECK: ands r0, r1 @ encoding: [0x08,0x40]
eors r0, r0, r1
@ CHECK: eors r0, r1 @ encoding: [0x48,0x40]
lsls r0, r0, r1
@ CHECK: lsls r0, r1 @ encoding: [0x88,0x40]
lsrs r0, r0, r1
@ CHECK: lsrs r0, r1 @ encoding: [0xc8,0x40]
asrs r0, r0, r1
@ CHECK: asrs r0, r1 @ encoding: [0x08,0x41]
adcs r0, r0, r1
@ CHECK: adcs r0, r1 @ encoding: [0x48,0x41]
sbcs r0, r0, r1
@ CHECK: sbcs r0, r1 @ encoding: [0x88,0x41]
rors r0, r0, r1
@ CHECK: rors r0, r1 @ encoding: [0xc8,0x41]
orrs r0, r0, r1
@ CHECK: orrs r0, r1 @ encoding: [0x08,0x43]
bics r0, r0, r1
@ CHECK: bics r0, r1 @ encoding: [0x88,0x43]