Page MenuHomePhabricator

[ScheduleDAG] Make sure to process all def operands before any use operands
ClosedPublic

Authored by kparzysz on May 10 2016, 7:56 AM.

Details

Summary

An example from Hexagon where things went wrong:

%R0<def> = L2_loadrigp <ga:@fp04>      ; load function address
J2_callr %R0<kill>, ..., %R0<imp-def>  ; call *R0, return value in R0

ScheduleDAGInstrs::buildSchedGraph would visit all instructions going backwards, and in each instruction it would visit all operands in their order on the operand list. In the case of this call, it visited the use of R0 first, then removed it from the set Uses after it visited the def. This caused the DAG to be missing the data dependence edge on R0 between the load and the call.

The final result was that the load and the call were packetized together, which meant that the call used the prior value of R0 instead of the loaded one.

Diff Detail

Repository
rL LLVM

Event Timeline

kparzysz updated this revision to Diff 56712.May 10 2016, 7:56 AM
kparzysz retitled this revision from to [ScheduleDAG] Make sure to process all def operands before any use operands.
kparzysz updated this object.
kparzysz added a reviewer: MatzeB.
kparzysz set the repository for this revision to rL LLVM.
kparzysz added a subscriber: llvm-commits.
atrick accepted this revision.May 10 2016, 9:43 AM
atrick edited edge metadata.

LGTM

This revision is now accepted and ready to land.May 10 2016, 9:43 AM
This revision was automatically updated to reflect the committed changes.
MatzeB added inline comments.May 10 2016, 11:05 AM
llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
974–975 ↗(On Diff #56742)

This will subregister defs which are uses as well, should be `!MO.readsReg())!

atrick added inline comments.May 10 2016, 11:14 AM
llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
974–975 ↗(On Diff #56742)

Matthias, can you clarify? We don't want addPhysRefDefs to be called twice for the same subreg!

MatzeB added inline comments.May 10 2016, 11:19 AM
llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
974–975 ↗(On Diff #56742)

Something like this:
%vreg0:sub0 = ... is both a definition and a use! (at least if lanemask tracking is not enabled), we still need to record it as a use. physregs never have subregister indexes so MO.readsReg() will never return true for physreg definitions.

MatzeB added inline comments.May 10 2016, 11:20 AM
llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
974–975 ↗(On Diff #56742)

It would also be nice to split addPhysRegDeps() into addPhysRegUseDeps() and addPhysRegDefDeps().

MatzeB added inline comments.May 10 2016, 11:29 AM
llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
974–975 ↗(On Diff #56742)

Hmm it looks like the code before this patch only used output dependencies for this case. So this change is fine in preserving that behavior.

atrick added inline comments.May 10 2016, 11:40 AM
llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
974–975 ↗(On Diff #56742)

I *think* Matthias is saying that this patch will fail to call addVRegUseDeps for subregs. So, that needs to be fixed but in a way that doesn't call addPhysRegDeps twice on the same operand.

Maybe Matthias can suggest a fix!

I am fine with the change as is now after realizing that it does not change the behaviour of the subregister def case. So this change is fine!

I am still confused as to why we could get away with ignoring those uses before. I guess output dependencies are enough to get the instruction order right, but this should be commented on and I'd like to check that it doesn't influence register pressure computation.

  • Matthias

I think this is a fairly rare case. There has to be an explicit use and then an implicit def of the same register. This came up for us in the Perennial C++ test suite.

Just chatted with Matthias. This patch as fine as-is--it preserves behavior. Matthias will add a comment explaining the pre-existing behavior.