This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Remove invariant group intrinsincs when comparing against null
ClosedPublic

Authored by aeubanks on Aug 25 2021, 3:13 PM.

Details

Summary

We cannot leak any equivalency information by comparing against null
since null never has virtual metadata associated with it (when null is
not a valid dereferenceable pointer).

Instcombine seems to make sure that a null will be on the RHS, so we
don't have to check both operands.

This fixes a missed optimization in llvm-test-suite's MultiSource lambda
benchmark under -fstrict-vtable-pointers.

Diff Detail

Event Timeline

aeubanks created this revision.Aug 25 2021, 3:13 PM
aeubanks requested review of this revision.Aug 25 2021, 3:13 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 25 2021, 3:13 PM
lebedev.ri added inline comments.Aug 25 2021, 3:29 PM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5705–5724

In-place replacements aren't nice.
How about:

llvm/test/Transforms/InstCombine/invariant.group.ll
2

I'm not sure what this is testing, but pass tests that involve more than a single pass are frowned upon.

aeubanks updated this revision to Diff 368761.Aug 25 2021, 3:40 PM

cleanup code

Code-wise this seems fine, but i'm not sure i'm sufficiently familiar with the semantics.

hmm, if two pointers are equal in an icmp, will GVN RAUW one with the other based on that info? maybe I'm completely missing something

nvm I think this patch is wrong

Prazek requested changes to this revision.Aug 26 2021, 5:30 AM

Lets talk offline about the specific case to get it right. The model is pretty brittle in those areas, so we have to be sure the transformations are legal

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5705–5717

If I understand this correctly, this essentially strips launders/strips from cmp operands.

I think this is incorrect. From the perspective of devirtualization we can have code like:

%vtable_a = load i8* %a, !invariant.group !{}
;;;
; %a == %b
%addr_a = call i8* @llvm.strip.invariant.group(i8* %a)
%addr_b = call i8* @llvm.strip.invariant.group(i8* %b)
%bool = icmp %addr_a, %addr_b
br %bool, %if, %after
if:
; This will not be able to change %b to %a
%vtable_b = load i8* %b, !invariant.group !{}

As you see, the two loads operate on %a and %b (where %b is a result of launder). As comparisons can leak the idea that %a and %b are essentially the same addresses (thus enabling GVN to RAUW %b with %a), we need to strip it before cmp.

In this case, we would replace the cmp with icmp %a %b, which would essentially tell GVN %a and %b can be used interchanganbly in this branch.

This revision now requires changes to proceed.Aug 26 2021, 5:30 AM

Just for the record (discussed offline): if the problem is comparisons of launder/strip(%p) with null, then for this specific case we could I think replace it with comparison of %p and null, as null does does not have any "virtual" information (similarly how we already optimzie launder/strip(null) to null

aeubanks updated this revision to Diff 368976.Aug 26 2021, 1:57 PM

only optimize null comparisons

aeubanks edited the summary of this revision. (Show Details)Aug 26 2021, 1:58 PM
aeubanks edited the summary of this revision. (Show Details)
Prazek accepted this revision.Aug 27 2021, 2:14 AM

LGTM! Great work with looking for regressions like that.

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5715

I wonder if the fact that usually there are bitcasts around strip/launder could be problematic.
I think this does not handle case like:

%b1 = bitcast i32* %p to i8*
%b2 = strip(%b1)
%b3 = bitcast i8* %b2 to i32*

icmp %b3, null

But it might be not a problem, if this code gets cannonicalized to:

%b1 = bitcast i32* %p to i8*
%b2 = strip(%b1)

icmp %b2, null

Could you double check if this would be optimized by InstCombine allone, or that there is any pass that would cannonicalize it?

This revision is now accepted and ready to land.Aug 27 2021, 2:14 AM

Seems fine to me with nits

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5709–5711
5714–5715

Could flatten the if's

5719

Could do early-return, but not sure how better that would be here

Could you also update the description and title?

aeubanks retitled this revision from [InstCombine] Replace icmp invariant group operands with the invariant group's operands to [InstCombine] Remove invariant group intrinsincs when comparing against null.Aug 27 2021, 11:08 AM
aeubanks marked an inline comment as done.Aug 27 2021, 11:20 AM
aeubanks added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5709–5711

it's hard to read with a multi-line if condition IMO

5715

added a test to verify that instcombine takes care of this

Prazek accepted this revision.Aug 28 2021, 3:59 AM

LGTM!