Index: include/llvm/CodeGen/MachineInstr.h =================================================================== --- include/llvm/CodeGen/MachineInstr.h +++ include/llvm/CodeGen/MachineInstr.h @@ -547,6 +547,12 @@ return hasProperty(MCID::MoveImm, Type); } + /// Return true if this instruction is a register move. + /// (including moving values from subreg to reg) + bool isMoveReg(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::MoveReg, Type); + } + /// Return true if this instruction is a bitcast instruction. bool isBitcast(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Bitcast, Type); Index: include/llvm/CodeGen/TargetInstrInfo.h =================================================================== --- include/llvm/CodeGen/TargetInstrInfo.h +++ include/llvm/CodeGen/TargetInstrInfo.h @@ -845,6 +845,14 @@ llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!"); } + /// If the specific machine instruction is a instruction that moves/copies + /// value from one register to another register return true along with + /// @Source machine operand and @Destination machine operand. + virtual bool isCopyInstr(const MachineInstr &MI, MachineOperand &Source, + MachineOperand &Destination) const { + return false; + } + /// Store the specified register of the given register class to the specified /// stack frame index. The store instruction is to be added to the given /// machine basic block before the specified machine instruction. If isKill Index: include/llvm/MC/MCInstrDesc.h =================================================================== --- include/llvm/MC/MCInstrDesc.h +++ include/llvm/MC/MCInstrDesc.h @@ -127,6 +127,7 @@ IndirectBranch, Compare, MoveImm, + MoveReg, Bitcast, Select, DelaySlot, @@ -244,6 +245,9 @@ /// Return true if the instruction is an add instruction. bool isAdd() const { return Flags & (1ULL << MCID::Add); } + /// Return true if the instruction is a register to register move. + bool isMoveReg() const { return Flags & (1ULL << MCID::MoveReg); } + /// Return true if the instruction is a call. bool isCall() const { return Flags & (1ULL << MCID::Call); } Index: include/llvm/Target/Target.td =================================================================== --- include/llvm/Target/Target.td +++ include/llvm/Target/Target.td @@ -437,6 +437,7 @@ bit isIndirectBranch = 0; // Is this instruction an indirect branch? bit isCompare = 0; // Is this instruction a comparison instruction? bit isMoveImm = 0; // Is this instruction a move immediate instruction? + bit isMoveReg = 0; // Is this instruction a move register instruction? bit isBitcast = 0; // Is this instruction a bitcast instruction? bit isSelect = 0; // Is this instruction a select instruction? bit isBarrier = 0; // Can control flow fall through this instruction? Index: lib/Target/ARM/ARMBaseInstrInfo.h =================================================================== --- lib/Target/ARM/ARMBaseInstrInfo.h +++ lib/Target/ARM/ARMBaseInstrInfo.h @@ -201,6 +201,9 @@ const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; + bool isCopyInstr(const MachineInstr &MI, MachineOperand &Src, + MachineOperand &Dest) const override; + void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg, bool isKill, int FrameIndex, Index: lib/Target/ARM/ARMBaseInstrInfo.cpp =================================================================== --- lib/Target/ARM/ARMBaseInstrInfo.cpp +++ lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -935,6 +935,24 @@ Mov->addRegisterKilled(SrcReg, TRI); } +bool ARMBaseInstrInfo::isCopyInstr(const MachineInstr &MI, MachineOperand &Src, + MachineOperand &Dest) const { + // VMOVRRD is also a copy instruction but it requires + // special way of handling. It is more complex copy version + // and since that we are not considering it. For recognition + // of such instruction isExtractSubregLike MI interface fuction + // could be used. + // VORRq is considered as a move only if two inputs are + // the same register. + if (!MI.isMoveReg() || + (MI.getOpcode() == ARM::VORRq && + MI.getOperand(1).getReg() != MI.getOperand(2).getReg())) + return false; + Dest = MI.getOperand(0); + Src = MI.getOperand(1); + return true; +} + const MachineInstrBuilder & ARMBaseInstrInfo::AddDReg(MachineInstrBuilder &MIB, unsigned Reg, unsigned SubIdx, unsigned State, Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -3340,7 +3340,7 @@ // Move Instructions. // -let hasSideEffects = 0 in +let hasSideEffects = 0, isMoveReg = 1 in def MOVr : AsI1<0b1101, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMOVr, "mov", "\t$Rd, $Rm", []>, UnaryDP, Sched<[WriteALU]> { bits<4> Rd; Index: lib/Target/ARM/ARMInstrThumb.td =================================================================== --- lib/Target/ARM/ARMInstrThumb.td +++ lib/Target/ARM/ARMInstrThumb.td @@ -1154,7 +1154,7 @@ // A7-73: MOV(2) - mov setting flag. -let hasSideEffects = 0 in { +let hasSideEffects = 0, isMoveReg = 1 in { def tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, 2, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, Index: lib/Target/ARM/ARMInstrVFP.td =================================================================== --- lib/Target/ARM/ARMInstrVFP.td +++ lib/Target/ARM/ARMInstrVFP.td @@ -999,6 +999,7 @@ []>; let hasSideEffects = 0 in { +let isMoveReg = 1 in { def VMOVD : ADuI<0b11101, 0b11, 0b0000, 0b01, 0, (outs DPR:$Dd), (ins DPR:$Dm), IIC_fpUNA64, "vmov", ".f64\t$Dd, $Dm", []>; @@ -1006,6 +1007,7 @@ def VMOVS : ASuI<0b11101, 0b11, 0b0000, 0b01, 0, (outs SPR:$Sd), (ins SPR:$Sm), IIC_fpUNA32, "vmov", ".f32\t$Sd, $Sm", []>; +} // isMoveReg let PostEncoderMethod = "", DecoderNamespace = "VFPV8" in { def VMOVH : ASuInp<0b11101, 0b11, 0b0000, 0b01, 0, @@ -1024,6 +1026,7 @@ // FP <-> GPR Copies. Int <-> FP Conversions. // +let isMoveReg = 1 in { def VMOVRS : AVConv2I<0b11100001, 0b1010, (outs GPR:$Rt), (ins SPR:$Sn), IIC_fpMOVSI, "vmov", "\t$Rt, $Sn", @@ -1069,6 +1072,7 @@ // pipelines. let D = VFPNeonDomain; } +} // isMoveReg def : Pat<(arm_vmovsr GPR:$Rt), (VMOVSR GPR:$Rt)>, Requires<[HasVFP2, UseVMOVSR]>; let hasSideEffects = 0 in { Index: lib/Target/Mips/MicroMipsDSPInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsDSPInstrInfo.td +++ lib/Target/Mips/MicroMipsDSPInstrInfo.td @@ -386,6 +386,7 @@ string AsmString = !strconcat("wrdsp", "\t$rt, $mask"); list Pattern = [(int_mips_wrdsp GPR32Opnd:$rt, immZExt7:$mask)]; InstrItinClass Itinerary = NoItinerary; + bit isMoveReg = 1; } class BPOSGE32C_MMR3_DESC { Index: lib/Target/Mips/MicroMipsInstrFPU.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFPU.td +++ lib/Target/Mips/MicroMipsInstrFPU.td @@ -130,7 +130,9 @@ } def FMOV_S_MM : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, - ABS_FM_MM<0, 0x1>, ISA_MICROMIPS; + ABS_FM_MM<0, 0x1>, ISA_MICROMIPS { + let isMoveReg = 1; +} def FNEG_S_MM : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>, ABS_FM_MM<0, 0x2d>, ISA_MICROMIPS; Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -238,6 +238,7 @@ !strconcat(opstr, "\t$dst_regs, $rs, $rt"), [], NoItinerary, FrmR> { let isReMaterializable = 1; + let isMoveReg = 1; } /// A register pair used by load/store pair instructions. @@ -415,12 +416,14 @@ [], II_MFHI_MFLO, FrmR> { let Uses = [UseReg]; let hasSideEffects = 0; + let isMoveReg = 1; } class MoveMM16 : MicroMipsInst16<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), [], II_MOVE, FrmR> { let isReMaterializable = 1; + let isMoveReg = 1; } class LoadImmMM16 : Index: lib/Target/Mips/Mips16InstrInfo.h =================================================================== --- lib/Target/Mips/Mips16InstrInfo.h +++ lib/Target/Mips/Mips16InstrInfo.h @@ -53,6 +53,9 @@ const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; + bool isCopyInstr(const MachineInstr &MI, MachineOperand &Src, + MachineOperand &Dest) const override; + void storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg, bool isKill, int FrameIndex, Index: lib/Target/Mips/Mips16InstrInfo.cpp =================================================================== --- lib/Target/Mips/Mips16InstrInfo.cpp +++ lib/Target/Mips/Mips16InstrInfo.cpp @@ -97,6 +97,16 @@ MIB.addReg(SrcReg, getKillRegState(KillSrc)); } +bool Mips16InstrInfo::isCopyInstr(const MachineInstr &MI, MachineOperand &Src, + MachineOperand &Dest) const { + if (MI.isMoveReg()) { + Dest = MI.getOperand(0); + Src = MI.getOperand(1); + return true; + } + return false; +} + void Mips16InstrInfo::storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, Index: lib/Target/Mips/Mips16InstrInfo.td =================================================================== --- lib/Target/Mips/Mips16InstrInfo.td +++ lib/Target/Mips/Mips16InstrInfo.td @@ -869,7 +869,9 @@ //Purpose: Move // To move the contents of a GPR to a GPR. // -def MoveR3216: FI8_MOVR3216_ins<"move", IIM16Alu>; +def MoveR3216: FI8_MOVR3216_ins<"move", IIM16Alu> { + let isMoveReg = 1; +} // // Format: MFHI rx MIPS16e @@ -879,6 +881,7 @@ def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIM16Alu> { let Uses = [HI0]; let hasSideEffects = 0; + let isMoveReg = 1; } // @@ -889,6 +892,7 @@ def Mflo16: FRR16_M_ins<0b10010, "mflo", IIM16Alu> { let Uses = [LO0]; let hasSideEffects = 0; + let isMoveReg = 0; } // Index: lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64InstrInfo.td +++ lib/Target/Mips/Mips64InstrInfo.td @@ -377,10 +377,12 @@ let isCodeGenOnly = 1, rs = 0, shamt = 0 in { def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt), "dsll\t$rd, $rt, 32", [], II_DSLL>; - def SLL64_32 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR32:$rt), - "sll\t$rd, $rt, 0", [], II_SLL>; - def SLL64_64 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR64:$rt), - "sll\t$rd, $rt, 0", [], II_SLL>; + let isMoveReg = 1 in { + def SLL64_32 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR32:$rt), + "sll\t$rd, $rt, 0", [], II_SLL>; + def SLL64_64 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR64:$rt), + "sll\t$rd, $rt, 0", [], II_SLL>; + } } // We need the following pseudo instruction to avoid offset calculation for Index: lib/Target/Mips/MipsDSPInstrInfo.td =================================================================== --- lib/Target/Mips/MipsDSPInstrInfo.td +++ lib/Target/Mips/MipsDSPInstrInfo.td @@ -447,6 +447,7 @@ list Pattern = [(set GPR32Opnd:$rd, (OpNode immZExt10:$mask))]; InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; + bit isMoveReg = 1; } class WRDSP_DESC_BASE Pattern = [(OpNode GPR32Opnd:$rs, immZExt10:$mask)]; InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; + bit isMoveReg = 1; } class DPA_W_PH_DESC_BASE { @@ -500,6 +502,7 @@ list Pattern = [(set GPR32Opnd:$rd, (OpNode RO:$ac))]; InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; + bit isMoveReg = 1; } class MTHI_DESC_BASE { @@ -508,6 +511,7 @@ string AsmString = !strconcat(instr_asm, "\t$rs, $ac"); InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; + bit isMoveReg = 1; } class BPOSGE32_PSEUDO_DESC_BASE : Index: lib/Target/Mips/MipsInstrFPU.td =================================================================== --- lib/Target/Mips/MipsInstrFPU.td +++ lib/Target/Mips/MipsInstrFPU.td @@ -149,12 +149,16 @@ class MFC1_FT : InstSE<(outs DstRC:$rt), (ins SrcRC:$fs), !strconcat(opstr, "\t$rt, $fs"), - [(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>, HARDFLOAT; + [(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>, HARDFLOAT { + let isMoveReg = 1; +} class MTC1_FT : InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"), - [(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR, opstr>, HARDFLOAT; + [(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR, opstr>, HARDFLOAT { + let isMoveReg = 1; +} class MTC1_64_FT : @@ -510,14 +514,16 @@ bitconvert>, MFC1_FM<5>, ISA_MIPS3; def DMFC1 : MFC1_FT<"dmfc1", GPR64Opnd, FGR64Opnd, II_DMFC1, bitconvert>, MFC1_FM<1>, ISA_MIPS3; - def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, - ABSS_FM<0x6, 16>; - def FMOV_D32 : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>, - ABSS_FM<0x6, 17>, FGR_32; - def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>, - ABSS_FM<0x6, 17>, FGR_64 { - let DecoderNamespace = "MipsFP64"; - } + let isMoveReg = 1 in { + def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, + ABSS_FM<0x6, 16>; + def FMOV_D32 : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>, + ABSS_FM<0x6, 17>, FGR_32; + def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>, + ABSS_FM<0x6, 17>, FGR_64 { + let DecoderNamespace = "MipsFP64"; + } + } // isMoveReg } /// Floating Point Memory Instructions Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1772,6 +1772,7 @@ FrmR, opstr> { let Uses = [UseReg]; let hasSideEffects = 0; + let isMoveReg = 1; } class PseudoMTLOHI @@ -1784,6 +1785,7 @@ FrmR, opstr> { let Defs = DefRegs; let hasSideEffects = 0; + let isMoveReg = 1; } class EffectiveAddress : Index: lib/Target/Mips/MipsMSAInstrInfo.td =================================================================== --- lib/Target/Mips/MipsMSAInstrInfo.td +++ lib/Target/Mips/MipsMSAInstrInfo.td @@ -1790,6 +1790,7 @@ string AsmString = "cfcmsa\t$rd, $cs"; InstrItinClass Itinerary = NoItinerary; bit hasSideEffects = 1; + bit isMoveReg = 1; } class CLE_S_B_DESC : MSA_3R_DESC_BASE<"cle_s.b", vsetle_v16i8, MSA128BOpnd>; @@ -1884,6 +1885,7 @@ string AsmString = "ctcmsa\t$cd, $rs"; InstrItinClass Itinerary = NoItinerary; bit hasSideEffects = 1; + bit isMoveReg = 1; } class DIV_S_B_DESC : MSA_3R_DESC_BASE<"div_s.b", sdiv, MSA128BOpnd>; @@ -2429,6 +2431,7 @@ string AsmString = "move.v\t$wd, $ws"; list Pattern = []; InstrItinClass Itinerary = NoItinerary; + bit isMoveReg = 1; } class MSUB_Q_H_DESC : MSA_3RF_4RF_DESC_BASE<"msub_q.h", int_mips_msub_q_h, Index: lib/Target/Mips/MipsSEInstrInfo.h =================================================================== --- lib/Target/Mips/MipsSEInstrInfo.h +++ lib/Target/Mips/MipsSEInstrInfo.h @@ -47,6 +47,9 @@ const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; + bool isCopyInstr(const MachineInstr &MI, MachineOperand &Src, + MachineOperand &Dest) const override; + void storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, Index: lib/Target/Mips/MipsSEInstrInfo.cpp =================================================================== --- lib/Target/Mips/MipsSEInstrInfo.cpp +++ lib/Target/Mips/MipsSEInstrInfo.cpp @@ -179,6 +179,62 @@ MIB.addReg(ZeroReg); } +static bool isORCopyInst(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case Mips::OR_MM: + case Mips::OR: + if (MI.getOperand(2).getReg() == Mips::ZERO) + return true; + case Mips::OR64: + if (MI.getOperand(2).getReg() == Mips::ZERO_64) + return true; + default: + return false; + } +} + +/// If @MI is WRDSP/RRDSP instruction return true with @isWrite set to true +/// if it is WRDSP instruction. +static bool isReadOrWritToDSPReg(const MachineInstr &MI, bool &isWrite) { + switch (MI.getOpcode()) { + case Mips::WRDSP: + case Mips::WRDSP_MM: + isWrite = true; + case Mips::RDDSP: + case Mips::RDDSP_MM: + return true; + default: + return false; + } +} + +/// We check for the common case of 'or', as it's MIPS' preferred instruction +/// for GPRs but we have to check the operands to ensure that is the case. +/// Other move instructions for MIPS are directly identifiable. +bool MipsSEInstrInfo::isCopyInstr(const MachineInstr &MI, MachineOperand &Src, + MachineOperand &Dest) const { + bool isDSPControlWrite = false; + // Condition is made to match the creation of WRDSP/RDDSP copy instruction + // from copyPhysReg function. + if (isReadOrWritToDSPReg(MI, isDSPControlWrite)) { + if (!MI.getOperand(1).isImm() || !MI.getOperand(1).getImm() == (1<<4)) + return false; + else if (isDSPControlWrite) { + Src = MI.getOperand(0); + Dest = MI.getOperand(2); + } else { + Dest = MI.getOperand(0); + Src = MI.getOperand(2); + } + return true; + } else if (MI.isMoveReg() || isORCopyInst(MI)) { + Dest = MI.getOperand(0); + Src = MI.getOperand(1); + return true; + } + return false; +} + void MipsSEInstrInfo:: storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, Index: lib/Target/X86/X86InstrAVX512.td =================================================================== --- lib/Target/X86/X86InstrAVX512.td +++ lib/Target/X86/X86InstrAVX512.td @@ -2683,7 +2683,7 @@ multiclass avx512_mask_mov opc_kk, bits<8> opc_km, bits<8> opc_mk, string OpcodeStr, RegisterClass KRC, ValueType vvt, X86MemOperand x86memop> { - let hasSideEffects = 0, SchedRW = [WriteMove] in + let isMoveReg = 1, hasSideEffects = 0, SchedRW = [WriteMove] in def kk : I, Sched<[WriteMove]>; @@ -3168,6 +3168,7 @@ X86SchedWriteMoveLS Sched, bit NoRMPattern = 0, SDPatternOperator SelectOprr = vselect> { let hasSideEffects = 0 in { + let isMoveReg = 1 in def rr : AVX512PI, EVEX, Sched<[Sched.RR]>; @@ -3270,6 +3271,7 @@ string Name, X86SchedWriteMoveLS Sched, bit NoMRPattern = 0> { let hasSideEffects = 0 in { + let isMoveReg = 1 in def rr_REV : AVX512PI, EVEX, FoldGenData, Index: lib/Target/X86/X86InstrInfo.h =================================================================== --- lib/Target/X86/X86InstrInfo.h +++ lib/Target/X86/X86InstrInfo.h @@ -394,6 +394,8 @@ void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; + bool isCopyInstr(const MachineInstr &MI, MachineOperand &Src, + MachineOperand &Dest) const override; void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, Index: lib/Target/X86/X86InstrInfo.cpp =================================================================== --- lib/Target/X86/X86InstrInfo.cpp +++ lib/Target/X86/X86InstrInfo.cpp @@ -6852,6 +6852,16 @@ llvm_unreachable("Cannot emit physreg copy instruction"); } +bool X86InstrInfo::isCopyInstr(const MachineInstr &MI, MachineOperand &Src, + MachineOperand &Dest) const { + if (MI.isMoveReg()) { + Dest = MI.getOperand(0); + Src = MI.getOperand(1); + return true; + } + return false; +} + static unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC, bool isStackAligned, Index: lib/Target/X86/X86InstrInfo.td =================================================================== --- lib/Target/X86/X86InstrInfo.td +++ lib/Target/X86/X86InstrInfo.td @@ -1455,7 +1455,7 @@ // Move Instructions. // let SchedRW = [WriteMove] in { -let hasSideEffects = 0 in { +let hasSideEffects = 0, isMoveReg = 1 in { def MOV8rr : I<0x88, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src), "mov{b}\t{$src, $dst|$dst, $src}", []>; def MOV16rr : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR16:$src), @@ -1624,7 +1624,7 @@ } // hasSideEffects = 0 let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - SchedRW = [WriteMove] in { + SchedRW = [WriteMove], isMoveReg = 1 in { def MOV8rr_REV : I<0x8A, MRMSrcReg, (outs GR8:$dst), (ins GR8:$src), "mov{b}\t{$src, $dst|$dst, $src}", []>, FoldGenData<"MOV8rr">; @@ -1673,7 +1673,7 @@ // that they can be used for copying and storing h registers, which can't be // encoded when a REX prefix is present. let isCodeGenOnly = 1 in { -let hasSideEffects = 0 in +let hasSideEffects = 0, isMoveReg = 1 in def MOV8rr_NOREX : I<0x88, MRMDestReg, (outs GR8_NOREX:$dst), (ins GR8_NOREX:$src), "mov{b}\t{$src, $dst|$dst, $src}", []>, Index: lib/Target/X86/X86InstrMMX.td =================================================================== --- lib/Target/X86/X86InstrMMX.td +++ lib/Target/X86/X86InstrMMX.td @@ -215,14 +215,14 @@ "movq\t{$src, $dst|$dst, $src}", [(set GR64:$dst, (bitconvert VR64:$src))]>, Sched<[WriteVecMoveToGpr]>; -let SchedRW = [WriteVecMove], hasSideEffects = 0 in { +let SchedRW = [WriteVecMove], hasSideEffects = 0, isMoveReg = 1 in { def MMX_MOVQ64rr : MMXI<0x6F, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src), "movq\t{$src, $dst|$dst, $src}", []>; let isCodeGenOnly = 1, ForceDisassemble = 1 in def MMX_MOVQ64rr_REV : MMXI<0x7F, MRMDestReg, (outs VR64:$dst), (ins VR64:$src), "movq\t{$src, $dst|$dst, $src}", []>, FoldGenData<"MMX_MOVQ64rr">; -} // SchedRW, hasSideEffects +} // SchedRW, hasSideEffects, isMoveReg } // isBitcast let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, mayStore = 1 in Index: lib/Target/X86/X86InstrSSE.td =================================================================== --- lib/Target/X86/X86InstrSSE.td +++ lib/Target/X86/X86InstrSSE.td @@ -408,7 +408,7 @@ X86MemOperand x86memop, PatFrag ld_frag, string asm, Domain d, X86SchedWriteMoveLS sched> { -let hasSideEffects = 0 in +let hasSideEffects = 0, isMoveReg = 1 in def rr : PI, Sched<[sched.RR]>; @@ -505,7 +505,8 @@ } // Predicate // For disassembler -let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in { +let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, + isMoveReg = 1 in { let SchedRW = [SchedWriteFMoveLS.XMM.RR] in { def VMOVAPSrr_REV : VPSI<0x29, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), @@ -581,7 +582,7 @@ // For disassembler let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0, - SchedRW = [SchedWriteFMoveLS.XMM.RR] in { + isMoveReg = 1, SchedRW = [SchedWriteFMoveLS.XMM.RR] in { def MOVAPSrr_REV : PSI<0x29, MRMDestReg, (outs VR128:$dst), (ins VR128:$src), "movaps\t{$src, $dst|$dst, $src}", []>, FoldGenData<"MOVAPSrr">; Index: utils/TableGen/CodeGenInstruction.h =================================================================== --- utils/TableGen/CodeGenInstruction.h +++ utils/TableGen/CodeGenInstruction.h @@ -226,6 +226,7 @@ bool isIndirectBranch : 1; bool isCompare : 1; bool isMoveImm : 1; + bool isMoveReg : 1; bool isBitcast : 1; bool isSelect : 1; bool isBarrier : 1; Index: utils/TableGen/CodeGenInstruction.cpp =================================================================== --- utils/TableGen/CodeGenInstruction.cpp +++ utils/TableGen/CodeGenInstruction.cpp @@ -306,6 +306,7 @@ isIndirectBranch = R->getValueAsBit("isIndirectBranch"); isCompare = R->getValueAsBit("isCompare"); isMoveImm = R->getValueAsBit("isMoveImm"); + isMoveReg = R->getValueAsBit("isMoveReg"); isBitcast = R->getValueAsBit("isBitcast"); isSelect = R->getValueAsBit("isSelect"); isBarrier = R->getValueAsBit("isBarrier"); Index: utils/TableGen/InstrInfoEmitter.cpp =================================================================== --- utils/TableGen/InstrInfoEmitter.cpp +++ utils/TableGen/InstrInfoEmitter.cpp @@ -489,6 +489,7 @@ if (Inst.isIndirectBranch) OS << "|(1ULL<