Index: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5504,23 +5504,41 @@ // then transform to 2 operand version of the same instruction // e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1' bool Transform = Op3.getReg() == Op4.getReg(); + + // For communtative operations, we might be able to transform if we swap + // Op4 and Op5. The 'ADD Rdm, SP, Rdm' form is already handled specially + // as tADDrsp. + const ARMOperand *LastOp = &Op5; + bool Swap = false; + if (!Transform && Op5.isReg() && Op3.getReg() == Op5.getReg() && + ((Mnemonic == "add" && Op4.getReg() != ARM::SP) || + Mnemonic == "and" || Mnemonic == "eor" || + Mnemonic == "adc" || Mnemonic == "orr")) { + Swap = true; + LastOp = &Op4; + Transform = true; + } + // If both registers are the same then remove one of them from // the operand list, with certain exceptions. if (Transform) { // Don't transform 'adds Rd, Rd, Rm' or 'sub{s} Rd, Rd, Rm' because the // 2 operand forms don't exist. if (((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub") && - Op5.isReg()) + LastOp->isReg()) Transform = false; // Don't transform 'add/sub{s} Rd, Rd, #imm' if the immediate fits into // 3-bits because the ARMARM says not to. - if ((Mnemonic == "add" || Mnemonic == "sub") && Op5.isImm0_7()) + if ((Mnemonic == "add" || Mnemonic == "sub") && LastOp->isImm0_7()) Transform = false; } - if (Transform) + if (Transform) { + if (Swap) + std::swap(Op4, Op5); Operands.erase(Operands.begin() + 3); + } } bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, Index: llvm/trunk/test/MC/ARM/thumb2-narrow-dp.ll =================================================================== --- llvm/trunk/test/MC/ARM/thumb2-narrow-dp.ll +++ llvm/trunk/test/MC/ARM/thumb2-narrow-dp.ll @@ -67,8 +67,12 @@ // CHECK: add r3, r1 @ encoding: [0x0b,0x44] ADD r4, r4, pc // T2 // CHECK: add r4, pc @ encoding: [0x7c,0x44] + ADD r4, pc, r4 // T2 +// CHECK: add r4, pc @ encoding: [0x7c,0x44] ADD pc, pc, r2 // T2 // CHECK: add pc, r2 @ encoding: [0x97,0x44] + ADD pc, r2, pc // T2 +// CHECK: add pc, r2 @ encoding: [0x97,0x44] // ADD (SP plus immediate) A8.8.9 ADD sp, sp, #20 // T2 Index: llvm/trunk/test/MC/ARM/thumb_rewrites.s =================================================================== --- llvm/trunk/test/MC/ARM/thumb_rewrites.s +++ llvm/trunk/test/MC/ARM/thumb_rewrites.s @@ -15,6 +15,9 @@ add r0, r0, r8 @ CHECK: add r0, r8 @ encoding: [0x40,0x44] + add r1, r8, r1 +@ CHECK: add r1, r8 @ encoding: [0x41,0x44] + add sp, sp, r0 @ CHECK: add sp, r0 @ encoding: [0x85,0x44] @@ -52,12 +55,18 @@ sub sp, sp, #16 @ CHECK: sub sp, #16 @ encoding: [0x84,0xb0] + ands r0, r1, r0 +@ CHECK: ands r0, r1 @ encoding: [0x08,0x40] + ands r0, r0, r1 @ CHECK: ands r0, r1 @ encoding: [0x08,0x40] eors r0, r0, r1 @ CHECK: eors r0, r1 @ encoding: [0x48,0x40] + eors r0, r1, r0 +@ CHECK: eors r0, r1 @ encoding: [0x48,0x40] + lsls r0, r0, r1 @ CHECK: lsls r0, r1 @ encoding: [0x88,0x40] @@ -70,6 +79,9 @@ adcs r0, r0, r1 @ CHECK: adcs r0, r1 @ encoding: [0x48,0x41] + adcs r0, r1, r0 +@ CHECK: adcs r0, r1 @ encoding: [0x48,0x41] + sbcs r0, r0, r1 @ CHECK: sbcs r0, r1 @ encoding: [0x88,0x41] @@ -79,5 +91,8 @@ orrs r0, r0, r1 @ CHECK: orrs r0, r1 @ encoding: [0x08,0x43] + orrs r0, r1, r0 +@ CHECK: orrs r0, r1 @ encoding: [0x08,0x43] + bics r0, r0, r1 @ CHECK: bics r0, r1 @ encoding: [0x88,0x43]