[llvm-commits] [llvm] r56290 - in /llvm/trunk: include/llvm/CodeGen/LiveIntervalAnalysis.h include/llvm/CodeGen/MachineOperand.h include/llvm/CodeGen/ScheduleDAG.h lib/CodeGen/AsmPrinter/AsmPrinter.cpp lib/CodeGen/LiveIntervalAnalysis.cpp lib/CodeGen/MachineInstr.cpp lib/CodeGen/RegAllocLinearScan.cpp lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp test/CodeGen/X86/2008-09-17-inline-asm-1.ll
Evan Cheng
evan.cheng at apple.com
Thu Sep 18 11:07:00 PDT 2008
On Sep 18, 2008, at 10:56 AM, Dale Johannesen wrote:
>
>> 2. After AsmsThatEarlyClobber and
>> AsmsWithEarlyClobberConflict are populated virtual registers can
>> change due to coalescing (and potentially other passes). Then the
>> maps
>> won't be accurate.
>>
>> Perhaps we should add a bit to LiveInterval to indicate a vr can be
>> earlyclobber or earlyclobberconflict. Coalescer should not touch any
>> register whose interval has the bit. Then we only do the check for
>> those intervals here. The check can use MachineRegisterInfo def / use
>> chain to look for any conflicts.
>
> I preferred a lookup table because walking a chain can get slow, but
> OK, I can
> do it this way. It may be that maintaining the table correctly is too
> hard.
I think we want to avoid maintaining the maps in LiveIntervalAnalysis.
I know the register allocator currently rely on it, but that may
change in the future.
Obviously traversing the def / use info will be slower. But if we only
do so for earlyclobber operands it should be ok. People who use this
inline asm "feature" should suffer. :-)
Evan
>
>
>> Evan
>>
>>>
>>> FreeReg = *I;
>>> if (FreeReg < inactiveCounts.size())
>>> FreeRegInactiveCount = inactiveCounts[FreeReg];
>>> @@ -1070,7 +1071,8 @@
>>> for (; I != E; ++I) {
>>> unsigned Reg = *I;
>>> if (prt_->isRegAvail(Reg) && Reg < inactiveCounts.size() &&
>>> - FreeRegInactiveCount < inactiveCounts[Reg]) {
>>> + FreeRegInactiveCount < inactiveCounts[Reg] &&
>>> + li_->noEarlyclobberConflict(cur->reg, *vrm_, Reg)) {
>>> FreeReg = Reg;
>>> FreeRegInactiveCount = inactiveCounts[Reg];
>>> if (FreeRegInactiveCount == MaxInactiveCount)
>>>
>>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp?rev=56290&r1=56289&r2=56290&view=diff
>>>
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> ====================================================================
>>> --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp
>>> (original)
>>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGEmit.cpp Wed Sep
>>> 17 16:13:11 2008
>>> @@ -231,7 +231,8 @@
>>> 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 @@
>>> 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 @@
>>> 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 @@
>>> 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 @@
>>>
>>> // 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 @@
>>> 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;
>>> }
>>> }
>>>
>>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=56290&r1=56289&r2=56290&view=diff
>>>
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> ====================================================================
>>> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
>>> (original)
>>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Wed
>>> Sep 17 16:13:11 2008
>>> @@ -4909,8 +4909,10 @@
>>> 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 @@
>>> 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 @@
>>>
>>> // 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 @@
>>> "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 @@
>>>
>>> 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;
>>> }
>>> }
>>>
>>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=56290&r1=56289&r2=56290&view=diff
>>>
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> ====================================================================
>>> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
>>> (original)
>>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Sep
>>> 17 16:13:11 2008
>>> @@ -1113,7 +1113,8 @@
>>>
>>> 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 @@
>>>
>>> // 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;
>>>
>>> Added: llvm/trunk/test/CodeGen/X86/2008-09-17-inline-asm-1.ll
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-09-17-inline-asm-1.ll?rev=56290&view=auto
>>>
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> ====================================================================
>>> --- llvm/trunk/test/CodeGen/X86/2008-09-17-inline-asm-1.ll (added)
>>> +++ llvm/trunk/test/CodeGen/X86/2008-09-17-inline-asm-1.ll Wed Sep
>>> 17 16:13:11 2008
>>> @@ -0,0 +1,24 @@
>>> +; RUN: llvm-as < %s | llc -o - -march=x86 | not grep "movl %eax,
>>> %eax"
>>> +; RUN: llvm-as < %s | llc -o - -march=x86 | not grep "movl %edx,
>>> %edx"
>>> +; RUN: llvm-as < %s | llc -o - -march=x86 | not grep "movl (%eax),
>>> %eax"
>>> +; RUN: llvm-as < %s | llc -o - -march=x86 | not grep "movl (%edx),
>>> %edx"
>>> +
>>> +; %0 must not be put in EAX or EDX.
>>> +; In the first asm, $0 and $2 must not be put in EAX.
>>> +; In the second asm, $0 and $2 must not be put in EDX.
>>> +; This is kind of hard to test thoroughly, but the things above
>>> should continue
>>> +; to pass, I think.
>>> +; ModuleID = '<stdin>'
>>> +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-
>>> i32:32:32-
>>> i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-
>>> f80:128:128"
>>> +target triple = "i386-apple-darwin8"
>>> + at x = common global i32 0 ; <i32*> [#uses=1]
>>> +
>>> +define i32 @aci(i32* %pw) nounwind {
>>> +entry:
>>> + %0 = load i32* @x, align 4 ; <i32> [#uses=1]
>>> + %asmtmp = tail call { i32, i32 } asm "movl $0, %eax\0A\090:\0A
>>> \09test %eax, %eax\0A\09je 1f\0A\09movl %eax, $2\0A\09incl $2\0A
>>> \09lock\0A\09cmpxchgl $2, $0\0A\09jne 0b\0A\091:",
>>> "=*m,=&{ax},=&r,*m,~{dirflag},~{fpsr},~{flags},~{memory},~{cc}"(i32*
>>> %pw, i32* %pw) nounwind ; <{ i32, i32 }> [#uses=0]
>>> + %asmtmp2 = tail call { i32, i32 } asm "movl $0, %edx\0A\090:\0A
>>> \09test %edx, %edx\0A\09je 1f\0A\09movl %edx, $2\0A\09incl $2\0A
>>> \09lock\0A\09cmpxchgl $2, $0\0A\09jne 0b\0A\091:",
>>> "=*m,=&{dx},=&r,*m,~{dirflag},~{fpsr},~{flags},~{memory},~{cc}"(i32*
>>> %pw, i32* %pw) nounwind ; <{ i32, i32 }> [#uses=1]
>>> + %asmresult3 = extractvalue { i32, i32 } %asmtmp2, 0 ; <i32>
>>> [#uses=1]
>>> + %1 = add i32 %asmresult3, %0 ; <i32> [#uses=1]
>>> + ret i32 %1
>>> +}
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list