Index: include/llvm/CodeGen/MachineRegisterInfo.h =================================================================== --- include/llvm/CodeGen/MachineRegisterInfo.h +++ include/llvm/CodeGen/MachineRegisterInfo.h @@ -596,6 +596,16 @@ const TargetRegisterClass *RC, unsigned MinNumRegs = 0); + /// \brief Try to constrain Op so that it is usable by argument OpNum of the + /// provided MCInstrDesc. If this fails, create a new virtual register in the + /// correct class and COPY the value there. + unsigned constrainOperandRegClass(MachineFunction &MF, + MachineBasicBlock::iterator InsertPt, + DebugLoc DL, const MCInstrDesc &II, + unsigned Op, unsigned OpNum, + const TargetInstrInfo &TII, + const TargetRegisterInfo &TRI); + /// recomputeRegClass - Try to find a legal super-class of Reg's register /// class that still satisfies the constraints from the instructions using /// Reg. Returns true if Reg was upgraded. Index: lib/CodeGen/MachineRegisterInfo.cpp =================================================================== --- lib/CodeGen/MachineRegisterInfo.cpp +++ lib/CodeGen/MachineRegisterInfo.cpp @@ -60,6 +60,25 @@ return NewRC; } +unsigned MachineRegisterInfo::constrainOperandRegClass( + MachineFunction &MF, MachineBasicBlock::iterator InsertPt, DebugLoc DL, + const MCInstrDesc &II, unsigned Op, unsigned OpNum, + const TargetInstrInfo &TII, const TargetRegisterInfo &TRI) { + if (TargetRegisterInfo::isVirtualRegister(Op)) { + const TargetRegisterClass *RegClass = TII.getRegClass(II, OpNum, &TRI, MF); + if (!constrainRegClass(Op, RegClass)) { + // If it's not legal to COPY between the register classes, something + // has gone very wrong before we got here. + unsigned NewOp = createVirtualRegister(RegClass); + BuildMI(*InsertPt->getParent(), InsertPt, DL, TII.get(TargetOpcode::COPY), + NewOp) + .addReg(Op); + return NewOp; + } + } + return Op; +} + bool MachineRegisterInfo::recomputeRegClass(unsigned Reg) { const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); Index: lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/FastISel.cpp +++ lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1701,19 +1701,8 @@ unsigned FastISel::constrainOperandRegClass(const MCInstrDesc &II, unsigned Op, unsigned OpNum) { - if (TargetRegisterInfo::isVirtualRegister(Op)) { - const TargetRegisterClass *RegClass = - TII.getRegClass(II, OpNum, &TRI, *FuncInfo.MF); - if (!MRI.constrainRegClass(Op, RegClass)) { - // If it's not legal to COPY between the register classes, something - // has gone very wrong before we got here. - unsigned NewOp = createResultReg(RegClass); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::COPY), NewOp).addReg(Op); - return NewOp; - } - } - return Op; + return MRI.constrainOperandRegClass(*FuncInfo.MF, FuncInfo.InsertPt, DbgLoc, + II, Op, OpNum, TII, TRI); } unsigned FastISel::fastEmitInst_(unsigned MachineInstOpcode, Index: lib/Target/X86/X86FastISel.cpp =================================================================== --- lib/Target/X86/X86FastISel.cpp +++ lib/Target/X86/X86FastISel.cpp @@ -3536,25 +3536,6 @@ if (!Result) return false; - // The index register could be in the wrong register class. Unfortunately, - // foldMemoryOperandImpl could have commuted the instruction so its not enough - // to just look at OpNo + the offset to the index reg. We actually need to - // scan the instruction to find the index reg and see if its the correct reg - // class. - unsigned OperandNo = 0; - for (MachineInstr::mop_iterator I = Result->operands_begin(), - E = Result->operands_end(); I != E; ++I, ++OperandNo) { - MachineOperand &MO = *I; - if (!MO.isReg() || MO.isDef() || MO.getReg() != AM.IndexReg) - continue; - // Found the index reg, now try to rewrite it. - unsigned IndexReg = constrainOperandRegClass(Result->getDesc(), - MO.getReg(), OperandNo); - if (IndexReg == MO.getReg()) - continue; - MO.setReg(IndexReg); - } - Result->addMemOperand(*FuncInfo.MF, createMachineMemOperandFor(LI)); MI->eraseFromParent(); return true; Index: lib/Target/X86/X86InstrInfo.cpp =================================================================== --- lib/Target/X86/X86InstrInfo.cpp +++ lib/Target/X86/X86InstrInfo.cpp @@ -4697,10 +4697,24 @@ return false; } -void addOperands(MachineInstrBuilder &MIB, ArrayRef MOs) { +static void addOperands(MachineFunction &MF, MachineInstrBuilder &MIB, + unsigned Offset, const MCInstrDesc &Desc, + ArrayRef MOs, + MachineBasicBlock::iterator InsertPt, MachineInstr *MI, + const TargetInstrInfo &TII) { + MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); + unsigned NumAddrOps = MOs.size(); - for (unsigned i = 0; i != NumAddrOps; ++i) - MIB.addOperand(MOs[i]); + for (unsigned i = 0; i != NumAddrOps; ++i) { + MachineOperand MO = MOs[i]; + if (MO.isReg()) { + MO.setReg(MRI.constrainOperandRegClass(MF, InsertPt, MI->getDebugLoc(), + Desc, MO.getReg(), i + Offset, TII, + TRI)); + } + MIB.addOperand(MO); + } if (NumAddrOps < 4) // FrameIndex only addOffset(MIB, 0); } @@ -4712,10 +4726,10 @@ const TargetInstrInfo &TII) { // Create the base instruction with the memory operand as the first part. // Omit the implicit operands, something BuildMI can't do. - MachineInstr *NewMI = MF.CreateMachineInstr(TII.get(Opcode), - MI->getDebugLoc(), true); + const MCInstrDesc &MCID = TII.get(Opcode); + MachineInstr *NewMI = MF.CreateMachineInstr(MCID, MI->getDebugLoc(), true); MachineInstrBuilder MIB(MF, NewMI); - addOperands(MIB, MOs); + addOperands(MF, MIB, 0, MCID, MOs, InsertPt, MI, TII); // Loop over the rest of the ri operands, converting them over. unsigned NumOps = MI->getDesc().getNumOperands()-2; @@ -4739,15 +4753,15 @@ MachineBasicBlock::iterator InsertPt, MachineInstr *MI, const TargetInstrInfo &TII) { // Omit the implicit operands, something BuildMI can't do. - MachineInstr *NewMI = MF.CreateMachineInstr(TII.get(Opcode), - MI->getDebugLoc(), true); + const MCInstrDesc &MCID = TII.get(Opcode); + MachineInstr *NewMI = MF.CreateMachineInstr(MCID, MI->getDebugLoc(), true); MachineInstrBuilder MIB(MF, NewMI); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (i == OpNo) { assert(MO.isReg() && "Expected to fold into reg operand!"); - addOperands(MIB, MOs); + addOperands(MF, MIB, OpNo, MCID, MOs, InsertPt, MI, TII); } else { MIB.addOperand(MO); } @@ -4763,9 +4777,11 @@ ArrayRef MOs, MachineBasicBlock::iterator InsertPt, MachineInstr *MI) { - MachineInstrBuilder MIB = BuildMI(*InsertPt->getParent(), InsertPt, - MI->getDebugLoc(), TII.get(Opcode)); - addOperands(MIB, MOs); + const MCInstrDesc &MCID = TII.get(Opcode); + MachineInstrBuilder MIB = + BuildMI(*InsertPt->getParent(), InsertPt, MI->getDebugLoc(), MCID); + addOperands(*InsertPt->getParent()->getParent(), MIB, 0, MCID, MOs, InsertPt, + MI, TII); return MIB.addImm(0); }