From: Krzysztof Parzyszek Date: Wed, 5 Oct 2016 13:15:06 +0000 (+0000) Subject: Fix machine operand traversal in ScheduleDAGInstrs::fixupKills X-Git-Tag: llvmorg-4.0.0-rc1~8054 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e7c72cdbb0ba7f1ac3ef85b972ad524f79c46af9;p=platform%2Fupstream%2Fllvm.git Fix machine operand traversal in ScheduleDAGInstrs::fixupKills llvm-svn: 283315 --- diff --git a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp index c147424cf7b5..ba9bf9062943 100644 --- a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -1309,7 +1309,13 @@ void ScheduleDAGInstrs::fixupKills(MachineBasicBlock *MBB) { // register is used multiple times we only set the kill flag on // the first use. Don't set kill flags on undef operands. killedRegs.reset(); - for (MachineOperand &MO : MI.operands()) { + + // toggleKillFlag can append new operands (implicit defs), so using + // a range-based loop is not safe. The new operands will be appended + // at the end of the operand list and they don't need to be visited, + // so iterating until the currently last operand is ok. + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue; unsigned Reg = MO.getReg(); if ((Reg == 0) || MRI.isReserved(Reg)) continue; @@ -1333,7 +1339,6 @@ void ScheduleDAGInstrs::fixupKills(MachineBasicBlock *MBB) { if (MO.isKill() != kill) { DEBUG(dbgs() << "Fixing " << MO << " in "); - // Warning: toggleKillFlag may invalidate MO. toggleKillFlag(&MI, MO); DEBUG(MI.dump()); DEBUG({ diff --git a/llvm/test/CodeGen/Hexagon/post-ra-kill-update.mir b/llvm/test/CodeGen/Hexagon/post-ra-kill-update.mir new file mode 100644 index 000000000000..c43624d7a8d3 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/post-ra-kill-update.mir @@ -0,0 +1,37 @@ +# RUN: llc -march=hexagon -mcpu=hexagonv60 -run-pass post-RA-sched -o - %s | FileCheck %s + +# The post-RA scheduler reorders S2_lsr_r_p and S2_lsr_r_p_or. Both of them +# use r9, and the last of the two kills it. The kill flag fixup did not +# correctly update the flag, resulting in both instructions killing r9. + +# CHECK-LABEL: name: foo +# Check for no-kill of r9 in the first instruction, after reordering: +# CHECK: %d7 = S2_lsr_r_p_or %d7, killed %d1, %r9 +# CHECK: %d13 = S2_lsr_r_p killed %d0, killed %r9 + +--- | + define void @foo() { + ret void + } +... + +--- +name: foo +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1 + liveins: %d0, %d1, %r9, %r13 + + %d7 = S2_asl_r_p %d0, %r13 + %d5 = S2_asl_r_p %d1, killed %r13 + %d6 = S2_lsr_r_p killed %d0, %r9 + %d7 = S2_lsr_r_p_or killed %d7, killed %d1, killed %r9 + %d1 = A2_combinew killed %r11, killed %r10 + %d0 = A2_combinew killed %r15, killed %r14 + J2_jump %bb.1, implicit-def %pc + + bb.1: + A2_nop +... +