This is an archive of the discontinued LLVM Phabricator instance.

Fix for a dangling point bug in DeadStoreElimination pass
ClosedPublic

Authored by quic_aankit on Jul 26 2019, 3:37 AM.

Details

Summary

The patch makes sure that the LastThrowing pointer does not point to any instruction deleted by call to DeleteDeadInstruction.

While iterating through the instructions the pass maintains a pointer to the lastThrowing Instruction. A call to deleteDeadInstruction deletes a dead store and other instructions feeding the original dead instruction which also become dead. The instruction pointed by the lastThrowing pointer could also be deleted by the call to DeleteDeadInstruction and thus it becomes a dangling pointer. Because of this, we see an error in the next iteration.

In the patch, we maintain a list of throwing instructions encountered previously and use the last non deleted throwing instruction from the container.

Diff Detail

Event Timeline

quic_aankit created this revision.Jul 26 2019, 3:37 AM

I think SetVector would be more suitable and lead to slightly simpler code (http://llvm.org/doxygen/classllvm_1_1SetVector.html)

Also, could you upload the patch with more context? (git show HEAD -U999999)

Uploading patch with more context

I think SetVector would be more suitable and lead to slightly simpler code (http://llvm.org/doxygen/classllvm_1_1SetVector.html)

Also, could you upload the patch with more context? (git show HEAD -U999999)

Uploaded the patch with more context.

The main motivation to use MapVector is for searching the deletedInstruction in the list of lastThrowing Instructions (Line120). With SetVector this step will be expensive.

I think SetVector would be more suitable and lead to slightly simpler code (http://llvm.org/doxygen/classllvm_1_1SetVector.html)

Also, could you upload the patch with more context? (git show HEAD -U999999)

Uploaded the patch with more context.

The main motivation to use MapVector is for searching the deletedInstruction in the list of lastThrowing Instructions (Line120). With SetVector this step will be expensive.

Right, the interface to SetVector is a bit unfortunate in that respect :( It's probably not worth generalizing that for now, especially if we can keep the logic to clean up the map in deleteDeadInstructions.

Some comments inline. Would it be possible to add a test where multiple entries are removed from the mapping in a single deleteDeadInstructions call? Not sure if that can be the case, IIUC that would require deleting a function that may throw with an argument that may throw as well, but can be removed once it is dead.

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
118

LLVM convention is to have upper case names for variables (same below)

1164

I think we could move the code to pop the removed instructions from the map to deleteDeadInstructions. That would keep the logic to manage the map in one place and here we can simply use the last instruction in the map as LastThrowing I think.

1165

AFAIK we are looking for the last throwing instruction we encountered, but this will set it to the first? Shouldn't check the map in reverse insertion order?

Otherwise we remove the store between the @foo calls, which we would have to preserve, as @foo may throw.

declare i8* @_Znwj(i32) local_unnamed_addr

declare void @foo() readnone
; CHECK-LABEL: @test(
; CHECK-NEXT: store
; CHECK-NEXT: ret void
define void @test(i8** %ptr, i8* %p1, i8* %p2) {
  store i8* undef, i8** %ptr
  call void @foo()
  store i8* %p1, i8** %ptr
  call void @foo()
  store i8* %p2, i8** %ptr
  %call = call i8* @_Znwj(i32 1)
  store i8* %call, i8** %ptr
  store i8* undef, i8** %ptr
  ret void
}
quic_aankit marked an inline comment as done.

Hi fhahn, sorry for the delay. I've addressed your comments. However, I was unable to add a test where multiple entries are removed from the mapping in a single deleteDeadInstructions call. The method you suggested does not work because deleting a function that may throw is not a legal operation. In the testcase that I have since it is a new function call "_Znwj", we are able to remove the call.

quic_aankit marked 4 inline comments as done.Sep 16 2019, 7:19 AM
quic_aankit added inline comments.
llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
1164

I've moved the code up in deleteDeadInstructions. I had this here to be able to use inexpensive pop_back instead of the expensive erase. But I think your suggestion makes more sense.

1165

I'm sorry. This had to be a reverse iterator. I've corrected it in the new patch

fhahn added a comment.Nov 2 2019, 2:53 PM

Sorry for the long delay! I had to go through the comments again.

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
103

Please run clang-format before committing. I think this should be <Instruction *, bool>.

119

I think it would be better to not use erase, as you had originally, i.e. set ThrowableInst[DeadInst] = false. What I meant with my last comment was that we could pop false values from the back of ThrowableInst at the end of this function, until we reach one element that's true. Or do it at the place you had originally, just with the right reverse iterator.

llvm/test/Transforms/DeadStoreElimination/DeleteThrowableInst.ll
1

Can you please also add the test I mentioned in the comment?

fhahn added a comment.Nov 28 2019, 8:59 AM

Reverse ping.

Are you still looking to submit this patch? If so, it would be great to not wait too long with responding, otherwise the reviewers will have to re-familiarize themselves with the patch and the comment history.

Reverse ping.

Are you still looking to submit this patch? If so, it would be great to not wait too long with responding, otherwise the reviewers will have to re-familiarize themselves with the patch and the comment history.

Sorry about it. Working on your comments right away.

Hi @fhahn , I've updated the patch to address your comments

fhahn accepted this revision.Dec 2 2019, 7:28 AM

LGTM with 2 optional nits, thanks!

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
154

Shouldn't we increment It early, as we remove the element It refers to? It does not seem to cause any issue, but FWIW, it seems that for SPEC and the test-suite, we always do at most 1 iteration of the loop.

llvm/test/Transforms/DeadStoreElimination/DeleteThrowableInst.ll
26

It might be better to store a concrete value instead undef (here and other places in the test casE) to make to test case more robust against future changes.

This revision is now accepted and ready to land.Dec 2 2019, 7:28 AM
quic_aankit marked 2 inline comments as done.
quic_aankit marked an inline comment as done.
quic_aankit added inline comments.
llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
154

I don't think that incrementing It after removing the element pointed by it should be an issue as we are not accessing the element in between. In the latest patch I've incremented It before removing the element.

fhahn added a comment.Dec 3 2019, 11:33 AM

Thanks! Do you need someone to commit the patch?

I'm trying to get access to commit the patch, but it would be great if you can get someone to commit it.

fhahn added a comment.Dec 5 2019, 9:30 AM

I'm trying to get access to commit the patch, but it would be great if you can get someone to commit it.

Sure thing, I can commit it on your behalf!

This revision was automatically updated to reflect the committed changes.
quic_aankit added a comment.EditedDec 5 2019, 11:10 AM

Hi @fhahn , the commit caused a buildbot failure.
http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/20911
Can you please revert the patch for now while I investigate the issue?

fhahn added a comment.Dec 5 2019, 11:33 AM

Hi @fhahn , the commit caused a buildbot failure.
http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/20911
Can you please revert the patch for now while I investigate the issue?

Done in rG19071173fc2e

Hi @fhahn, I've updated the patch to handle the failure with MSVC. Using iterator with pop_back was causing problems on windows.