return true;
}
+static bool isARegister(unsigned Reg) {
+ return Reg == X86::AL || Reg == X86::AX || Reg == X86::EAX || Reg == X86::RAX;
+}
+
/// Simplify things like MOV32rm to MOV32o32a.
bool X86::optimizeMOV(MCInst &MI, bool In64BitMode) {
// Don't make these simplifications in 64-bit mode; other assemblers don't
unsigned AddrOp = AddrBase + 3;
// Check whether the destination register can be fixed.
unsigned Reg = MI.getOperand(RegOp).getReg();
- if (Reg != X86::AL && Reg != X86::AX && Reg != X86::EAX && Reg != X86::RAX)
+ if (!isARegister(Reg))
return false;
// Check whether this is an absolute address.
// FIXME: We know TLVP symbol refs aren't, but there should be a better way
MI.addOperand(Seg);
return true;
}
+
+/// Simplify FOO $imm, %{al,ax,eax,rax} to FOO $imm, for instruction with
+/// a short fixed-register form.
+bool X86::optimizeToFixedRegisterForm(MCInst &MI) {
+ unsigned NewOpc;
+ switch (MI.getOpcode()) {
+ default:
+ return false;
+ FROM_TO(ADC8ri, ADC8i8)
+ FROM_TO(ADC16ri, ADC16i16)
+ FROM_TO(ADC32ri, ADC32i32)
+ FROM_TO(ADC64ri32, ADC64i32)
+ FROM_TO(ADD8ri, ADD8i8)
+ FROM_TO(ADD16ri, ADD16i16)
+ FROM_TO(ADD32ri, ADD32i32)
+ FROM_TO(ADD64ri32, ADD64i32)
+ FROM_TO(AND8ri, AND8i8)
+ FROM_TO(AND16ri, AND16i16)
+ FROM_TO(AND32ri, AND32i32)
+ FROM_TO(AND64ri32, AND64i32)
+ FROM_TO(CMP8ri, CMP8i8)
+ FROM_TO(CMP16ri, CMP16i16)
+ FROM_TO(CMP32ri, CMP32i32)
+ FROM_TO(CMP64ri32, CMP64i32)
+ FROM_TO(OR8ri, OR8i8)
+ FROM_TO(OR16ri, OR16i16)
+ FROM_TO(OR32ri, OR32i32)
+ FROM_TO(OR64ri32, OR64i32)
+ FROM_TO(SBB8ri, SBB8i8)
+ FROM_TO(SBB16ri, SBB16i16)
+ FROM_TO(SBB32ri, SBB32i32)
+ FROM_TO(SBB64ri32, SBB64i32)
+ FROM_TO(SUB8ri, SUB8i8)
+ FROM_TO(SUB16ri, SUB16i16)
+ FROM_TO(SUB32ri, SUB32i32)
+ FROM_TO(SUB64ri32, SUB64i32)
+ FROM_TO(TEST8ri, TEST8i8)
+ FROM_TO(TEST16ri, TEST16i16)
+ FROM_TO(TEST32ri, TEST32i32)
+ FROM_TO(TEST64ri32, TEST64i32)
+ FROM_TO(XOR8ri, XOR8i8)
+ FROM_TO(XOR16ri, XOR16i16)
+ FROM_TO(XOR32ri, XOR32i32)
+ FROM_TO(XOR64ri32, XOR64i32)
+ }
+ // Check whether the destination register can be fixed.
+ unsigned Reg = MI.getOperand(0).getReg();
+ if (!isARegister(Reg))
+ return false;
+
+ // If so, rewrite the instruction.
+ MCOperand Saved = MI.getOperand(MI.getNumOperands() - 1);
+ MI.clear();
+ MI.setOpcode(NewOpc);
+ MI.addOperand(Saved);
+ return true;
+}
return MCOperand::createExpr(Expr);
}
-/// Simplify FOO $imm, %{al,ax,eax,rax} to FOO $imm, for instruction with
-/// a short fixed-register form.
-static void SimplifyShortImmForm(MCInst &Inst, unsigned Opcode) {
- unsigned ImmOp = Inst.getNumOperands() - 1;
- assert(Inst.getOperand(0).isReg() &&
- (Inst.getOperand(ImmOp).isImm() || Inst.getOperand(ImmOp).isExpr()) &&
- ((Inst.getNumOperands() == 3 && Inst.getOperand(1).isReg() &&
- Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) ||
- Inst.getNumOperands() == 2) &&
- "Unexpected instruction!");
-
- // Check whether the destination register can be fixed.
- unsigned Reg = Inst.getOperand(0).getReg();
- if (Reg != X86::AL && Reg != X86::AX && Reg != X86::EAX && Reg != X86::RAX)
- return;
-
- // If so, rewrite the instruction.
- MCOperand Saved = Inst.getOperand(ImmOp);
- Inst = MCInst();
- Inst.setOpcode(Opcode);
- Inst.addOperand(Saved);
-}
-
static unsigned getRetOpcode(const X86Subtarget &Subtarget) {
return Subtarget.is64Bit() ? X86::RET64 : X86::RET32;
}
if (auto MaybeMCOp = LowerMachineOperand(MI, MO))
OutMI.addOperand(*MaybeMCOp);
- if (X86::optimizeInstFromVEX3ToVEX2(OutMI, MI->getDesc()))
- return;
-
- if (X86::optimizeShiftRotateWithImmediateOne(OutMI))
- return;
-
- if (X86::optimizeVPCMPWithImmediateOneOrSix(OutMI))
- return;
-
- if (X86::optimizeMOVSX(OutMI))
- return;
-
bool In64BitMode = AsmPrinter.getSubtarget().is64Bit();
- if (X86::optimizeINCDEC(OutMI, In64BitMode))
- return;
-
- if (X86::optimizeMOV(OutMI, In64BitMode))
+ if (X86::optimizeInstFromVEX3ToVEX2(OutMI, MI->getDesc()) ||
+ X86::optimizeShiftRotateWithImmediateOne(OutMI) ||
+ X86::optimizeVPCMPWithImmediateOneOrSix(OutMI) ||
+ X86::optimizeMOVSX(OutMI) || X86::optimizeINCDEC(OutMI, In64BitMode) ||
+ X86::optimizeMOV(OutMI, In64BitMode) ||
+ X86::optimizeToFixedRegisterForm(OutMI))
return;
// Handle a few special cases to eliminate operand modifiers.
OutMI.setOpcode(convertTailJumpOpcode(OutMI.getOpcode()));
break;
- case X86::ADC8ri: case X86::ADC16ri: case X86::ADC32ri: case X86::ADC64ri32:
- case X86::ADD8ri: case X86::ADD16ri: case X86::ADD32ri: case X86::ADD64ri32:
- case X86::AND8ri: case X86::AND16ri: case X86::AND32ri: case X86::AND64ri32:
- case X86::CMP8ri: case X86::CMP16ri: case X86::CMP32ri: case X86::CMP64ri32:
- case X86::OR8ri: case X86::OR16ri: case X86::OR32ri: case X86::OR64ri32:
- case X86::SBB8ri: case X86::SBB16ri: case X86::SBB32ri: case X86::SBB64ri32:
- case X86::SUB8ri: case X86::SUB16ri: case X86::SUB32ri: case X86::SUB64ri32:
- case X86::TEST8ri:case X86::TEST16ri:case X86::TEST32ri:case X86::TEST64ri32:
- case X86::XOR8ri: case X86::XOR16ri: case X86::XOR32ri: case X86::XOR64ri32: {
- unsigned NewOpc;
- switch (OutMI.getOpcode()) {
- default: llvm_unreachable("Invalid opcode");
- case X86::ADC8ri: NewOpc = X86::ADC8i8; break;
- case X86::ADC16ri: NewOpc = X86::ADC16i16; break;
- case X86::ADC32ri: NewOpc = X86::ADC32i32; break;
- case X86::ADC64ri32: NewOpc = X86::ADC64i32; break;
- case X86::ADD8ri: NewOpc = X86::ADD8i8; break;
- case X86::ADD16ri: NewOpc = X86::ADD16i16; break;
- case X86::ADD32ri: NewOpc = X86::ADD32i32; break;
- case X86::ADD64ri32: NewOpc = X86::ADD64i32; break;
- case X86::AND8ri: NewOpc = X86::AND8i8; break;
- case X86::AND16ri: NewOpc = X86::AND16i16; break;
- case X86::AND32ri: NewOpc = X86::AND32i32; break;
- case X86::AND64ri32: NewOpc = X86::AND64i32; break;
- case X86::CMP8ri: NewOpc = X86::CMP8i8; break;
- case X86::CMP16ri: NewOpc = X86::CMP16i16; break;
- case X86::CMP32ri: NewOpc = X86::CMP32i32; break;
- case X86::CMP64ri32: NewOpc = X86::CMP64i32; break;
- case X86::OR8ri: NewOpc = X86::OR8i8; break;
- case X86::OR16ri: NewOpc = X86::OR16i16; break;
- case X86::OR32ri: NewOpc = X86::OR32i32; break;
- case X86::OR64ri32: NewOpc = X86::OR64i32; break;
- case X86::SBB8ri: NewOpc = X86::SBB8i8; break;
- case X86::SBB16ri: NewOpc = X86::SBB16i16; break;
- case X86::SBB32ri: NewOpc = X86::SBB32i32; break;
- case X86::SBB64ri32: NewOpc = X86::SBB64i32; break;
- case X86::SUB8ri: NewOpc = X86::SUB8i8; break;
- case X86::SUB16ri: NewOpc = X86::SUB16i16; break;
- case X86::SUB32ri: NewOpc = X86::SUB32i32; break;
- case X86::SUB64ri32: NewOpc = X86::SUB64i32; break;
- case X86::TEST8ri: NewOpc = X86::TEST8i8; break;
- case X86::TEST16ri: NewOpc = X86::TEST16i16; break;
- case X86::TEST32ri: NewOpc = X86::TEST32i32; break;
- case X86::TEST64ri32: NewOpc = X86::TEST64i32; break;
- case X86::XOR8ri: NewOpc = X86::XOR8i8; break;
- case X86::XOR16ri: NewOpc = X86::XOR16i16; break;
- case X86::XOR32ri: NewOpc = X86::XOR32i32; break;
- case X86::XOR64ri32: NewOpc = X86::XOR64i32; break;
- }
- SimplifyShortImmForm(OutMI, NewOpc);
- break;
- }
case X86::MASKMOVDQU:
case X86::VMASKMOVDQU:
if (In64BitMode)