llvm.org GIT mirror llvm / ab17c04
[ARM] Refactor converting Thumb1 from 3 to 2 operand (nfc) Also adds some test cases. Differential Revision: http://reviews.llvm.org/D11054 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241799 91177308-0d34-0410-b5e6-96231b3b80d8 Scott Douglass 5 years ago
2 changed file(s) with 64 addition(s) and 42 deletion(s). Raw diff Collapse all Expand all
241241 bool &CanAcceptCarrySet,
242242 bool &CanAcceptPredicationCode);
243243
244 void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting,
245 OperandVector &Operands);
244246 bool isThumb() const {
245247 // FIXME: Can tablegen auto-generate this?
246248 return STI.getFeatureBits()[ARM::ModeThumb];
54645466 CanAcceptPredicationCode = true;
54655467 }
54665468
5469 // \brief Some Thumb1 instructions have two operand forms that are not
5470 // available as three operand, convert to two operand form if possible.
5471 //
5472 // FIXME: We would really like to be able to tablegen'erate this.
5473 void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic,
5474 bool CarrySetting,
5475 OperandVector &Operands) {
5476 if (Operands.size() != 6 || !isThumbOne())
5477 return;
5478
5479 ARMOperand &Op3 = static_cast(*Operands[3]);
5480 ARMOperand &Op4 = static_cast(*Operands[4]);
5481 if (!Op3.isReg() || !Op4.isReg())
5482 return;
5483
5484 ARMOperand &Op5 = static_cast(*Operands[5]);
5485
5486 if (!(Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" ||
5487 Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5488 Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" ||
5489 Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic"))
5490 return;
5491
5492 // If first 2 operands of a 3 operand instruction are the same
5493 // then transform to 2 operand version of the same instruction
5494 // e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1'
5495 bool Transform = Op3.getReg() == Op4.getReg();
5496 // If both registers are the same then remove one of them from
5497 // the operand list, with certain exceptions.
5498 if (Transform) {
5499 // Don't transform 'adds Rd, Rd, Rm' or 'sub{s} Rd, Rd, Rm' because the
5500 // 2 operand forms don't exist.
5501 if (((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub") &&
5502 Op5.isReg())
5503 Transform = false;
5504 }
5505
5506 if (Transform)
5507 Operands.erase(Operands.begin() + 3);
5508 }
5509
54675510 bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
54685511 OperandVector &Operands) {
54695512 // FIXME: This is all horribly hacky. We really need a better way to deal
58375880 "VFP/Neon double precision register expected");
58385881 }
58395882
5883 tryConvertingToTwoOperandForm(Mnemonic, CarrySetting, Operands);
5884
58405885 // Some instructions, mostly Thumb, have forms for the same mnemonic that
58415886 // do and don't have a cc_out optional-def operand. With some spot-checks
58425887 // of the operand list, we can figure out which variant we're trying to
58985943 ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc());
58995944 Operands.erase(Operands.begin() + Idx + 1);
59005945 }
5901 }
5902
5903 // If first 2 operands of a 3 operand instruction are the same
5904 // then transform to 2 operand version of the same instruction
5905 // e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1'
5906 // FIXME: We would really like to be able to tablegen'erate this.
5907 if (isThumbOne() && Operands.size() == 6 &&
5908 (Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" ||
5909 Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5910 Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" ||
5911 Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic")) {
5912 ARMOperand &Op3 = static_cast(*Operands[3]);
5913 ARMOperand &Op4 = static_cast(*Operands[4]);
5914 ARMOperand &Op5 = static_cast(*Operands[5]);
5915
5916 // If both registers are the same then remove one of them from
5917 // the operand list.
5918 if (Op3.isReg() && Op4.isReg() && Op3.getReg() == Op4.getReg()) {
5919 // If 3rd operand (variable Op5) is a register and the instruction is adds/sub
5920 // then do not transform as the backend already handles this instruction
5921 // correctly.
5922 if (!Op5.isReg() || !((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub")) {
5923 Operands.erase(Operands.begin() + 3);
5924 if (Mnemonic == "add" && !CarrySetting) {
5925 // Special case for 'add' (not 'adds') instruction must
5926 // remove the CCOut operand as well.
5927 Operands.erase(Operands.begin() + 1);
5928 }
5929 }
5930 }
5931 }
5932
5933 // If instruction is 'add' and first two register operands
5934 // use SP register, then remove one of the SP registers from
5935 // the instruction.
5936 // FIXME: We would really like to be able to tablegen'erate this.
5937 if (isThumbOne() && Operands.size() == 5 && Mnemonic == "add" && !CarrySetting) {
5938 ARMOperand &Op2 = static_cast(*Operands[2]);
5939 ARMOperand &Op3 = static_cast(*Operands[3]);
5940 if (Op2.isReg() && Op3.isReg() && Op2.getReg() == ARM::SP && Op3.getReg() == ARM::SP) {
5941 Operands.erase(Operands.begin() + 2);
5942 }
59435946 }
59445947
59455948 // GNU Assembler extension (compatibility)
1111 add sp, sp, r0
1212 @ CHECK: add sp, r0 @ encoding: [0x85,0x44]
1313
14 add r4, sp, r4
15 @ CHECK: add r4, sp, r4 @ encoding: [0x6c,0x44]
16
17 add r4, r4, sp
18 @ CHECK: add r4, sp @ encoding: [0x6c,0x44]
19
20 add sp, sp, #32
21 @ FIXME: ARMARM says 'add sp, sp, #32'
22 @ CHECK: add sp, #32 @ encoding: [0x08,0xb0]
23
24 add r5, sp, #1016
25 @ CHECK: add r5, sp, #1016 @ encoding: [0xfe,0xad]
26
1427 add r0, r0, r1
1528 @ CHECK: add r0, r1 @ encoding: [0x08,0x44]
1629
1932
2033 subs r0, r0, r0
2134 @ CHECK: subs r0, r0, r0 @ encoding: [0x00,0x1a]
35
36 subs r2, r2, #8
37 @ CHECK: subs r2, #8 @ encoding: [0x08,0x3a]
38
39 sub sp, sp, #16
40 @ CHECK: sub sp, #16 @ encoding: [0x84,0xb0]
2241
2342 ands r0, r0, r1
2443 @ CHECK: ands r0, r1 @ encoding: [0x08,0x40]