diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -5702,6 +5702,23 @@ 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 @@ if (Instruction *Res = foldVectorCmp(I, Builder)) return Res; + if (Instruction *Res = foldICmpInvariantGroup(I)) + return Res; + return Changed ? &I : nullptr; } diff --git a/llvm/test/Transforms/InstCombine/invariant.group.ll b/llvm/test/Transforms/InstCombine/invariant.group.ll --- a/llvm/test/Transforms/InstCombine/invariant.group.ll +++ b/llvm/test/Transforms/InstCombine/invariant.group.ll @@ -161,8 +161,7 @@ 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_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 @@ ; 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_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*