This is an archive of the discontinued LLVM Phabricator instance.

Patch for dbg variable instrinsics to point towards cloned values in JumpThreading
ClosedPublic

Authored by BenJMudd on Dec 20 2022, 8:05 AM.

Details

Summary

This is a patch to fix debug value intrinsics outside of cloned blocks in the jumpthreading pass to point towards any derived values. If it cannot it sets them to undef

Diff Detail

Event Timeline

BenJMudd created this revision.Dec 20 2022, 8:05 AM
BenJMudd requested review of this revision.Dec 20 2022, 8:05 AM
nlopes added inline comments.Dec 20 2022, 10:48 AM
llvm/lib/Transforms/Utils/SSAUpdater.cpp
221

Please use PoisonValue as placeholder whenever possible. We are trying to get rid of undef in LLVM.
Thank you!

BenJMudd added inline comments.Dec 21 2022, 2:33 AM
llvm/lib/Transforms/Utils/SSAUpdater.cpp
221

This patch doesnt introduce any newly created undef Values, just moving where they're created, so I believe it should stay undef for now, until this and the relevant tests are migrated

Please use clang-format-patch to correct some style issues.

probinson added inline comments.Dec 21 2022, 3:37 AM
llvm/include/llvm/Transforms/Utils/SSAUpdater.h
121
BenJMudd updated this revision to Diff 484545.Dec 21 2022, 5:29 AM

Used clang-format-diff to fix formatting issues brought up by Paul Robinson

BenJMudd updated this revision to Diff 484546.Dec 21 2022, 5:32 AM

it's -> its

BenJMudd marked an inline comment as done.Dec 21 2022, 5:32 AM

Please generate diffs with full context (e.g., -U999999 in the diff/show command). It's really helpful to be able to look above and below the modified lines to understand the context of the patch.

BenJMudd updated this revision to Diff 487325.Jan 9 2023, 1:16 AM

Added context to diff file

One minor comment. I don't feel comfortable enough with metadata to actually approve this, however.

llvm/lib/Transforms/Scalar/JumpThreading.cpp
2058
BenJMudd updated this revision to Diff 488114.Jan 11 2023, 1:45 AM

Added comment from Paul Robinson

BenJMudd marked an inline comment as done.Jan 11 2023, 1:45 AM
StephenTozer accepted this revision.Jan 16 2023, 4:20 AM

Changes LGTM!

This revision is now accepted and ready to land.Jan 16 2023, 4:20 AM
BenJMudd updated this revision to Diff 493520.EditedJan 31 2023, 1:42 AM

Moved definition of NewVal in SSAUpdater.cpp line 217 -> 219

This revision was landed with ongoing or failed builds.Feb 1 2023, 4:54 AM
This revision was automatically updated to reflect the committed changes.
Michael137 added a subscriber: Michael137.EditedFeb 1 2023, 8:00 AM

FYI, it looks like this broke https://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/50434/testReport/junit/lldb-api/tools_lldb-vscode_optimized/TestVSCode_optimized_py/ where we're presumably relying on a variable to have gotten optimised out but which is now not the case anymore. So not an issue with this patch necessarily, just notifying.

Snippet from test:

int main(int argc, char const *argv[]) {               
  int optimized = argc > 1 ? std::stoi(argv[1]) : 0;   
                                                       
  printf("argc: %d, optimized: %d\n", argc, optimized);

compiled with -glldb -O3

FYI, it looks like this broke https://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/50434/testReport/junit/lldb-api/tools_lldb-vscode_optimized/TestVSCode_optimized_py/ where we're presumably relying on a variable to have gotten optimised out but which is now not the case anymore. So not an issue with this patch necessarily, just notifying.

Snippet from test:

int main(int argc, char const *argv[]) {               
  int optimized = argc > 1 ? std::stoi(argv[1]) : 0;   
                                                       
  printf("argc: %d, optimized: %d\n", argc, optimized);

compiled with -glldb -O3

FYI, it looks like this broke https://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/50434/testReport/junit/lldb-api/tools_lldb-vscode_optimized/TestVSCode_optimized_py/ where we're presumably relying on a variable to have gotten optimised out but which is now not the case anymore. So not an issue with this patch necessarily, just notifying.

Snippet from test:

int main(int argc, char const *argv[]) {               
  int optimized = argc > 1 ? std::stoi(argv[1]) : 0;   
                                                       
  printf("argc: %d, optimized: %d\n", argc, optimized);

compiled with -glldb -O3

If it's relying on debug info to get lost would using a nodebug attribute work, or does it need a variable, but without a location? In that case, we could rewrite the test to compile to LLVM IR at -O0, use sed to remote the location from the dbg.declare() and then compile the patch IR with clang. That would be cross-architecture and slightly more reliable (if still ugly) than relying on -O3 doing something specific.

jgorbe added a subscriber: jgorbe.Feb 1 2023, 11:16 AM
uabelho added a subscriber: uabelho.Feb 7 2023, 1:05 AM

Hi,

It looks like this patch makes jump-threading yield different results with/without debug info.
With

opt -passes=jump-threading bbi-78731_red.ll -S -o -

We get e.g

for.cond:                                         ; preds = %lor.end51, %entry
  %cond4130 = phi i32 [ undef, %entry ], [ %cond4131, %lor.end51 ]
  %e.0 = phi i32 [ 0, %entry ], [ %cond3111226, %lor.end51 ]

and if we comment out the call to llvm.dbg.value we instead get

for.cond:                                         ; preds = %lor.end51, %entry
  %e.0 = phi i32 [ 0, %entry ], [ %cond3111226, %lor.end51 ]

jmorse added a comment.Feb 7 2023, 3:30 AM

/me squints -- I think the idea here was that if SSAUpdater has a value at the end of the block we can use that and it won't cause new codegen; but then we're using GetValueInMiddleOfBlock, which will generate code in certain circumstances.

@StephenTozer @BenJMudd Presumably we can just use GetValueAtEndOfBlock as this isn't a general SSA update query, we have a guarantee that only blocks outside of the the (threaded) value definitions will be updated, where there's no need to consider definitions in the middle of the block.

/me squints -- I think the idea here was that if SSAUpdater has a value at the end of the block we can use that and it won't cause new codegen; but then we're using GetValueInMiddleOfBlock, which will generate code in certain circumstances.

@StephenTozer @BenJMudd Presumably we can just use GetValueAtEndOfBlock as this isn't a general SSA update query, we have a guarantee that only blocks outside of the the (threaded) value definitions will be updated, where there's no need to consider definitions in the middle of the block.

I just did a quick test to do

 void SSAUpdater::UpdateDebugValue(Instruction *I, DbgValueInst *DbgValue) {
   BasicBlock *UserBB = DbgValue->getParent();
   if (HasValueForBlock(UserBB)) {
-    Value *NewVal = GetValueInMiddleOfBlock(UserBB);
+    Value *NewVal = GetValueAtEndOfBlock(UserBB);
     DbgValue->replaceVariableLocationOp(I, NewVal);
   }
   else
     DbgValue->setKillLocation();
 }

and then the difference I saw with/without debug info disappears.
I don't know anything about this, just wanted to let you know your suggestion indeed seems to work.

/me squints -- I think the idea here was that if SSAUpdater has a value at the end of the block we can use that and it won't cause new codegen; but then we're using GetValueInMiddleOfBlock, which will generate code in certain circumstances.

Ah, my bad - I've bumped into this before and saw the potential for CodeGen changes, but misread/misremembered the logic and thought that the HasValueForBlock check was guarding against CodeGen. I think GetValueAtEndOfBlock can also generate SSA, the function for this is FindValueForBlock.

Ah ok, I had no idea that GetValueInMiddleOfBlock was causing code gen. @StephenTozer using FindValueForBlock seems to be the best solution then, thanks.

StephenTozer added a comment.EditedFeb 7 2023, 3:48 AM

Actually looking back over it I'd add further - FindValueForBlock isn't necessarily right because we're looking for values in the middle of the block, and that function will give us the value at the end only (which may be incorrect depending on the position of the debug value). I encountered this problem in MachineSSAUpdater, and the approach I took there was to add a ExistingValueOnly parameter to GetValue(InMiddle|AtEnd)OfBlock that performs all the same logic but returns empty if it would need to generate any code to provide a value. Happy to repeat that fix here!

jmorse added a comment.Feb 7 2023, 3:49 AM

Cool, sounds like this is just a case of mistaken-function-identity, thanks for catching this @uabelho. I'll drop in a follow-up patch shortly to use GetValueAtEndOfBlock