Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 6215f78

Browse files
committed
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218521 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent a5ab9ba commit 6215f78

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5674,6 +5674,48 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
56745674
}
56755675
}
56765676

5677+
// If first 2 operands of a 3 operand instruction are the same
5678+
// then transform to 2 operand version of the same instruction
5679+
// e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1'
5680+
// FIXME: We would really like to be able to tablegen'erate this.
5681+
if (isThumbOne() && Operands.size() == 6 &&
5682+
(Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" ||
5683+
Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5684+
Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" ||
5685+
Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic")) {
5686+
ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
5687+
ARMOperand &Op4 = static_cast<ARMOperand &>(*Operands[4]);
5688+
ARMOperand &Op5 = static_cast<ARMOperand &>(*Operands[5]);
5689+
5690+
// If both registers are the same then remove one of them from
5691+
// the operand list.
5692+
if (Op3.isReg() && Op4.isReg() && Op3.getReg() == Op4.getReg()) {
5693+
// If 3rd operand (variable Op5) is a register and the instruction is adds/sub
5694+
// then do not transform as the backend already handles this instruction
5695+
// correctly.
5696+
if (!Op5.isReg() || !((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub")) {
5697+
Operands.erase(Operands.begin() + 3);
5698+
if (Mnemonic == "add" && !CarrySetting) {
5699+
// Special case for 'add' (not 'adds') instruction must
5700+
// remove the CCOut operand as well.
5701+
Operands.erase(Operands.begin() + 1);
5702+
}
5703+
}
5704+
}
5705+
}
5706+
5707+
// If instruction is 'add' and first two register operands
5708+
// use SP register, then remove one of the SP registers from
5709+
// the instruction.
5710+
// FIXME: We would really like to be able to tablegen'erate this.
5711+
if (isThumbOne() && Operands.size() == 5 && Mnemonic == "add" && !CarrySetting) {
5712+
ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
5713+
ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
5714+
if (Op2.isReg() && Op3.isReg() && Op2.getReg() == ARM::SP && Op3.getReg() == ARM::SP) {
5715+
Operands.erase(Operands.begin() + 2);
5716+
}
5717+
}
5718+
56775719
// GNU Assembler extension (compatibility)
56785720
if ((Mnemonic == "ldrd" || Mnemonic == "strd")) {
56795721
ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
@@ -8180,7 +8222,7 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
81808222
}
81818223
// Some high-register supporting Thumb1 encodings only allow both registers
81828224
// to be from r0-r7 when in Thumb2.
8183-
else if (Opc == ARM::tADDhirr && isThumbOne() &&
8225+
else if (Opc == ARM::tADDhirr && isThumbOne() && !hasV6MOps() &&
81848226
isARMLowRegister(Inst.getOperand(1).getReg()) &&
81858227
isARMLowRegister(Inst.getOperand(2).getReg()))
81868228
return Match_RequiresThumb2;

test/MC/ARM/thumb_rewrites.s

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
@ RUN: llvm-mc -triple thumbv6m -show-encoding < %s | FileCheck %s
2+
3+
adds r0, r0, #8
4+
@ CHECK: adds r0, #8 @ encoding: [0x08,0x30]
5+
6+
adds r0, r0, r0
7+
@ CHECK: adds r0, r0, r0 @ encoding: [0x00,0x18]
8+
9+
add r0, r0, r8
10+
@ CHECK: add r0, r8 @ encoding: [0x40,0x44]
11+
12+
add sp, sp, r0
13+
@ CHECK: add sp, r0 @ encoding: [0x85,0x44]
14+
15+
add r0, r0, r1
16+
@ CHECK: add r0, r1 @ encoding: [0x08,0x44]
17+
18+
add r2, r2, r3
19+
@ CHECK: add r2, r3 @ encoding: [0x1a,0x44]
20+
21+
subs r0, r0, r0
22+
@ CHECK: subs r0, r0, r0 @ encoding: [0x00,0x1a]
23+
24+
ands r0, r0, r1
25+
@ CHECK: ands r0, r1 @ encoding: [0x08,0x40]
26+
27+
eors r0, r0, r1
28+
@ CHECK: eors r0, r1 @ encoding: [0x48,0x40]
29+
30+
lsls r0, r0, r1
31+
@ CHECK: lsls r0, r1 @ encoding: [0x88,0x40]
32+
33+
lsrs r0, r0, r1
34+
@ CHECK: lsrs r0, r1 @ encoding: [0xc8,0x40]
35+
36+
asrs r0, r0, r1
37+
@ CHECK: asrs r0, r1 @ encoding: [0x08,0x41]
38+
39+
adcs r0, r0, r1
40+
@ CHECK: adcs r0, r1 @ encoding: [0x48,0x41]
41+
42+
sbcs r0, r0, r1
43+
@ CHECK: sbcs r0, r1 @ encoding: [0x88,0x41]
44+
45+
rors r0, r0, r1
46+
@ CHECK: rors r0, r1 @ encoding: [0xc8,0x41]
47+
48+
orrs r0, r0, r1
49+
@ CHECK: orrs r0, r1 @ encoding: [0x08,0x43]
50+
51+
bics r0, r0, r1
52+
@ CHECK: bics r0, r1 @ encoding: [0x88,0x43]

0 commit comments

Comments
 (0)