[InstCombine] Remove invariant group intrinsincs when comparing against null
authorArthur Eubanks <aeubanks@google.com>
Wed, 25 Aug 2021 18:31:22 +0000 (11:31 -0700)
committerArthur Eubanks <aeubanks@google.com>
Sun, 29 Aug 2021 22:45:25 +0000 (15:45 -0700)
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

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/invariant.group.ll

index 7103761..0ff23b4 100644 (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;
 }
 
index a1ed714..da3d8a7 100644 (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*