[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
This commit is contained in:
Bradley Smith 2014-04-09 14:44:18 +00:00
parent 250f973d7f
commit 7b5940c0c0
4 changed files with 97 additions and 19 deletions

View File

@ -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",

View File

@ -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<ARM64Operand *>(Operands[0]);
ARM64Operand *Op2 = static_cast<ARM64Operand *>(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<ARM64Operand *>(Operands[0]);
ARM64Operand *Op2 = static_cast<ARM64Operand *>(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<ARM64Operand *>(Operands[0]);
ARM64Operand *Op2 = static_cast<ARM64Operand *>(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<ARM64Operand *>(Operands[1]);
ARM64Operand *Op2 = static_cast<ARM64Operand *>(Operands[2]);
if (Op2->isImm()) {
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(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") {

View File

@ -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);

View File

@ -11,3 +11,7 @@
0x08 0x20 0x21 0x1e
# CHECK: fcmp s0, #0.0
0x1f 0x00 0x00 0x11
# CHECK: mov wsp, w0