Page MenuHomePhabricator

Bitcast wrapped in a call obscures function attributes, pessimizing MemorySSA
ClosedPublic

Authored by antoniofrighetto on Sep 16 2021, 8:06 AM.

Details

Summary

A logic incompleteness may lead MemorySSA to be too conservative in its results. Specifically,
when dealing with a call of kind call i32 bitcast (i1 (i1)* @test to i32 (i32)*)(i32 %1),
where function call test is declared with readonly attribute, the bitcast is not wrapped,
obscuring function attributes. Hence, some methods of CallBase (e.g., doesNotReadMemory)
could provide incomplete results. This issue was addressed with improved checks.

Diff Detail

Event Timeline

antoniofrighetto requested review of this revision.Sep 16 2021, 8:07 AM
Herald added a reviewer: baziotis. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript
nikic added a subscriber: nikic.Sep 16 2021, 8:16 AM
nikic added inline comments.
llvm/lib/IR/Instructions.cpp
353

You should be able to drop the getCalledFunction() part, as it is subsumed by the newly added code.

I'm slightly worried about the inconsistency but I am convincing myself slowly this is fine to do. I also imagine a single bitcast is the most important case to catch. The tests for MSSA is a bit obscure but I guess there is sufficient test coverage across the 4 tests.

The Attributor tests need to be updated properly though. I left comments.

llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll
1

Don't change the options.

135

Run the update script so these things don't go away.

jdoerfert added inline comments.Sep 16 2021, 8:19 AM
llvm/lib/IR/Instructions.cpp
356–357

Style suggestion, OK to ignore. I find it easier to read (less casts).

antoniofrighetto marked 2 inline comments as done.

LGTM, anyone else?

lebedev.ri accepted this revision.Sep 16 2021, 10:49 AM

LGTM, anyone else?

LG

llvm/lib/IR/Instructions.cpp
354–355

There's BitCastOperator, but it would also catch instructions

358–359

Could also use dyn_cast, don't know if that would be better/worse.

This revision is now accepted and ready to land.Sep 16 2021, 10:49 AM
antoniofrighetto marked an inline comment as done.
llvm/lib/IR/Instructions.cpp
341

I suspect methods CallBase::getIntrinsicID and CallBase::paramHasAttr might be changed as well in the future.

353

Right, forgot to drop it.

358–359

Since I've changed to use dyn_cast before, it seems reasonable to use it here too.

nikic accepted this revision.Sep 16 2021, 11:55 AM

I'm okay with this for the case of function attributes in particular, because those don't really depend on ABI considerations. I will say though that you're brushing really close to UB here, and I may push back against extending other places in this direction. Like, say you have a void(i128) and call it as void(i64, i64) knowing that under the particular ABI used those two i64s will assemble into an i128 -- is that a legal call? In what manner would a function param attribute correlate with call arguments there?

I'm okay with this for the case of function attributes in particular, because those don't really depend on ABI considerations. I will say though that you're brushing really close to UB here, and I may push back against extending other places in this direction. Like, say you have a void(i128) and call it as void(i64, i64) knowing that under the particular ABI used those two i64s will assemble into an i128 -- is that a legal call? In what manner would a function param attribute correlate with call arguments there?

I second this.

Recently I (had to) start to fix all the places in the Attributor that are not aware that call site and callee might mismatch wrt. parameters (due to casts). It's a mess even w/o attributes.
For functions we should be OK because there is no ambiguity what the "function" is.

I'm okay with this for the case of function attributes in particular, because those don't really depend on ABI considerations. I will say though that you're brushing really close to UB here, and I may push back against extending other places in this direction. Like, say you have a void(i128) and call it as void(i64, i64) knowing that under the particular ABI used those two i64s will assemble into an i128 -- is that a legal call? In what manner would a function param attribute correlate with call arguments there?

Haven't really thought about it, yet, like @jdoerfert noted, there should exist no ambiguity as far as the function is concerned.

This comment was removed by antoniofrighetto.

I don't have commit access, may anybody close this, please?

This revision is now accepted and ready to land.Sep 19 2021, 11:24 AM
This revision was automatically updated to reflect the committed changes.