diff options
Diffstat (limited to 'lib/CodeGen/SelectionDAG')
-rw-r--r-- | lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp | 23 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp | 36 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 5 |
3 files changed, 44 insertions, 20 deletions
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp index 4ea29063ab..d929aaff7b 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp @@ -231,7 +231,8 @@ unsigned ScheduleDAG::getVR(SDValue Op, void ScheduleDAG::AddOperand(MachineInstr *MI, SDValue Op, unsigned IIOpNum, const TargetInstrDesc *II, - DenseMap<SDValue, unsigned> &VRBaseMap) { + DenseMap<SDValue, unsigned> &VRBaseMap, + bool overlapsEarlyClobber) { if (Op.isMachineOpcode()) { // Note that this case is redundant with the final else block, but we // include it because it is the most common and it makes the logic @@ -244,7 +245,9 @@ void ScheduleDAG::AddOperand(MachineInstr *MI, SDValue Op, const TargetInstrDesc &TID = MI->getDesc(); bool isOptDef = IIOpNum < TID.getNumOperands() && TID.OpInfo[IIOpNum].isOptionalDef(); - MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef)); + MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef, false, false, + false, 0, false, + overlapsEarlyClobber)); // Verify that it is right. assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); @@ -278,7 +281,9 @@ void ScheduleDAG::AddOperand(MachineInstr *MI, SDValue Op, const ConstantFP *CFP = F->getConstantFPValue(); MI->addOperand(MachineOperand::CreateFPImm(CFP)); } else if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) { - MI->addOperand(MachineOperand::CreateReg(R->getReg(), false)); + MI->addOperand(MachineOperand::CreateReg(R->getReg(), false, false, + false, false, 0, false, + overlapsEarlyClobber)); } else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) { MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(),TGA->getOffset())); } else if (BasicBlockSDNode *BB = dyn_cast<BasicBlockSDNode>(Op)) { @@ -314,7 +319,9 @@ void ScheduleDAG::AddOperand(MachineInstr *MI, SDValue Op, Op.getValueType() != MVT::Flag && "Chain and flag operands should occur at end of operand list!"); unsigned VReg = getVR(Op, VRBaseMap); - MI->addOperand(MachineOperand::CreateReg(VReg, false)); + MI->addOperand(MachineOperand::CreateReg(VReg, false, false, + false, false, 0, false, + overlapsEarlyClobber)); // Verify that it is right. Note that the reg class of the physreg and the // vreg don't necessarily need to match, but the target copy insertion has @@ -596,6 +603,7 @@ void ScheduleDAG::EmitNode(SDNode *Node, bool IsClone, // Add all of the operand registers to the instruction. for (unsigned i = 2; i != NumOps;) { + bool overlapsEarlyClobber = false; unsigned Flags = cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue(); unsigned NumVals = Flags >> 3; @@ -618,13 +626,18 @@ void ScheduleDAG::EmitNode(SDNode *Node, bool IsClone, false, 0, true)); } break; + case 7: // Addressing mode overlapping earlyclobber. + case 5: // Use of register overlapping earlyclobber. + overlapsEarlyClobber = true; + // fall through case 1: // Use of register. case 3: // Immediate. case 4: // Addressing mode. // The addressing mode has been selected, just add all of the // operands to the machine instruction. for (; NumVals; --NumVals, ++i) - AddOperand(MI, Node->getOperand(i), 0, 0, VRBaseMap); + AddOperand(MI, Node->getOperand(i), 0, 0, VRBaseMap, + overlapsEarlyClobber); break; } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 62a6b4f180..9492b33527 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -4909,8 +4909,10 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { assert(OpInfo.isIndirect && "Memory output must be indirect operand"); // Add information to the INLINEASM node to know about this output. - unsigned ResOpType = 4/*MEM*/ | (1 << 3); - AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, + unsigned ResOpType = SawEarlyClobber ? + 7 /* MEM OVERLAPS EARLYCLOBBER */ : + 4/*MEM*/; + AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType | (1<<3), TLI.getPointerTy())); AsmNodeOperands.push_back(OpInfo.CallOperand); break; @@ -4963,7 +4965,8 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getZExtValue(); assert(((NumOps & 7) == 2 /*REGDEF*/ || (NumOps & 7) == 6 /*EARLYCLOBBER REGDEF*/ || - (NumOps & 7) == 4 /*MEM*/) && + (NumOps & 7) == 4 /*MEM*/ || + (NumOps & 7) == 7 /*MEM OVERLAPS EARLYCLOBBER*/) && "Skipped past definitions?"); CurOp += (NumOps>>3)+1; } @@ -4985,14 +4988,17 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // Use the produced MatchedRegs object to MatchedRegs.getCopyToRegs(InOperandVal, DAG, Chain, &Flag); - MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, DAG, AsmNodeOperands); + MatchedRegs.AddInlineAsmOperands(SawEarlyClobber ? + 1 /*REGUSE*/ : + 5 /*REGUSE OVERLAPS EARLYCLOBBER*/, + DAG, AsmNodeOperands); break; } else { - assert((NumOps & 7) == 4/*MEM*/ && "Unknown matching constraint!"); + assert(((NumOps & 7) == 7/*MEM OVERLAPS EARLYCLOBBER */ || + (NumOps & 7) == 4) && "Unknown matching constraint!"); assert((NumOps >> 3) == 1 && "Unexpected number of operands"); // Add information to the INLINEASM node to know about this input. - unsigned ResOpType = 4/*MEM*/ | (1 << 3); - AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, + AsmNodeOperands.push_back(DAG.getTargetConstant(NumOps, TLI.getPointerTy())); AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]); break; @@ -5024,8 +5030,10 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { "Memory operands expect pointer values"); // Add information to the INLINEASM node to know about this input. - unsigned ResOpType = 4/*MEM*/ | (1 << 3); - AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, + unsigned ResOpType = SawEarlyClobber ? + 7 /* MEM OVERLAPS EARLYCLOBBER */ : + 4/*MEM*/; + AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType | (1<<3), TLI.getPointerTy())); AsmNodeOperands.push_back(InOperandVal); break; @@ -5043,16 +5051,18 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, Chain, &Flag); - OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, DAG, - AsmNodeOperands); + OpInfo.AssignedRegs.AddInlineAsmOperands(SawEarlyClobber ? + 5 /*REGUSE OVERLAPS EARLYCLOBBER*/: + 1/*REGUSE*/, + DAG, AsmNodeOperands); break; } case InlineAsm::isClobber: { // Add the clobbered value to the operand list, so that the register // allocator is aware that the physreg got clobbered. if (!OpInfo.AssignedRegs.Regs.empty()) - OpInfo.AssignedRegs.AddInlineAsmOperands(2/*REGDEF*/, DAG, - AsmNodeOperands); + OpInfo.AssignedRegs.AddInlineAsmOperands(6 /* EARLYCLOBBER REGDEF */, + DAG, AsmNodeOperands); break; } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 140bad27f5..c2938e35f8 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1113,7 +1113,8 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) { while (i != e) { unsigned Flags = cast<ConstantSDNode>(InOps[i])->getZExtValue(); - if ((Flags & 7) != 4 /*MEM*/) { + if ((Flags & 7) != 4 /*MEM*/ && + (Flags & 7) != 7 /*MEM OVERLAPS EARLYCLOBBER*/) { // Just skip over this operand, copying the operands verbatim. Ops.insert(Ops.end(), InOps.begin()+i, InOps.begin()+i+(Flags >> 3) + 1); i += (Flags >> 3) + 1; @@ -1128,7 +1129,7 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) { // Add this to the output node. MVT IntPtrTy = CurDAG->getTargetLoweringInfo().getPointerTy(); - Ops.push_back(CurDAG->getTargetConstant(4/*MEM*/ | (SelOps.size() << 3), + Ops.push_back(CurDAG->getTargetConstant((Flags & 7) | (SelOps.size()<< 3), IntPtrTy)); Ops.insert(Ops.end(), SelOps.begin(), SelOps.end()); i += 2; |