diff options
Diffstat (limited to 'lib/Target/X86/X86MCInstLower.cpp')
| -rw-r--r-- | lib/Target/X86/X86MCInstLower.cpp | 120 | 
1 files changed, 76 insertions, 44 deletions
| diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index cfd68f74b7b2..a8a9fd8accde 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -13,19 +13,20 @@  //===----------------------------------------------------------------------===//  #include "X86AsmPrinter.h" -#include "X86COFFMachineModuleInfo.h"  #include "InstPrinter/X86ATTInstPrinter.h" -#include "llvm/Type.h" +#include "X86COFFMachineModuleInfo.h" +#include "llvm/ADT/SmallString.h"  #include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/IR/Type.h"  #include "llvm/MC/MCAsmInfo.h"  #include "llvm/MC/MCContext.h"  #include "llvm/MC/MCExpr.h"  #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstBuilder.h"  #include "llvm/MC/MCStreamer.h"  #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h"  #include "llvm/Support/FormattedStream.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/Target/Mangler.h"  using namespace llvm;  namespace { @@ -238,7 +239,8 @@ static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {      if (!MI->getOperand(OpNo+i).isReg()) continue;      unsigned Reg = MI->getOperand(OpNo+i).getReg(); -    if (Reg == 0) continue; +    // LEAs can use RIP-relative addressing, and RIP has no sub/super register. +    if (Reg == 0 || Reg == X86::RIP) continue;      MI->getOperand(OpNo+i).setReg(getX86SubSuperRegister(Reg, MVT::i64));    } @@ -405,6 +407,57 @@ ReSimplify:      LowerUnaryToTwoAddr(OutMI, X86::XOR32rr); // MOV32r0 -> XOR32rr      break; +  // Commute operands to get a smaller encoding by using VEX.R instead of VEX.B +  // if one of the registers is extended, but other isn't. +  case X86::VMOVAPDrr: +  case X86::VMOVAPDYrr: +  case X86::VMOVAPSrr: +  case X86::VMOVAPSYrr: +  case X86::VMOVDQArr: +  case X86::VMOVDQAYrr: +  case X86::VMOVDQUrr: +  case X86::VMOVDQUYrr: +  case X86::VMOVUPDrr: +  case X86::VMOVUPDYrr: +  case X86::VMOVUPSrr: +  case X86::VMOVUPSYrr: { +    if (!X86II::isX86_64ExtendedReg(OutMI.getOperand(0).getReg()) && +        X86II::isX86_64ExtendedReg(OutMI.getOperand(1).getReg())) { +      unsigned NewOpc; +      switch (OutMI.getOpcode()) { +      default: llvm_unreachable("Invalid opcode"); +      case X86::VMOVAPDrr:  NewOpc = X86::VMOVAPDrr_REV;  break; +      case X86::VMOVAPDYrr: NewOpc = X86::VMOVAPDYrr_REV; break; +      case X86::VMOVAPSrr:  NewOpc = X86::VMOVAPSrr_REV;  break; +      case X86::VMOVAPSYrr: NewOpc = X86::VMOVAPSYrr_REV; break; +      case X86::VMOVDQArr:  NewOpc = X86::VMOVDQArr_REV;  break; +      case X86::VMOVDQAYrr: NewOpc = X86::VMOVDQAYrr_REV; break; +      case X86::VMOVDQUrr:  NewOpc = X86::VMOVDQUrr_REV;  break; +      case X86::VMOVDQUYrr: NewOpc = X86::VMOVDQUYrr_REV; break; +      case X86::VMOVUPDrr:  NewOpc = X86::VMOVUPDrr_REV;  break; +      case X86::VMOVUPDYrr: NewOpc = X86::VMOVUPDYrr_REV; break; +      case X86::VMOVUPSrr:  NewOpc = X86::VMOVUPSrr_REV;  break; +      case X86::VMOVUPSYrr: NewOpc = X86::VMOVUPSYrr_REV; break; +      } +      OutMI.setOpcode(NewOpc); +    } +    break; +  } +  case X86::VMOVSDrr: +  case X86::VMOVSSrr: { +    if (!X86II::isX86_64ExtendedReg(OutMI.getOperand(0).getReg()) && +        X86II::isX86_64ExtendedReg(OutMI.getOperand(2).getReg())) { +      unsigned NewOpc; +      switch (OutMI.getOpcode()) { +      default: llvm_unreachable("Invalid opcode"); +      case X86::VMOVSDrr:   NewOpc = X86::VMOVSDrr_REV;   break; +      case X86::VMOVSSrr:   NewOpc = X86::VMOVSSrr_REV;   break; +      } +      OutMI.setOpcode(NewOpc); +    } +    break; +  } +    // TAILJMPr64, CALL64r, CALL64pcrel32 - These instructions have register    // inputs modeled as normal uses instead of implicit uses.  As such, truncate    // off all but the first operand (the callee).  FIXME: Change isel. @@ -549,18 +602,14 @@ ReSimplify:      OutMI.setOpcode(X86::RET);      break; -  case X86::MORESTACK_RET_RESTORE_R10: { -    MCInst retInst; - +  case X86::MORESTACK_RET_RESTORE_R10:      OutMI.setOpcode(X86::MOV64rr);      OutMI.addOperand(MCOperand::CreateReg(X86::R10));      OutMI.addOperand(MCOperand::CreateReg(X86::RAX)); -    retInst.setOpcode(X86::RET); -    AsmPrinter.OutStreamer.EmitInstruction(retInst); +    AsmPrinter.OutStreamer.EmitInstruction(MCInstBuilder(X86::RET));      break;    } -  }  }  static void LowerTlsAddr(MCStreamer &OutStreamer, @@ -574,11 +623,8 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,    MCContext &context = OutStreamer.getContext(); -  if (needsPadding) { -    MCInst prefix; -    prefix.setOpcode(X86::DATA16_PREFIX); -    OutStreamer.EmitInstruction(prefix); -  } +  if (needsPadding) +    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX));    MCSymbolRefExpr::VariantKind SRVK;    switch (MI.getOpcode()) { @@ -628,20 +674,11 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,    OutStreamer.EmitInstruction(LEA);    if (needsPadding) { -    MCInst prefix; -    prefix.setOpcode(X86::DATA16_PREFIX); -    OutStreamer.EmitInstruction(prefix); -    prefix.setOpcode(X86::DATA16_PREFIX); -    OutStreamer.EmitInstruction(prefix); -    prefix.setOpcode(X86::REX64_PREFIX); -    OutStreamer.EmitInstruction(prefix); +    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX)); +    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX)); +    OutStreamer.EmitInstruction(MCInstBuilder(X86::REX64_PREFIX));    } -  MCInst call; -  if (is64Bits) -    call.setOpcode(X86::CALL64pcrel32); -  else -    call.setOpcode(X86::CALLpcrel32);    StringRef name = is64Bits ? "__tls_get_addr" : "___tls_get_addr";    MCSymbol *tlsGetAddr = context.GetOrCreateSymbol(name);    const MCSymbolRefExpr *tlsRef = @@ -649,8 +686,9 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,                              MCSymbolRefExpr::VK_PLT,                              context); -  call.addOperand(MCOperand::CreateExpr(tlsRef)); -  OutStreamer.EmitInstruction(call); +  OutStreamer.EmitInstruction(MCInstBuilder(is64Bits ? X86::CALL64pcrel32 +                                                     : X86::CALLpcrel32) +    .addExpr(tlsRef));  }  void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { @@ -694,7 +732,6 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {      return LowerTlsAddr(OutStreamer, MCInstLowering, *MI);    case X86::MOVPC32r: { -    MCInst TmpInst;      // This is a pseudo op for a two instruction sequence with a label, which      // looks like:      //     call "L1$pb" @@ -703,20 +740,17 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {      // Emit the call.      MCSymbol *PICBase = MF->getPICBaseSymbol(); -    TmpInst.setOpcode(X86::CALLpcrel32);      // FIXME: We would like an efficient form for this, so we don't have to do a      // lot of extra uniquing. -    TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(PICBase, -                                                                 OutContext))); -    OutStreamer.EmitInstruction(TmpInst); +    OutStreamer.EmitInstruction(MCInstBuilder(X86::CALLpcrel32) +      .addExpr(MCSymbolRefExpr::Create(PICBase, OutContext)));      // Emit the label.      OutStreamer.EmitLabel(PICBase);      // popl $reg -    TmpInst.setOpcode(X86::POP32r); -    TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg()); -    OutStreamer.EmitInstruction(TmpInst); +    OutStreamer.EmitInstruction(MCInstBuilder(X86::POP32r) +      .addReg(MI->getOperand(0).getReg()));      return;    } @@ -746,12 +780,10 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {      DotExpr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(OpSym,OutContext),                                        DotExpr, OutContext); -    MCInst TmpInst; -    TmpInst.setOpcode(X86::ADD32ri); -    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); -    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); -    TmpInst.addOperand(MCOperand::CreateExpr(DotExpr)); -    OutStreamer.EmitInstruction(TmpInst); +    OutStreamer.EmitInstruction(MCInstBuilder(X86::ADD32ri) +      .addReg(MI->getOperand(0).getReg()) +      .addReg(MI->getOperand(1).getReg()) +      .addExpr(DotExpr));      return;    }    } | 
