diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/RegAllocLocal.cpp | 51 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp | 49 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h | 2 |
3 files changed, 61 insertions, 41 deletions
diff --git a/llvm/lib/CodeGen/RegAllocLocal.cpp b/llvm/lib/CodeGen/RegAllocLocal.cpp index 0a20128632d..cd4de344cc4 100644 --- a/llvm/lib/CodeGen/RegAllocLocal.cpp +++ b/llvm/lib/CodeGen/RegAllocLocal.cpp @@ -722,6 +722,55 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) { } } + // If any physical regs are earlyclobber, spill any value they might + // have in them, then mark them unallocatable. + // If any virtual regs are earlyclobber, allocate them now (before + // freeing inputs that are killed). + if (MI->getOpcode()==TargetInstrInfo::INLINEASM) { + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& MO = MI->getOperand(i); + if (MO.isRegister() && MO.isDef() && MO.isEarlyClobber() && + MO.getReg()) { + if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + unsigned DestVirtReg = MO.getReg(); + unsigned DestPhysReg; + + // If DestVirtReg already has a value, use it. + if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg))) + DestPhysReg = getReg(MBB, MI, DestVirtReg); + MF->getRegInfo().setPhysRegUsed(DestPhysReg); + markVirtRegModified(DestVirtReg); + getVirtRegLastUse(DestVirtReg) = + std::make_pair((MachineInstr*)0, 0); + DOUT << " Assigning " << TRI->getName(DestPhysReg) + << " to %reg" << DestVirtReg << "\n"; + MO.setReg(DestPhysReg); // Assign the earlyclobber register + } else { + unsigned Reg = MO.getReg(); + if (PhysRegsUsed[Reg] == -2) continue; // Something like ESP. + // These are extra physical register defs when a sub-register + // is defined (def of a sub-register is a read/mod/write of the + // larger registers). Ignore. + if (isReadModWriteImplicitDef(MI, MO.getReg())) continue; + + MF->getRegInfo().setPhysRegUsed(Reg); + spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg + PhysRegsUsed[Reg] = 0; // It is free and reserved now + AddToPhysRegsUseOrder(Reg); + + for (const unsigned *AliasSet = TRI->getSubRegisters(Reg); + *AliasSet; ++AliasSet) { + if (PhysRegsUsed[*AliasSet] != -2) { + MF->getRegInfo().setPhysRegUsed(*AliasSet); + PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now + AddToPhysRegsUseOrder(*AliasSet); + } + } + } + } + } + } + // Get the used operands into registers. This has the potential to spill // incoming values if we are out of registers. Note that we completely // ignore physical register uses here. We assume that if an explicit @@ -778,6 +827,7 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand& MO = MI->getOperand(i); if (MO.isRegister() && MO.isDef() && !MO.isImplicit() && MO.getReg() && + !MO.isEarlyClobber() && TargetRegisterInfo::isPhysicalRegister(MO.getReg())) { unsigned Reg = MO.getReg(); if (PhysRegsUsed[Reg] == -2) continue; // Something like ESP. @@ -839,6 +889,7 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand& MO = MI->getOperand(i); if (MO.isRegister() && MO.isDef() && MO.getReg() && + !MO.isEarlyClobber() && TargetRegisterInfo::isVirtualRegister(MO.getReg())) { unsigned DestVirtReg = MO.getReg(); unsigned DestPhysReg; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 43ca2364d59..1365d684f4d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -4465,12 +4465,10 @@ private: /// allocation. This produces generally horrible, but correct, code. /// /// OpInfo describes the operand. -/// HasEarlyClobber is true if there are any early clobber constraints (=&r) -/// or any explicitly clobbered registers. /// Input and OutputRegs are the set of already allocated physical registers. /// void SelectionDAGLowering:: -GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, +GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, std::set<unsigned> &OutputRegs, std::set<unsigned> &InputRegs) { // Compute whether this value requires an input register, an output register, @@ -4481,10 +4479,9 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, case InlineAsm::isOutput: isOutReg = true; - // If this is an early-clobber output, or if there is an input - // constraint that matches this, we need to reserve the input register - // so no other inputs allocate to it. - isInReg = OpInfo.isEarlyClobber || OpInfo.hasMatchingInput; + // If there is an input constraint that matches this, we need to reserve + // the input register so no other inputs allocate to it. + isInReg = OpInfo.hasMatchingInput; break; case InlineAsm::isInput: isInReg = true; @@ -4551,16 +4548,11 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, std::vector<unsigned> RegClassRegs; const TargetRegisterClass *RC = PhysReg.second; if (RC) { - // If this is an early clobber or tied register, our regalloc doesn't know - // how to maintain the constraint. If it isn't, go ahead and create vreg + // If this is a tied register, our regalloc doesn't know how to maintain + // the constraint. If it isn't, go ahead and create vreg // and let the regalloc do the right thing. - if (!OpInfo.hasMatchingInput && !OpInfo.isEarlyClobber && - // If there is some other early clobber and this is an input register, - // then we are forced to pre-allocate the input reg so it doesn't - // conflict with the earlyclobber. - !(OpInfo.Type == InlineAsm::isInput && HasEarlyClobber)) { + if (!OpInfo.hasMatchingInput) { RegVT = *PhysReg.second->vt_begin(); - if (OpInfo.ConstraintVT == MVT::Other) ValueVT = RegVT; @@ -4664,11 +4656,6 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { std::vector<InlineAsm::ConstraintInfo> ConstraintInfos = IA->ParseConstraints(); - // SawEarlyClobber - Keep track of whether we saw an earlyclobber output - // constraint. If so, we can't let the register allocator allocate any input - // registers, because it will not know to avoid the earlyclobbered output reg. - bool SawEarlyClobber = false; - bool hasMemory = hasInlineAsmMemConstraint(ConstraintInfos, TLI); unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. @@ -4744,24 +4731,6 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // Compute the constraint code and ConstraintType to use. TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, hasMemory, &DAG); - // Keep track of whether we see an earlyclobber. - SawEarlyClobber |= OpInfo.isEarlyClobber; - - // If we see a clobber of a register, it is an early clobber. - if (!SawEarlyClobber && - OpInfo.Type == InlineAsm::isClobber && - OpInfo.ConstraintType == TargetLowering::C_Register) { - // Note that we want to ignore things that we don't track here, like - // dirflag, fpsr, flags, etc. - std::pair<unsigned, const TargetRegisterClass*> PhysReg = - TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode, - OpInfo.ConstraintVT); - if (PhysReg.first || PhysReg.second) { - // This is a register we know of. - SawEarlyClobber = true; - } - } - // If this is a memory input, and if the operand is not indirect, do what we // need to to provide an address for the memory input. if (OpInfo.ConstraintType == TargetLowering::C_Memory && @@ -4802,7 +4771,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // If this constraint is for a specific register, allocate it before // anything else. if (OpInfo.ConstraintType == TargetLowering::C_Register) - GetRegistersForValue(OpInfo, SawEarlyClobber, OutputRegs, InputRegs); + GetRegistersForValue(OpInfo, OutputRegs, InputRegs); } ConstraintInfos.clear(); @@ -4815,7 +4784,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // C_Register operands have already been allocated, Other/Memory don't need // to be. if (OpInfo.ConstraintType == TargetLowering::C_RegisterClass) - GetRegistersForValue(OpInfo, SawEarlyClobber, OutputRegs, InputRegs); + GetRegistersForValue(OpInfo, OutputRegs, InputRegs); } // AsmNodeOperands - The operands for the ISD::INLINEASM node. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h index 18e15af4577..eb9ed3f7cab 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h @@ -398,7 +398,7 @@ public: N = NewN; } - void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, + void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, std::set<unsigned> &OutputRegs, std::set<unsigned> &InputRegs); |