This is an archive of the discontinued LLVM Phabricator instance.

[OpenMPOpt] Validate declaration types against the expected types
ClosedPublic

Authored by hamax97 on Mar 12 2020, 4:28 AM.

Details

Summary

Validation of the found runtime library functions declarations types (return and argument types) with the expected types.

Diff Detail

Event Timeline

hamax97 created this revision.Mar 12 2020, 4:28 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 12 2020, 4:28 AM
hamax97 edited the summary of this revision. (Show Details)Mar 12 2020, 4:30 AM
hamax97 edited projects, added Restricted Project; removed Restricted Project.Mar 12 2020, 6:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 12 2020, 6:39 PM

Thanks for the patch!

(Check out the phabricator documentation on llvm.org to see how to upload patches with full context)

Two things that are missing are:

  1. clear the RFI, or not create it in the first place if the types not match, e.g., use _ReturnType and __VA_ARGS__ directly.
  2. Add test cases for the different problems, too many/few arguments, wrong return or argument type. You can for example test it via the statistics or by verifying an optimization does not happen, e.g., deduplication.
llvm/lib/Transforms/IPO/OpenMPOpt.cpp
398

You can use pointer comparison on llvm::Type directly, they are unique.

400

You also need to make sure if the function is varidic as we might expect less arguments. There should be a test as well, we already have known functions that are variadic __kmpc_fork_call or something similar.

404

This is a good case for auto (IMHO). The kind of container is an implementation detail that should not escape and is not helpful, auto RTFTyIt = ...; should do the trick :)

413

Make this a (static) class function if possible.

hamax97 updated this revision to Diff 250344.Mar 13 2020, 8:34 PM
  1. RFI is not created unless the declaration found matches the runtime function type.
  2. Conditional modified to check when a function is variadic.
  3. Comparison between Type* made directly.
  4. The function that checks if the types matches was moved to a class static function.
hamax97 updated this revision to Diff 250345.Mar 13 2020, 8:37 PM

Added regression test that uses the statistics to show that "runtime functions" declarations with different types than the expected are not matched.

You need to squash the commits locally into one or diff against the base or you only upload the latest ;)

jdoerfert added inline comments.Mar 13 2020, 9:37 PM
llvm/test/Transforms/OpenMP/rtf_type_checking.ll
2 ↗(On Diff #250345)

; REQUIRES: asserts

is needed so this works in builds that do not track statistics.

47 ↗(On Diff #250345)

Remove the attributes.

63 ↗(On Diff #250345)

In the comment above you say the last runtime call is matched, maybe having one that is is actually a good thing.

hamax97 updated this revision to Diff 250426.EditedMar 15 2020, 8:56 AM

Regression test modified to match a proper use of a runtime library function.
PD: Sorry for all that mess before.

hamax97 marked an inline comment as done.Mar 15 2020, 8:57 AM
hamax97 added inline comments.
llvm/test/Transforms/OpenMP/rtf_type_checking.ll
64 ↗(On Diff #250426)

The pass is run as many times as functions exist in the file. Is that the expected behavior?

Almost there :) some comments below.

llvm/lib/Transforms/IPO/OpenMPOpt.cpp
400

I think what is said here was not helpful. For the var arg case we have the function and a function type basically, both should be var arg and have the same number of arguments. I was thinking call vs function decl but that is not the case. My bad.

413

Nit: Add a TODO at the beginning of this function reminding us that we should output information to the user (under debug output and via remarks).

464

Nit: = std::move(ArgsTypes)

llvm/test/Transforms/OpenMP/rtf_type_checking.ll
64 ↗(On Diff #250426)

Yes, but part of the pass should not be run as often I guess. Though that is a problem for later.

2 ↗(On Diff #250345)

Nit: leave the RUN line at the top

hamax97 updated this revision to Diff 250433.EditedMar 15 2020, 11:50 AM
hamax97 marked an inline comment as not done.

Minor change to test file + adding std::move to object copy.

lebedev.ri retitled this revision from Validate declaration types against the expected types to [OpenMPOpt] Validate declaration types against the expected types .Mar 15 2020, 12:20 PM
hamax97 added inline comments.Mar 15 2020, 6:49 PM
llvm/lib/Transforms/IPO/OpenMPOpt.cpp
400

I don't understand what you mean. You were thinking on comparing the function call against the declaration?. Because the optimizer does that for you. The idea was to compare the declaration against the real runtime function declaration, wasn't it?.

Then is this ok?, or what should I do?

jdoerfert added inline comments.Mar 18 2020, 5:53 PM
llvm/lib/Transforms/IPO/OpenMPOpt.cpp
400

I mean, add two tests for var-args functions. One where there are not enough arguments, one where there are too many. Both should be flagged as bad. That is, the size needs to match perfectly.

hamax97 marked an inline comment as done.Mar 19 2020, 2:23 AM
hamax97 added inline comments.
llvm/lib/Transforms/IPO/OpenMPOpt.cpp
400

IMHO, I think adding a test case for when there are too many arguments in a variadic function wouldn't be useful since we can only compare against the arguments that are mandatory.

Check out how the number of arguments are being compared (Note that the argument types are checked only if the number of arguments is valid). There are 5 possible function declarations:

Variadic Function:

  1. Same number of arguments -> Which is ok.
  2. More arguments than expected. Which is ok, it's a variadic function.
  3. Less arguments than expected. Which is NOT ok, and is covered by:
if (F->arg_size() < RTFArgTypes.size())

Non-variadic function:

  1. Same number of arguments. Which is ok. What we want.
  2. Different number of arguments. Which is NOT ok, and is covered by:
if (!IsVarArg && F->arg_size() > RTFArgTypes.size())

Together with the if statement above, that checks if has less arguments, covers the second case for non-variadic functions.

hamax97 marked an inline comment as not done.Mar 19 2020, 2:23 AM
jdoerfert added inline comments.Mar 19 2020, 9:34 PM
llvm/lib/Transforms/IPO/OpenMPOpt.cpp
400

IMHO, I think adding a test case for when there are too many arguments in a variadic function wouldn't be useful since we can only compare against the arguments that are mandatory.

Sure, but we can (and should) change the way we check here so we can detect bad signatures of variadic functions that have too many or too few mandatory arguments.

More arguments than expected. Which is ok, it's a variadic function.

I disagree. We compare the declaration against an expected declaration, they should match. The number of optional arguments at the call sites is a different story though.

hamax97 updated this revision to Diff 251684.Mar 20 2020, 10:06 AM

Removing unnecessary check for variadic function.

hamax97 marked an inline comment as done.Mar 20 2020, 10:11 AM
hamax97 added inline comments.
llvm/lib/Transforms/IPO/OpenMPOpt.cpp
400

Ohhh, sure, I got you. Sorry. I was confusing function call with function declaration. Now fixed. But I cannot have two function declarations with the same function name, opt complains, and the only variadic function inside OMPKinds.def is __kmpc_fork_call.

But I have a function declaration with fewer arguments than necessary which also covers the test case you are asking for. Or do you think I might need to create another test file?.

jdoerfert accepted this revision.Mar 20 2020, 9:26 PM

LGTM. Thx!

llvm/lib/Transforms/IPO/OpenMPOpt.cpp
400

It's fine

This revision is now accepted and ready to land.Mar 20 2020, 9:26 PM

LGTM. Thx!

Thanks for your time.
I don't have commit permissions. Does it have to pass kind of another check to be pushed?.

pcc added a subscriber: pcc.Mar 23 2020, 12:07 PM

This change broke the msan buildbot: http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/39755

==70358==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x5a602b2 in deleteParallelRegions /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Transforms/IPO/OpenMPOpt.cpp:127:9
    #1 0x5a602b2 in (anonymous namespace)::OpenMPOpt::run() /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Transforms/IPO/OpenMPOpt.cpp:116:16
    #2 0x5a94252 in (anonymous namespace)::OpenMPOptLegacyPass::runOnSCC(llvm::CallGraphSCC&) /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Transforms/IPO/OpenMPOpt.cpp:559:19
    #3 0x3f53893 in RunPassOnSCC /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Analysis/CallGraphSCCPass.cpp:139:23
In D76058#1937554, @pcc wrote:

This change broke the msan buildbot: http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/39755

==70358==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x5a602b2 in deleteParallelRegions /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Transforms/IPO/OpenMPOpt.cpp:127:9
    #1 0x5a602b2 in (anonymous namespace)::OpenMPOpt::run() /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Transforms/IPO/OpenMPOpt.cpp:116:16
    #2 0x5a94252 in (anonymous namespace)::OpenMPOptLegacyPass::runOnSCC(llvm::CallGraphSCC&) /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Transforms/IPO/OpenMPOpt.cpp:559:19
    #3 0x3f53893 in RunPassOnSCC /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Analysis/CallGraphSCCPass.cpp:139:23

Oversight, thanks! Should be fixed with f09f4b26762ab5d5c15ab6f66eb02a497c5f0b8e.