[InstCombine] Remove invariant group intrinsincs when comparing against null

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.

Reviewed By: Prazek

Differential Revision: https://reviews.llvm.org/D108734
This commit is contained in:
Arthur Eubanks 2021-08-25 11:31:22 -07:00
parent 4b1fde8a2b
commit 099e4bcd5d
2 changed files with 24 additions and 9 deletions

View File

@ -5702,6 +5702,23 @@ static Instruction *foldICmpOfUAddOv(ICmpInst &I) {
return ExtractValueInst::Create(UAddOv, 1);
}
static Instruction *foldICmpInvariantGroup(ICmpInst &I) {
if (!I.getOperand(0)->getType()->isPointerTy() ||
NullPointerIsDefined(
I.getParent()->getParent(),
I.getOperand(0)->getType()->getPointerAddressSpace())) {
return nullptr;
}
Instruction *Op;
if (match(I.getOperand(0), m_Instruction(Op)) &&
match(I.getOperand(1), m_Zero()) &&
Op->isLaunderOrStripInvariantGroup()) {
return ICmpInst::Create(Instruction::ICmp, I.getPredicate(),
Op->getOperand(0), I.getOperand(1));
}
return nullptr;
}
Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
bool Changed = false;
const SimplifyQuery Q = SQ.getWithInstruction(&I);
@ -5942,6 +5959,9 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
if (Instruction *Res = foldVectorCmp(I, Builder))
return Res;
if (Instruction *Res = foldICmpInvariantGroup(I))
return Res;
return Changed ? &I : nullptr;
}

View File

@ -161,8 +161,7 @@ define i16 addrspace(42)* @skipWithDifferentTypesDifferentAddrspace(i8* %a) {
define i1 @icmp_null_launder(i8* %a) {
; CHECK-LABEL: @icmp_null_launder(
; CHECK-NEXT: [[A2:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* [[A:%.*]])
; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A2]], null
; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A:%.*]], null
; CHECK-NEXT: ret i1 [[R]]
;
%a2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %a)
@ -172,8 +171,7 @@ define i1 @icmp_null_launder(i8* %a) {
define i1 @icmp_null_strip(i8* %a) {
; CHECK-LABEL: @icmp_null_strip(
; CHECK-NEXT: [[A2:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* [[A:%.*]])
; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A2]], null
; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A:%.*]], null
; CHECK-NEXT: ret i1 [[R]]
;
%a2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
@ -206,8 +204,7 @@ define i1 @icmp_null_strip_valid_null(i8* %a) #0 {
; Check that null always becomes the RHS
define i1 @icmp_null_launder_lhs(i8* %a) {
; CHECK-LABEL: @icmp_null_launder_lhs(
; CHECK-NEXT: [[A2:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* [[A:%.*]])
; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A2]], null
; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A:%.*]], null
; CHECK-NEXT: ret i1 [[R]]
;
%a2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %a)
@ -217,9 +214,7 @@ define i1 @icmp_null_launder_lhs(i8* %a) {
define i1 @icmp_null_launder_bitcasts(i32* %a) {
; CHECK-LABEL: @icmp_null_launder_bitcasts(
; CHECK-NEXT: [[A2:%.*]] = bitcast i32* [[A:%.*]] to i8*
; CHECK-NEXT: [[A3:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* [[A2]])
; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A3]], null
; CHECK-NEXT: [[R:%.*]] = icmp eq i32* [[A:%.*]], null
; CHECK-NEXT: ret i1 [[R]]
;
%a2 = bitcast i32* %a to i8*