[llvm-dev] LiveVariables clears the MO::IsDead bit from non-RA, physical regs, but never restores it. Bug?
Johnson, Nicholas Paul via llvm-dev
llvm-dev at lists.llvm.org
Fri Nov 20 08:49:12 PST 2015
Following up, I've submitted a patch to phabricator for review: http://reviews.llvm.org/D14875
D. E. Shaw Research
>From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of
>Johnson, Nicholas Paul via llvm-dev
>Sent: Tuesday, November 17, 2015 5:58 PM
>To: llvm-dev at lists.llvm.org
>Subject: [llvm-dev] LiveVariables clears the MO::IsDead bit from non-RA,
>physical regs, but never restores it. Bug?
>I am observing poor instruction scheduling in my out-of-tree target. The
>problem is an over-constrained scheduling DAG. In particular, the DAG
>includes spurious output dependencies on physical, non-register-allocatable
>registers. MISched already includes code to avoid this problem. However
>that code relies on information clobbered by the earlier pass LiveVariables.
>I wonder whether this is a bug in the LiveVariables pass and would
>appreciate feedback. Let me expand with a small example,
>Suppose my target declares machine instruction type FOO that implicitly
>writes a condition-code register named 'F_OVERFLOW'. F_OVERFLOW is a
>physical register and is not register-allocatable. Consider this sequence of
>A: %vreg4<def> = FOO %vreg1<kill>, %F_OVERFLOW<imp-def,dead>
>B: %vreg5<def> = FOO %vreg2<kill>, %F_OVERFLOW<imp-def,dead>
>C: %vreg6<def> = FOO %vreg3<kill>, %F_OVERFLOW<imp-def>
>When constructing a MISched DAG, I expect to see output dependencies (A -
>> C) and (B -> C). I assert that output dependency (A -> B) is spurious because
>F_OVERFLOW is dead at B. Indeed, ScheduleDAGInstrs::addPhysRegDeps
>already includes a test for this case (if MO.isDead()), confirming that the
>developer intended to omit output dependencies on dead registers.
>However, the LiveVariables pass clears the isDead flag from all operands that
>reference F_OVERFLOW and does not reset those flags. Without this
>information MISched builds the pessimistic graph including the spurious
>output dependency (A -> B). I don't believe this is the intended behavior,
>and I'll cite two comments to support that hypothesis:
>(1) In method LiveVariables::runOnInstr, the comment "// Clear kill and dead
>markers. LV will recompute them" suggests that the kill, dead flags will be
>valid after this pass completes.
>(2) At the top of LiveVariables.h, "If a physical register is not register
>allocatable, it is not tracked. This is useful for things like the stack pointer
>and condition codes." This suggests that the pass cannot restore the
>MachineOperand::IsKill and MachineOperand::IsDead bits for physical non-
>I would appreciate any feedback. If we decide this is buggy, I'll work on a fix.
>I have tested this on 3.6.1. I have not yet tested on the 3.7 series as it may
>take some effort to port my out-of-tree target. However, I looked at the old
>and new versions and I don't *think* any relevant code has changed.
>D. E. Shaw Research
>LLVM Developers mailing list
>llvm-dev at lists.llvm.org
More information about the llvm-dev