diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index b9ad1f93ed5..d64df445b05 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -145,30 +145,20 @@ public: /// isIdentityCopy - Return true if the instruction is a copy (or /// extract_subreg, insert_subreg, subreg_to_reg) where the source and /// destination registers are the same. - bool isIdentityCopy(const MachineInstr &MI, - unsigned &SrcReg, unsigned &DstReg, - unsigned &SrcSubIdx, unsigned &DstSubIdx) const { + bool isIdentityCopy(const MachineInstr &MI) const { + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; if (isMoveInstr(MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && SrcReg == DstReg) return true; - if (MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { - DstReg = MI.getOperand(0).getReg(); - DstSubIdx = MI.getOperand(0).getSubReg(); - SrcReg = MI.getOperand(1).getReg(); - SrcSubIdx = MI.getOperand(1).getSubReg(); - return DstReg == SrcReg; - } - - if (MI.getOpcode() == TargetInstrInfo::INSERT_SUBREG || - MI.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { - DstReg = MI.getOperand(0).getReg(); - DstSubIdx = MI.getOperand(0).getSubReg(); - SrcReg = MI.getOperand(2).getReg(); - SrcSubIdx = MI.getOperand(2).getSubReg(); - return DstReg == SrcReg; - } + if (MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG && + MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) + return true; + if ((MI.getOpcode() == TargetInstrInfo::INSERT_SUBREG || + MI.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) && + MI.getOperand(0).getReg() == MI.getOperand(2).getReg()) + return true; return false; } diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp index 1dca0a97da4..cf90aba86b3 100644 --- a/lib/CodeGen/RegisterScavenging.cpp +++ b/lib/CodeGen/RegisterScavenging.cpp @@ -177,7 +177,24 @@ void RegScavenger::forward() { if (!Reg || isReserved(Reg)) continue; if (MO.isUse()) { - assert(isUsed(Reg) && "Using an undefined register!"); + if (!isUsed(Reg)) { + // Check if it's partial live: e.g. + // D0 = insert_subreg D0, S0 + // ... D0 + // The problem is the insert_subreg could be eliminated. The use of + // D0 is using a partially undef value. This is not *incorrect* since + // S1 is can be freely clobbered. + // Ideally we would like a way to model this, but leaving the + // insert_subreg around causes both correctness and performance issues. + bool SubUsed = false; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + if (isUsed(SubReg)) { + SubUsed = true; + break; + } + assert(SubUsed && "Using an undefined register!"); + } assert((!EarlyClobberRegs.test(Reg) || MI->isRegTiedToDefOperand(i)) && "Using an early clobbered register!"); } else { diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 5e369064fa2..f8784f60f5e 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -1853,7 +1853,7 @@ bool SimpleRegisterCoalescing::RangeIsDefinedByCopyFromReg(LiveInterval &li, tii_->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && DstReg == li.reg && SrcReg == Reg) { // Cache computed info. - LR->valno->def = LR->start; + LR->valno->def = LR->start; LR->valno->setCopy(DefMI); return true; } @@ -2006,7 +2006,7 @@ bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS){ // RHS into, update the value number info for the LHS to indicate that the // value number is defined where the RHS value number was. const VNInfo *VNI = RHS.getValNumInfo(0); - LHSValNo->def = VNI->def; + LHSValNo->def = VNI->def; LHSValNo->setCopy(VNI->getCopy()); // Okay, the final step is to loop over the RHS live intervals, adding them to @@ -2489,7 +2489,8 @@ SimpleRegisterCoalescing::lastRegisterUse(LiveIndex Start, MachineOperand &Use = I.getOperand(); MachineInstr *UseMI = Use.getParent(); unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; - if (tii_->isIdentityCopy(*UseMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) + if (tii_->isMoveInstr(*UseMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && + SrcReg == DstReg) // Ignore identity copies. continue; LiveIndex Idx = li_->getInstructionIndex(UseMI); @@ -2515,7 +2516,8 @@ SimpleRegisterCoalescing::lastRegisterUse(LiveIndex Start, // Ignore identity copies. unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; - if (!tii_->isIdentityCopy(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) + if (!(tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && + SrcReg == DstReg)) for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) { MachineOperand &Use = MI->getOperand(i); if (Use.isReg() && Use.isUse() && Use.getReg() && @@ -2568,8 +2570,7 @@ void SimpleRegisterCoalescing::CalculateSpillWeights() { for (MachineBasicBlock::const_iterator mii = MBB->begin(), mie = MBB->end(); mii != mie; ++mii) { const MachineInstr *MI = mii; - unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; - if (tii_->isIdentityCopy(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) + if (tii_->isIdentityCopy(*MI)) continue; if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) @@ -2705,34 +2706,27 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) && "Unrecognized copy instruction"); DstReg = MI->getOperand(0).getReg(); - // Do not delete subreg_to_reg, insert_subreg with undef source unless - // the definition is dead. e.g. - // %DO = INSERT_SUBREG %D0, %S0, 1 - // or else the scavenger may complain. These will be eliminated by the - // rewriter or the subreg lowering pass. if (TargetRegisterInfo::isPhysicalRegister(DstReg)) - // Don't delete extract_subreg of a physical register. - DoDelete = false; - else if (MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || - (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG && - MI->getOperand(1).isUndef())) + // Do not delete extract_subreg, insert_subreg of physical + // registers unless the definition is dead. e.g. + // %DO = INSERT_SUBREG %D0, %S0, 1 + // or else the scavenger may complain. LowerSubregs will + // delete them later. DoDelete = false; } - if (MI->registerDefIsDead(DstReg)) { LiveInterval &li = li_->getInterval(DstReg); if (!ShortenDeadCopySrcLiveRange(li, MI)) ShortenDeadCopyLiveRange(li, MI); DoDelete = true; } - - if (!DoDelete) { + if (!DoDelete) mii = next(mii); - } else { + else { li_->RemoveMachineInstrFromMaps(MI); mii = mbbi->erase(mii); + ++numPeep; } - ++numPeep; continue; } @@ -2770,7 +2764,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { } // If the move will be an identity move delete it - if (tii_->isIdentityCopy(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) { + bool isMove= tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx); + if (isMove && SrcReg == DstReg) { if (li_->hasInterval(SrcReg)) { LiveInterval &RegInt = li_->getInterval(SrcReg); // If def of this move instruction is dead, remove its live range diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp index 7e060c0074b..107c19ad019 100644 --- a/lib/CodeGen/VirtRegRewriter.cpp +++ b/lib/CodeGen/VirtRegRewriter.cpp @@ -495,7 +495,7 @@ static bool InvalidateRegDef(MachineBasicBlock::iterator I, MachineOperand *DefOp = NULL; for (unsigned i = 0, e = DefMI->getNumOperands(); i != e; ++i) { MachineOperand &MO = DefMI->getOperand(i); - if (!MO.isReg() || MO.isUse() || !MO.isKill() || MO.isUndef()) + if (!MO.isReg() || !MO.isUse() || !MO.isKill() || MO.isUndef()) continue; if (MO.getReg() == Reg) DefOp = &MO; @@ -2258,7 +2258,7 @@ private: // eliminate this or else the undef marker is lost and it will // confuses the scavenger. This is extremely rare. unsigned Src, Dst, SrcSR, DstSR; - if (TII->isIdentityCopy(MI, Src, Dst, SrcSR, DstSR) && + if (TII->isMoveInstr(MI, Src, Dst, SrcSR, DstSR) && Src == Dst && !MI.findRegisterUseOperand(Src)->isUndef()) { ++NumDCE; DEBUG(errs() << "Removing now-noop copy: " << MI); @@ -2347,7 +2347,7 @@ private: // instruction before considering the dest reg to be changed. { unsigned Src, Dst, SrcSR, DstSR; - if (TII->isIdentityCopy(MI, Src, Dst, SrcSR, DstSR)) { + if (TII->isMoveInstr(MI, Src, Dst, SrcSR, DstSR) && Src == Dst) { ++NumDCE; DEBUG(errs() << "Removing now-noop copy: " << MI); InvalidateKills(MI, TRI, RegKills, KillOps); diff --git a/test/CodeGen/X86/2009-10-25-RewriterBug.ll b/test/CodeGen/X86/2009-10-25-RewriterBug.ll new file mode 100644 index 00000000000..5b4e818359e --- /dev/null +++ b/test/CodeGen/X86/2009-10-25-RewriterBug.ll @@ -0,0 +1,171 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin -relocation-model=pic -disable-fp-elim + +%struct.DecRefPicMarking_t = type { i32, i32, i32, i32, i32, %struct.DecRefPicMarking_t* } +%struct.FrameStore = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %struct.StorablePicture*, %struct.StorablePicture*, %struct.StorablePicture* } +%struct.StorablePicture = type { i32, i32, i32, i32, i32, [50 x [6 x [33 x i64]]], [50 x [6 x [33 x i64]]], [50 x [6 x [33 x i64]]], [50 x [6 x [33 x i64]]], i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16**, i16***, i8*, i16**, i8***, i64***, i64***, i16****, i8**, i8**, %struct.StorablePicture*, %struct.StorablePicture*, %struct.StorablePicture*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [2 x i32], i32, %struct.DecRefPicMarking_t*, i32 } + +define fastcc void @insert_picture_in_dpb(%struct.FrameStore* nocapture %fs, %struct.StorablePicture* %p) nounwind ssp { +entry: + %0 = getelementptr inbounds %struct.FrameStore* %fs, i64 0, i32 12 ; <%struct.StorablePicture**> [#uses=1] + %1 = icmp eq i32 undef, 0 ; [#uses=1] + br i1 %1, label %bb.i, label %bb36.i + +bb.i: ; preds = %entry + br i1 undef, label %bb3.i, label %bb14.preheader.i + +bb3.i: ; preds = %bb.i + unreachable + +bb14.preheader.i: ; preds = %bb.i + br i1 undef, label %bb9.i, label %bb20.preheader.i + +bb9.i: ; preds = %bb9.i, %bb14.preheader.i + br i1 undef, label %bb9.i, label %bb20.preheader.i + +bb20.preheader.i: ; preds = %bb9.i, %bb14.preheader.i + br i1 undef, label %bb18.i, label %bb29.preheader.i + +bb18.i: ; preds = %bb20.preheader.i + unreachable + +bb29.preheader.i: ; preds = %bb20.preheader.i + br i1 undef, label %bb24.i, label %bb30.i + +bb24.i: ; preds = %bb29.preheader.i + unreachable + +bb30.i: ; preds = %bb29.preheader.i + store i32 undef, i32* undef, align 8 + br label %bb67.preheader.i + +bb36.i: ; preds = %entry + br label %bb67.preheader.i + +bb67.preheader.i: ; preds = %bb36.i, %bb30.i + %2 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=2] + %3 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=2] + %4 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=2] + %5 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=1] + %6 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=1] + %7 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=1] + %8 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=1] + %9 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=1] + %10 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=1] + %11 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=1] + %12 = phi %struct.StorablePicture* [ null, %bb36.i ], [ undef, %bb30.i ] ; <%struct.StorablePicture*> [#uses=1] + br i1 undef, label %bb38.i, label %bb68.i + +bb38.i: ; preds = %bb66.i, %bb67.preheader.i + %13 = phi %struct.StorablePicture* [ %37, %bb66.i ], [ %2, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %14 = phi %struct.StorablePicture* [ %38, %bb66.i ], [ %3, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %15 = phi %struct.StorablePicture* [ %39, %bb66.i ], [ %4, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %16 = phi %struct.StorablePicture* [ %40, %bb66.i ], [ %5, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %17 = phi %struct.StorablePicture* [ %40, %bb66.i ], [ %6, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %18 = phi %struct.StorablePicture* [ %40, %bb66.i ], [ %7, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %19 = phi %struct.StorablePicture* [ %40, %bb66.i ], [ %8, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %20 = phi %struct.StorablePicture* [ %40, %bb66.i ], [ %9, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %21 = phi %struct.StorablePicture* [ %40, %bb66.i ], [ %10, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %22 = phi %struct.StorablePicture* [ %40, %bb66.i ], [ %11, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %23 = phi %struct.StorablePicture* [ %40, %bb66.i ], [ %12, %bb67.preheader.i ] ; <%struct.StorablePicture*> [#uses=1] + %indvar248.i = phi i64 [ %indvar.next249.i, %bb66.i ], [ 0, %bb67.preheader.i ] ; [#uses=3] + %storemerge52.i = trunc i64 %indvar248.i to i32 ; [#uses=1] + %24 = getelementptr inbounds %struct.StorablePicture* %23, i64 0, i32 19 ; [#uses=0] + br i1 undef, label %bb.nph51.i, label %bb66.i + +bb.nph51.i: ; preds = %bb38.i + %25 = sdiv i32 %storemerge52.i, 8 ; [#uses=0] + br label %bb39.i + +bb39.i: ; preds = %bb64.i, %bb.nph51.i + %26 = phi %struct.StorablePicture* [ %17, %bb.nph51.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=1] + %27 = phi %struct.StorablePicture* [ %18, %bb.nph51.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=0] + %28 = phi %struct.StorablePicture* [ %19, %bb.nph51.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=0] + %29 = phi %struct.StorablePicture* [ %20, %bb.nph51.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=0] + %30 = phi %struct.StorablePicture* [ %21, %bb.nph51.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=0] + %31 = phi %struct.StorablePicture* [ %22, %bb.nph51.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=0] + br i1 undef, label %bb57.i, label %bb40.i + +bb40.i: ; preds = %bb39.i + br i1 undef, label %bb57.i, label %bb41.i + +bb41.i: ; preds = %bb40.i + %storemerge10.i = select i1 undef, i32 2, i32 4 ; [#uses=1] + %32 = zext i32 %storemerge10.i to i64 ; [#uses=1] + br i1 undef, label %bb45.i, label %bb47.i + +bb45.i: ; preds = %bb41.i + %33 = getelementptr inbounds %struct.StorablePicture* %26, i64 0, i32 5, i64 undef, i64 %32, i64 undef ; [#uses=1] + %34 = load i64* %33, align 8 ; [#uses=1] + br label %bb47.i + +bb47.i: ; preds = %bb45.i, %bb41.i + %storemerge11.i = phi i64 [ %34, %bb45.i ], [ 0, %bb41.i ] ; [#uses=0] + %scevgep246.i = getelementptr i64* undef, i64 undef ; [#uses=0] + br label %bb64.i + +bb57.i: ; preds = %bb40.i, %bb39.i + br i1 undef, label %bb58.i, label %bb60.i + +bb58.i: ; preds = %bb57.i + br label %bb60.i + +bb60.i: ; preds = %bb58.i, %bb57.i + %35 = load i64*** undef, align 8 ; [#uses=1] + %scevgep256.i = getelementptr i64** %35, i64 %indvar248.i ; [#uses=1] + %36 = load i64** %scevgep256.i, align 8 ; [#uses=1] + %scevgep243.i = getelementptr i64* %36, i64 undef ; [#uses=1] + store i64 -1, i64* %scevgep243.i, align 8 + br label %bb64.i + +bb64.i: ; preds = %bb60.i, %bb47.i + br i1 undef, label %bb39.i, label %bb66.i + +bb66.i: ; preds = %bb64.i, %bb38.i + %37 = phi %struct.StorablePicture* [ %13, %bb38.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=2] + %38 = phi %struct.StorablePicture* [ %14, %bb38.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=2] + %39 = phi %struct.StorablePicture* [ %15, %bb38.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=2] + %40 = phi %struct.StorablePicture* [ %16, %bb38.i ], [ null, %bb64.i ] ; <%struct.StorablePicture*> [#uses=8] + %indvar.next249.i = add i64 %indvar248.i, 1 ; [#uses=1] + br i1 undef, label %bb38.i, label %bb68.i + +bb68.i: ; preds = %bb66.i, %bb67.preheader.i + %41 = phi %struct.StorablePicture* [ %2, %bb67.preheader.i ], [ %37, %bb66.i ] ; <%struct.StorablePicture*> [#uses=0] + %42 = phi %struct.StorablePicture* [ %3, %bb67.preheader.i ], [ %38, %bb66.i ] ; <%struct.StorablePicture*> [#uses=1] + %43 = phi %struct.StorablePicture* [ %4, %bb67.preheader.i ], [ %39, %bb66.i ] ; <%struct.StorablePicture*> [#uses=1] + br i1 undef, label %bb.nph48.i, label %bb108.i + +bb.nph48.i: ; preds = %bb68.i + br label %bb80.i + +bb80.i: ; preds = %bb104.i, %bb.nph48.i + %44 = phi %struct.StorablePicture* [ %42, %bb.nph48.i ], [ null, %bb104.i ] ; <%struct.StorablePicture*> [#uses=1] + %45 = phi %struct.StorablePicture* [ %43, %bb.nph48.i ], [ null, %bb104.i ] ; <%struct.StorablePicture*> [#uses=1] + br i1 undef, label %bb.nph39.i, label %bb104.i + +bb.nph39.i: ; preds = %bb80.i + br label %bb81.i + +bb81.i: ; preds = %bb102.i, %bb.nph39.i + %46 = phi %struct.StorablePicture* [ %44, %bb.nph39.i ], [ %48, %bb102.i ] ; <%struct.StorablePicture*> [#uses=0] + %47 = phi %struct.StorablePicture* [ %45, %bb.nph39.i ], [ %48, %bb102.i ] ; <%struct.StorablePicture*> [#uses=0] + br i1 undef, label %bb83.i, label %bb82.i + +bb82.i: ; preds = %bb81.i + br i1 undef, label %bb83.i, label %bb101.i + +bb83.i: ; preds = %bb82.i, %bb81.i + br label %bb102.i + +bb101.i: ; preds = %bb82.i + br label %bb102.i + +bb102.i: ; preds = %bb101.i, %bb83.i + %48 = load %struct.StorablePicture** %0, align 8 ; <%struct.StorablePicture*> [#uses=2] + br i1 undef, label %bb81.i, label %bb104.i + +bb104.i: ; preds = %bb102.i, %bb80.i + br label %bb80.i + +bb108.i: ; preds = %bb68.i + unreachable +}