This is an archive of the discontinued LLVM Phabricator instance.

[clang/DIVar] Emit flag for params that have unchanged values
ClosedPublic

Authored by djtodoro on Feb 11 2019, 3:21 AM.

Details

Summary

Emit debug info flag that indicates that a parameter has unchanged value through the course of a function.

This info will be used for emitting DW_OP_entry_value expressions for the parameter.

Authors: @asowda, @NikolaPrica, @djtodoro, @ivanbaev

Diff Detail

Repository
rL LLVM

Event Timeline

djtodoro created this revision.Feb 11 2019, 3:21 AM
djtodoro added a project: debug-info.
djtodoro added a subscriber: petarj.
djtodoro updated this revision to Diff 186611.Feb 13 2019, 2:42 AM
  • Rename: VariableNotChanged ===> ArgumentNotModified
  • Refactor a test case
probinson added inline comments.Feb 21 2019, 10:36 AM
include/clang/AST/Decl.h
1482 ↗(On Diff #186611)

There should be a comment here.
The style in this class appears to omit the 'get' word from the name of the getter, so isArgumentModified for the method name would look more consistent.

lib/Sema/SemaExpr.cpp
11282 ↗(On Diff #186611)

Does this fit on one line if you use const auto *LHSDeclRef ...? Given you have the dyn_cast on the RHS there's no real need to give the type name twice.

+ rsmith, + bricci for review.

I was under the impression that space inside VarDecl was quite constrained. Pardon the likely naive question, but: is there any way to make the representation more compact (maybe sneak a bit into ParmVarDeclBitfields)?

riccibruno edited reviewers, added: riccibruno; removed: bricci.Feb 21 2019, 1:04 PM

If this bit is relevant to function parameters, why is getIsArgumentModified in VarDecl and not in ParamVarDecl ? What you can do is move the relevant methods to ParamVarDecl, and stash the bit in ParmVarDeclBitfields.

include/clang/AST/Decl.h
843 ↗(On Diff #186611)

Yeah, please don't waste a whole pointer just to store a bit.

Oh and I think that you will also have to update the serialization code/de-serialization code in ASTReaderDecl.cpp / ASTWriterDecl.cpp. You might also have to update TreeTransform but I am less familiar with this.

I am wondering about the semantics of this bit. I don't think that you can know for sure within clang whether a variable has been modified. The best you can do is know for sure that some variable has been modified, but I don't think you can prove that it has not been modified.

Consequently I am wondering if you should change the name of this flag to something like IsArgumentKnownToBeModified.

Orthogonal to this you need to also add tests for templates.

djtodoro marked 2 inline comments as done.Feb 22 2019, 6:22 AM

I was under the impression that space inside VarDecl was quite constrained. Pardon the likely naive question, but: is there any way to make the representation more compact (maybe sneak a bit into ParmVarDeclBitfields)?

@vsk Thanks for the comment! Sure, it is better idea. Initially, we thought this could be used even for local variables, but since we are using it only for parameters it makes more sense.

lib/Sema/SemaExpr.cpp
11282 ↗(On Diff #186611)

Does this fit on one line if you use const auto *LHSDeclRef ...? Given you have the dyn_cast on the RHS there's no real need to give the type name twice.

@probinson Thanks for the comment! Sure, it will be refactored.

djtodoro marked an inline comment as done.Feb 22 2019, 6:27 AM

@riccibruno Thanks for your comments!

Oh and I think that you will also have to update the serialization code/de-serialization code in ASTReaderDecl.cpp / ASTWriterDecl.cpp. You might also have to update TreeTransform but I am less familiar with this.

I've added ASTReaderDecl.cpp / ASTWriterDecl.cpp, but looking at TreeTransform I'm not sure if there is a place for adding something regarding this.

I am wondering about the semantics of this bit. I don't think that you can know for sure within clang whether a variable has been modified. The best you can do is know for sure that some variable has been modified, but I don't think you can prove that it has not been modified.

Consequently I am wondering if you should change the name of this flag to something like IsArgumentKnownToBeModified.

Orthogonal to this you need to also add tests for templates.

I agree! You are right, good idea!

djtodoro updated this revision to Diff 187931.Feb 22 2019, 6:31 AM
  • Add a field in ParmVarDecl instead of VarDecl
  • Use a bit in ParmVarDeclBitfields to indicate parameter modification
  • Add support for the bit in ASTReaderDecl.cpp / ASTWriterDecl.cpp
  • Add test case for templates
riccibruno added inline comments.Feb 22 2019, 6:51 AM
lib/Sema/SemaExpr.cpp
11301 ↗(On Diff #187931)

Comments:

  1. Shouldn't you mark the variable to be modified only if CheckForModifiableLvalue returns true ?
  1. I think that you need to handle way more than just member expressions. For example are you handling (x, y) (comma operator) ? But hard-coding every cases here is probably not ideal. It would be nice if there was already some code somewhere that could help you do this.
  1. I believe that a MemberExpr has always a base. Similarly DeclRefExprs always have a referenced declaration (so you can omit the if).
lebedev.ri added inline comments.
lib/Sema/SemaExpr.cpp
11301 ↗(On Diff #187931)

I'm not quite sure what this differential is about, but i feel like mentioning ExprMutationAnalyzer lib in clang-tidy / clang-tools-extra.

I'm not quite sure what this differential is about, but i feel like mentioning ExprMutationAnalyzer lib in clang-tidy / clang-tools-extra.

Alternatively perhaps you could re-use getMemoryLocation() from D57660. It would handle for you members, references, structured bindings +more in a relatively self-contained code.

djtodoro marked an inline comment as done.Feb 25 2019, 2:23 AM

I'm not quite sure what this differential is about, but i feel like mentioning ExprMutationAnalyzer lib in clang-tidy / clang-tools-extra.

Alternatively perhaps you could re-use getMemoryLocation() from D57660. It would handle for you members, references, structured bindings +more in a relatively self-contained code.

@lebedev.ri, @riccibruno Thanks for your advices! We'll check this also.

lib/Sema/SemaExpr.cpp
11301 ↗(On Diff #187931)

@riccibruno Please find inlined replies:

  1. Shouldn't you mark the variable to be modified only if CheckForModifiableLvalue returns true ?

Hmm, we should avoid marking variables modification if this emits an error. But, we should emit it if CheckForModifiableLvalue returns false, since in the case of returning true an error will be emitted.

  1. I think that you need to handle way more than just member expressions. For example are you handling (x, y) (comma operator) ? But hard-coding every cases here is probably not ideal. It would be nice if there was already some code somewhere that could help you do this.

Hard coding all cases is not good idea. I agree. Since we are only looking for declaration references, we could make just a function that traverses any Expr and find declaration ref.

  1. I believe that a MemberExpr has always a base. Similarly DeclRefExprs always have a referenced declaration (so you can omit the if).

I think you are right. Thanks!

djtodoro updated this revision to Diff 188110.Feb 25 2019, 2:40 AM
  • Handle all kinds of expressions when mark a param's modification
riccibruno added inline comments.Feb 25 2019, 7:05 AM
lib/Sema/SemaExpr.cpp
11292 ↗(On Diff #188110)

Hmm, I don't think that this will work. Suppose that you have an expression like (a, b) += c You want to mark b as modified, but not a. What is needed I believe is:

Given an expression E find the variable that this expression designate if any, and if it is a function parameter mark it "known to be modified".

Visiting all of the children just looking for DeclRefExprs is a bit too blunt I believe.

11316 ↗(On Diff #188110)

Hmm, we should avoid marking variables modification if this emits an error. But, we should emit it if CheckForModifiableLvalue returns false, since in the case of returning true an error will be emitted.

You are right, I believed for a moment that CheckForModifiableLvalue returned false on error.

djtodoro marked an inline comment as done.Feb 26 2019, 7:11 AM
djtodoro added inline comments.
lib/Sema/SemaExpr.cpp
11292 ↗(On Diff #188110)

You are right. We thought it is possible implementing this with some basic analysis (with low overhead), but in order to support all cases it would take much time and it is not good idea.

I tried to use ExprMutationAnalyzer (that @lebedev.ri mentioned) and it seems to be useful for this. It seems that it can be used a little bit later than in this phase, because it takes ASTContext, but in this stage we have ASTContext finished up to node we are currently observing (an expression from which we are extracting DeclRef). But, even using it in the right time, it seems that ExprMutationAnalyzer does not have support for comma operator. I'm trying to extend this analyzer in order to add support for that. ASAP I will post new changes.
For the other cases I tried, it works.

djtodoro updated this revision to Diff 195192.Apr 15 2019, 8:31 AM

-Rebase
-Use ExprMutationAnalyzer for parameter's modification check

aprantl added inline comments.Apr 15 2019, 8:38 PM
lib/CodeGen/CGDebugInfo.cpp
4537 ↗(On Diff #195192)

Just looking at the type declarations in CGDebugInfo.h: Why not iterate over the SPCache directly? Shouldn't that contain all Function declarations only?

4541 ↗(On Diff #195192)

clang-format please

4546 ↗(On Diff #195192)

Could this be a cast<>?

djtodoro marked 3 inline comments as done.Apr 16 2019, 5:41 AM
djtodoro added inline comments.
lib/CodeGen/CGDebugInfo.cpp
4537 ↗(On Diff #195192)

I tried it, but SPCache is empty at this point.

djtodoro updated this revision to Diff 195359.Apr 16 2019, 5:44 AM

-Run clang-format
-Use cast instead of 'dyn_cast'

aprantl added inline comments.May 13 2019, 10:15 AM
lib/CodeGen/CGDebugInfo.cpp
3885 ↗(On Diff #199214)

A dyn_cast followed by an unconditional use seems strange. I would expect either a cast or an if (PD) check.

djtodoro marked an inline comment as done.May 16 2019, 4:54 AM
djtodoro added inline comments.
lib/CodeGen/CGDebugInfo.cpp
3885 ↗(On Diff #199214)

Yes, thanks for this!

djtodoro updated this revision to Diff 199788.May 16 2019, 4:58 AM

-Careful use of dyn_cast
-Fill the ParamCache only in the case of EnableDebugEntryValues option

aprantl added inline comments.May 16 2019, 3:31 PM
lib/CodeGen/CGDebugInfo.cpp
3885 ↗(On Diff #199788)

We shouldn't query CGM.getLangOpts().Optimize. If we don't want this to happen at -O0, we shouldn't set EnableDebugEntryValues at a higher level (Driver, CompilerInvocation, ...) ..Otherwise inevitably someone will query one but not the other and things will go out of sync.

4535 ↗(On Diff #199788)

Please add either a top-level comment about what this block is doing or perhaps factor this out into a descriptively named static function.

4537 ↗(On Diff #195192)

Where is it emptied? Just grepping through CGDebugInfo did not make this obvious to me.

djtodoro marked 3 inline comments as done.May 17 2019, 7:18 AM
djtodoro added inline comments.
lib/CodeGen/CGDebugInfo.cpp
3885 ↗(On Diff #199788)

I agree. Thanks!

4535 ↗(On Diff #199788)

Sure.

4537 ↗(On Diff #195192)

The SPCache actually gets filled only in the case of CXXMemberFunction.
In the other cases of SP production there is only filling of DeclCache.
Should we use it like this or ?

aprantl added inline comments.May 17 2019, 9:57 AM
lib/CodeGen/CGDebugInfo.cpp
4537 ↗(On Diff #195192)

If the number of entries in the DeclCache is much larger than the size of SPCache, we should keep them separate to speed up this loop. Otherwise we should join them to conserve memory.

djtodoro updated this revision to Diff 200486.May 21 2019, 6:38 AM

-Use SPCache instead of DeclCache
-Refactor the code by addressing suggestions

aprantl added inline comments.May 21 2019, 11:14 AM
lib/CodeGen/CGDebugInfo.cpp
4468 ↗(On Diff #200486)

/// Analyzes each function parameter to determine whether it is constant throughout the function body.

4478 ↗(On Diff #200486)
if (FuncAnalyzer.isMutated(Parm))
  continue;
4483 ↗(On Diff #200486)

should the else be an assertion or are there legitimate failure cases?

aprantl accepted this revision.May 21 2019, 11:14 AM

Couple more nitpicks, but otherwise good.

This revision is now accepted and ready to land.May 21 2019, 11:14 AM
djtodoro updated this revision to Diff 200950.May 23 2019, 6:15 AM

-Add SPDefCache to speed up the process
-Add additional assertions that will improve quality of the code

djtodoro updated this revision to Diff 201505.May 27 2019, 5:10 AM

-Rebase
-Add a test

This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptJun 26 2019, 6:33 AM