This is an archive of the discontinued LLVM Phabricator instance.

[ExecutionDepsFix] Don't make copies of LiveReg objects when collecting operands for soft instructions
ClosedPublic

Authored by craig.topper on Feb 21 2017, 9:29 PM.

Details

Summary

While collecting operands we make copies of the LiveReg objects which are stored in the LiveRegs array. If the instruction uses the same register multiple times we end up with multiple copies. Later we iterate through the collected list of LiveReg objects and merge DomainValues. In the process of doing this the merge function can change the contents of the original LiveReg object in the LiveRegs array, but not the copies that have been made. So when we get to the second usage of the register we end up seeing a stale copy of the LiveReg object.

To fix this I've stopped copying and now just store a pointer to the original LiveReg object. Another option might be to avoid adding the same register to the Regs array twice, but this approach seemed simpler.

The included test case from PR 30284 exposes this bug due to an AVX-512 masked OR instruction using the same register for the passthru operand and one of the inputs to the OR operation.

Diff Detail

Repository
rL LLVM

Event Timeline

craig.topper created this revision.Feb 21 2017, 9:29 PM
myatsina edited edge metadata.Feb 22 2017, 7:46 AM

I've seen some places that do SmallVector<std::unique_ptr<type>, size>. This might be a bit better as it states explicitly that there is no duplication in this data structure.

Another option is using SamllSetVector data structure and std::sort (instead of the sorted insertion section), but it will require to define a comparison operator for LiveReg.

Can't use SmallVector of std::unique_ptr on the vector I changed because then the vector would become the owner for these objects, but they need to be owned by the LiveRegs member variable not his local vector.

RKSimon added inline comments.Feb 23 2017, 2:54 AM
lib/CodeGen/ExecutionDepsFix.cpp
737 ↗(On Diff #89319)

It looks like this code was reusing the same i variable name for the inner loop - change it if you can? Also, possibly replace with a for-range loop and just break on the insertion.

test/CodeGen/X86/pr30284.ll
5 ↗(On Diff #89319)

I realise its a test case but is it worth cleaning this up - remove unnecessary metadata etc. ?

Address Simon's feedback.

I made the outer loop a range-based for loop and commited it in r296093.

I've replaced the sorted insert loop with std::upper_bound and vector::insert which should sort in the same way though std::upper_bound would do a binary search instead of the previous linear search.

This revision is now accepted and ready to land.Feb 24 2017, 10:20 AM
This revision was automatically updated to reflect the committed changes.