From 7b5940c0c094b3fefb98c7cbc9cbab73e58e4cd6 Mon Sep 17 00:00:00 2001 From: Bradley Smith Date: Wed, 9 Apr 2014 14:44:18 +0000 Subject: [PATCH] [ARM64] Fix canonicalisation of MOVs. MOV is too complex to be modelled by a dumb alias. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205889 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM64/ARM64InstrInfo.td | 7 --- lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp | 71 +++++++++++++++++++---- lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp | 34 ++++++++++- test/MC/Disassembler/ARM64/canonical-form.txt | 4 ++ 4 files changed, 97 insertions(+), 19 deletions(-) diff --git a/lib/Target/ARM64/ARM64InstrInfo.td b/lib/Target/ARM64/ARM64InstrInfo.td index 35a73f923c8..241ada9ca2d 100644 --- a/lib/Target/ARM64/ARM64InstrInfo.td +++ b/lib/Target/ARM64/ARM64InstrInfo.td @@ -604,13 +604,6 @@ defm ORN : LogicalReg<0b01, 1, "orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>; defm ORR : LogicalReg<0b01, 0, "orr", or>; -def : InstAlias<"mov $dst, $src", (ORRWrs GPR32:$dst, WZR, GPR32:$src, 0)>; -def : InstAlias<"mov $dst, $src", - (ADDWri GPR32sp:$dst, GPR32sp:$src, 0, 0)>; -def : InstAlias<"mov $dst, $src", (ORRXrs GPR64:$dst, XZR, GPR64:$src, 0)>; -def : InstAlias<"mov $dst, $src", - (ADDXri GPR64sp:$dst, GPR64sp:$src, 0, 0)>; - def : InstAlias<"tst $src1, $src2", (ANDSWri WZR, GPR32:$src1, logical_imm32:$src2)>; def : InstAlias<"tst $src1, $src2", diff --git a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp index ee985772878..e5005796058 100644 --- a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp +++ b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp @@ -3732,9 +3732,9 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst, } } -static void rewriteMOV(ARM64AsmParser::OperandVector &Operands, - StringRef mnemonic, uint64_t imm, unsigned shift, - MCContext &Context) { +static void rewriteMOVI(ARM64AsmParser::OperandVector &Operands, + StringRef mnemonic, uint64_t imm, unsigned shift, + MCContext &Context) { ARM64Operand *Op = static_cast(Operands[0]); ARM64Operand *Op2 = static_cast(Operands[2]); Operands[0] = @@ -3750,6 +3750,43 @@ static void rewriteMOV(ARM64AsmParser::OperandVector &Operands, delete Op; } +static void rewriteMOVRSP(ARM64AsmParser::OperandVector &Operands, + MCContext &Context) { + ARM64Operand *Op = static_cast(Operands[0]); + ARM64Operand *Op2 = static_cast(Operands[2]); + Operands[0] = + ARM64Operand::CreateToken("add", false, Op->getStartLoc(), Context); + + const MCExpr *Imm = MCConstantExpr::Create(0, Context); + Operands.push_back(ARM64Operand::CreateImm(Imm, Op2->getStartLoc(), + Op2->getEndLoc(), Context)); + Operands.push_back(ARM64Operand::CreateShifter( + ARM64_AM::LSL, 0, Op2->getStartLoc(), Op2->getEndLoc(), Context)); + + delete Op; +} + +static void rewriteMOVR(ARM64AsmParser::OperandVector &Operands, + MCContext &Context) { + ARM64Operand *Op = static_cast(Operands[0]); + ARM64Operand *Op2 = static_cast(Operands[2]); + Operands[0] = + ARM64Operand::CreateToken("orr", false, Op->getStartLoc(), Context); + + // Operands[2] becomes Operands[3]. + Operands.push_back(Operands[2]); + // And Operands[2] becomes ZR. + unsigned ZeroReg = ARM64::XZR; + if (isGPR32Register(Operands[2]->getReg())) + ZeroReg = ARM64::WZR; + + Operands[2] = + ARM64Operand::CreateReg(ZeroReg, false, Op2->getStartLoc(), + Op2->getEndLoc(), Context); + + delete Op; +} + bool ARM64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) { switch (ErrCode) { case Match_MissingFeature: @@ -3840,6 +3877,7 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // FIXME: Catching this here is a total hack, and we should use tblgen // support to implement this instead as soon as it is available. + ARM64Operand *Op1 = static_cast(Operands[1]); ARM64Operand *Op2 = static_cast(Operands[2]); if (Op2->isImm()) { if (const MCConstantExpr *CE = dyn_cast(Op2->getImm())) { @@ -3856,36 +3894,47 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // MOVK Rd, imm << 0 if ((Val & 0xFFFF) == Val) - rewriteMOV(Operands, "movz", Val, 0, getContext()); + rewriteMOVI(Operands, "movz", Val, 0, getContext()); // MOVK Rd, imm << 16 else if ((Val & 0xFFFF0000ULL) == Val) - rewriteMOV(Operands, "movz", Val, 16, getContext()); + rewriteMOVI(Operands, "movz", Val, 16, getContext()); // MOVK Rd, imm << 32 else if ((Val & 0xFFFF00000000ULL) == Val) - rewriteMOV(Operands, "movz", Val, 32, getContext()); + rewriteMOVI(Operands, "movz", Val, 32, getContext()); // MOVK Rd, imm << 48 else if ((Val & 0xFFFF000000000000ULL) == Val) - rewriteMOV(Operands, "movz", Val, 48, getContext()); + rewriteMOVI(Operands, "movz", Val, 48, getContext()); // MOVN Rd, (~imm << 0) else if ((NVal & 0xFFFFULL) == NVal) - rewriteMOV(Operands, "movn", NVal, 0, getContext()); + rewriteMOVI(Operands, "movn", NVal, 0, getContext()); // MOVN Rd, ~(imm << 16) else if ((NVal & 0xFFFF0000ULL) == NVal) - rewriteMOV(Operands, "movn", NVal, 16, getContext()); + rewriteMOVI(Operands, "movn", NVal, 16, getContext()); // MOVN Rd, ~(imm << 32) else if ((NVal & 0xFFFF00000000ULL) == NVal) - rewriteMOV(Operands, "movn", NVal, 32, getContext()); + rewriteMOVI(Operands, "movn", NVal, 32, getContext()); // MOVN Rd, ~(imm << 48) else if ((NVal & 0xFFFF000000000000ULL) == NVal) - rewriteMOV(Operands, "movn", NVal, 48, getContext()); + rewriteMOVI(Operands, "movn", NVal, 48, getContext()); } + } else if (Op1->isReg() && Op2->isReg()) { + // reg->reg move. + unsigned Reg1 = Op1->getReg(); + unsigned Reg2 = Op2->getReg(); + if ((Reg1 == ARM64::SP && isGPR64Reg(Reg2)) || + (Reg2 == ARM64::SP && isGPR64Reg(Reg1)) || + (Reg1 == ARM64::WSP && isGPR32Register(Reg2)) || + (Reg2 == ARM64::WSP && isGPR32Register(Reg1))) + rewriteMOVRSP(Operands, getContext()); + else + rewriteMOVR(Operands, getContext()); } } else if (NumOperands == 4) { if (Tok == "add" || Tok == "adds" || Tok == "sub" || Tok == "subs") { diff --git a/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp b/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp index 7d1dd50b720..f702522ef33 100644 --- a/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp +++ b/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp @@ -52,7 +52,7 @@ void ARM64InstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { void ARM64InstPrinter::printInst(const MCInst *MI, raw_ostream &O, StringRef Annot) { - // Check for special encodings and print the cannonical alias instead. + // Check for special encodings and print the canonical alias instead. unsigned Opcode = MI->getOpcode(); @@ -250,6 +250,38 @@ void ARM64InstPrinter::printInst(const MCInst *MI, raw_ostream &O, printExtend(MI, 3, O); return; } + // ADD WSP, Wn, #0 ==> MOV WSP, Wn + if (Opcode == ARM64::ADDWri && (MI->getOperand(0).getReg() == ARM64::WSP || + MI->getOperand(1).getReg() == ARM64::WSP) && + MI->getOperand(2).getImm() == 0 && + ARM64_AM::getShiftValue(MI->getOperand(3).getImm()) == 0) { + O << "\tmov\t" << getRegisterName(MI->getOperand(0).getReg()) + << ", " << getRegisterName(MI->getOperand(1).getReg()); + return; + } + // ADD XSP, Wn, #0 ==> MOV XSP, Wn + if (Opcode == ARM64::ADDXri && (MI->getOperand(0).getReg() == ARM64::SP || + MI->getOperand(1).getReg() == ARM64::SP) && + MI->getOperand(2).getImm() == 0 && + ARM64_AM::getShiftValue(MI->getOperand(3).getImm()) == 0) { + O << "\tmov\t" << getRegisterName(MI->getOperand(0).getReg()) + << ", " << getRegisterName(MI->getOperand(1).getReg()); + return; + } + // ORR Wn, WZR, Wm ==> MOV Wn, Wm + if (Opcode == ARM64::ORRWrs && MI->getOperand(1).getReg() == ARM64::WZR && + MI->getOperand(3).getImm() == 0) { + O << "\tmov\t" << getRegisterName(MI->getOperand(0).getReg()) + << ", " << getRegisterName(MI->getOperand(2).getReg()); + return; + } + // ORR Xn, XZR, Xm ==> MOV Xn, Xm + if (Opcode == ARM64::ORRXrs && MI->getOperand(1).getReg() == ARM64::XZR && + MI->getOperand(3).getImm() == 0) { + O << "\tmov\t" << getRegisterName(MI->getOperand(0).getReg()) + << ", " << getRegisterName(MI->getOperand(2).getReg()); + return; + } if (!printAliasInstr(MI, O)) printInstruction(MI, O); diff --git a/test/MC/Disassembler/ARM64/canonical-form.txt b/test/MC/Disassembler/ARM64/canonical-form.txt index 3172fd2521f..80c032d71a9 100644 --- a/test/MC/Disassembler/ARM64/canonical-form.txt +++ b/test/MC/Disassembler/ARM64/canonical-form.txt @@ -11,3 +11,7 @@ 0x08 0x20 0x21 0x1e # CHECK: fcmp s0, #0.0 + +0x1f 0x00 0x00 0x11 + +# CHECK: mov wsp, w0 -- 2.11.0