diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -4705,10 +4705,76 @@ indicatePessimisticFixpoint(); } + /// Check if \p ICmp is an equality comparison (==/!=) with at least one + /// nullptr. If so, try to simplify it using AANonNull on the other operand. + /// Return true if successful, in that case SimplifiedAssociatedValue will be + /// updated and \p Changed is set appropriately. + bool checkForNullPtrCompare(Attributor &A, ICmpInst *ICmp, + ChangeStatus &Changed) { + if (!ICmp) + return false; + if (!ICmp->isEquality()) + return false; + + // This is a comparison with == or !-. We check for nullptr now. + bool Op0IsNull = isa(ICmp->getOperand(0)); + bool Op1IsNull = isa(ICmp->getOperand(1)); + if (!Op0IsNull && !Op1IsNull) + return false; + + LLVMContext &Ctx = ICmp->getContext(); + // Check for `nullptr ==/!= nullptr` first: + if (Op0IsNull && Op1IsNull) { + Value *NewVal = ConstantInt::get( + Type::getInt1Ty(Ctx), ICmp->getPredicate() == CmpInst::ICMP_EQ); + SimplifiedAssociatedValue = NewVal; + indicateOptimisticFixpoint(); + assert(!SimplifiedAssociatedValue.hasValue() && + "Did not expect non-fixed value for constant comparison"); + Changed = ChangeStatus::CHANGED; + return true; + } + + // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the + // non-nullptr operand and if we assume it's non-null we can conclude the + // result of the comparison. + assert((Op0IsNull || Op1IsNull) && + "Expected nullptr versus non-nullptr comparison at this point"); + + // The index is the operand that we assume is not null. + unsigned PtrIdx = Op0IsNull; + auto &PtrNonNullAA = A.getAAFor( + *this, IRPosition::value(*ICmp->getOperand(PtrIdx))); + if (!PtrNonNullAA.isAssumedNonNull()) + return false; + + // The new value depends on the predicate, true for != and false for ==. + Value *NewVal = ConstantInt::get(Type::getInt1Ty(Ctx), + ICmp->getPredicate() == CmpInst::ICMP_NE); + + assert((!SimplifiedAssociatedValue.hasValue() || + SimplifiedAssociatedValue == NewVal) && + "Did not expect to change value for zero-comparison"); + + bool HasValueBefore = SimplifiedAssociatedValue.hasValue(); + SimplifiedAssociatedValue = NewVal; + + if (PtrNonNullAA.isKnownNonNull()) + indicateOptimisticFixpoint(); + + Changed = HasValueBefore ? ChangeStatus::UNCHANGED : ChangeStatus ::CHANGED; + return true; + } + /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A) override { bool HasValueBefore = SimplifiedAssociatedValue.hasValue(); + ChangeStatus Changed; + if (checkForNullPtrCompare(A, dyn_cast(&getAnchorValue()), + Changed)) + return Changed; + auto VisitValueCB = [&](Value &V, const Instruction *CtxI, bool &, bool Stripped) -> bool { auto &AA = A.getAAFor(*this, IRPosition::value(V)); diff --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll --- a/llvm/test/Transforms/Attributor/align.ll +++ b/llvm/test/Transforms/Attributor/align.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes -; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM -; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM +; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM @@ -147,29 +147,31 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 { -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@f1 -; IS__TUNIT____-SAME: (i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null -; IS__TUNIT____-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__TUNIT____-SAME: (i8* noalias nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: br label [[TMP3:%.*]] +; IS__TUNIT____: 2: +; IS__TUNIT____-NEXT: unreachable ; IS__TUNIT____: 3: -; IS__TUNIT____-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2() -; IS__TUNIT____-NEXT: br label [[TMP5]] -; IS__TUNIT____: 5: -; IS__TUNIT____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] -; IS__TUNIT____-NEXT: ret i8* [[TMP6]] -; -; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____-LABEL: define {{[^@]+}}@f1 -; IS__CGSCC____-SAME: (i8* nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null -; IS__CGSCC____-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] -; IS__CGSCC____: 3: -; IS__CGSCC____-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2() -; IS__CGSCC____-NEXT: br label [[TMP5]] -; IS__CGSCC____: 5: -; IS__CGSCC____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] -; IS__CGSCC____-NEXT: ret i8* [[TMP6]] +; IS__TUNIT____-NEXT: ret i8* [[TMP0]] +; +; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f1 +; IS__CGSCC_OPM-SAME: (i8* nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC_OPM-NEXT: br label [[TMP3:%.*]] +; IS__CGSCC_OPM: 2: +; IS__CGSCC_OPM-NEXT: unreachable +; IS__CGSCC_OPM: 3: +; IS__CGSCC_OPM-NEXT: ret i8* [[TMP0]] +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f1() local_unnamed_addr +; IS__CGSCC_NPM-NEXT: br label [[TMP2:%.*]] +; IS__CGSCC_NPM: 1: +; IS__CGSCC_NPM-NEXT: unreachable +; IS__CGSCC_NPM: 2: +; IS__CGSCC_NPM-NEXT: ret i8* @a1 ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 @@ -186,20 +188,6 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 { -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; CHECK-LABEL: define {{[^@]+}}@f2() local_unnamed_addr -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null -; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]] -; CHECK: 2: -; CHECK-NEXT: [[TMP3:%.*]] = tail call i8* @f1(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) -; CHECK-NEXT: br label [[TMP6:%.*]] -; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = tail call i8* @f3() -; CHECK-NEXT: br label [[TMP6]] -; CHECK: 6: -; CHECK-NEXT: [[TMP7:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ] -; CHECK-NEXT: ret i8* [[TMP7]] -; %2 = icmp eq i8* %0, null br i1 %2, label %5, label %3 @@ -219,17 +207,6 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 { -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; CHECK-LABEL: define {{[^@]+}}@f3() local_unnamed_addr -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null -; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] -; CHECK: 2: -; CHECK-NEXT: [[TMP3:%.*]] = tail call i8* @f1(i8* noalias nofree noundef nonnull readnone align 16 dereferenceable(1) "no-capture-maybe-returned" @a2) -; CHECK-NEXT: br label [[TMP4]] -; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ @a1, [[TMP0:%.*]] ] -; CHECK-NEXT: ret i8* [[TMP5]] -; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 @@ -245,15 +222,20 @@ ; TEST 7 ; Better than IR information define align 4 i8* @test7() #0 { -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7() ; IS__TUNIT____-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) ; IS__TUNIT____-NEXT: ret i8* [[C]] ; -; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____-LABEL: define {{[^@]+}}@test7() -; IS__CGSCC____-NEXT: [[C:%.*]] = tail call nonnull align 8 dereferenceable(1) i8* @f1(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) @a1) -; IS__CGSCC____-NEXT: ret i8* [[C]] +; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test7() +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) @a1) +; IS__CGSCC_OPM-NEXT: ret i8* [[C]] +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test7() +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = tail call nonnull align 8 dereferenceable(1) i8* @f1() +; IS__CGSCC_NPM-NEXT: ret i8* [[C]] ; %c = tail call i8* @f1(i8* align 8 dereferenceable(1) @a1) ret i8* %c @@ -262,33 +244,22 @@ ; TEST 7b ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind uwtable -; IS__TUNIT____-LABEL: define {{[^@]+}}@f1b -; IS__TUNIT____-SAME: (i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null -; IS__TUNIT____-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] -; IS__TUNIT____: 3: -; IS__TUNIT____-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b() -; IS__TUNIT____-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8 -; IS__TUNIT____-NEXT: store i8 [[L]], i8* @a1, align 8 -; IS__TUNIT____-NEXT: br label [[TMP5]] -; IS__TUNIT____: 5: -; IS__TUNIT____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] -; IS__TUNIT____-NEXT: ret i8* [[TMP6]] -; -; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind uwtable -; IS__CGSCC____-LABEL: define {{[^@]+}}@f1b -; IS__CGSCC____-SAME: (i8* nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null -; IS__CGSCC____-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] -; IS__CGSCC____: 3: -; IS__CGSCC____-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b() -; IS__CGSCC____-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8 -; IS__CGSCC____-NEXT: store i8 [[L]], i8* @a1, align 8 -; IS__CGSCC____-NEXT: br label [[TMP5]] -; IS__CGSCC____: 5: -; IS__CGSCC____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] -; IS__CGSCC____-NEXT: ret i8* [[TMP6]] +; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f1b +; IS__CGSCC_OPM-SAME: (i8* nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC_OPM-NEXT: br label [[TMP3:%.*]] +; IS__CGSCC_OPM: 2: +; IS__CGSCC_OPM-NEXT: unreachable +; IS__CGSCC_OPM: 3: +; IS__CGSCC_OPM-NEXT: ret i8* [[TMP0]] +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f1b() local_unnamed_addr +; IS__CGSCC_NPM-NEXT: br label [[TMP2:%.*]] +; IS__CGSCC_NPM: 1: +; IS__CGSCC_NPM-NEXT: unreachable +; IS__CGSCC_NPM: 2: +; IS__CGSCC_NPM-NEXT: ret i8* undef ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 @@ -306,20 +277,6 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 { -; -; CHECK: Function Attrs: nofree noinline nosync nounwind uwtable -; CHECK-LABEL: define {{[^@]+}}@f2b() local_unnamed_addr -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null -; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]] -; CHECK: 2: -; CHECK-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) -; CHECK-NEXT: br label [[TMP6:%.*]] -; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = tail call i8* @f3b() -; CHECK-NEXT: br label [[TMP6]] -; CHECK: 6: -; CHECK-NEXT: [[TMP7:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ] -; CHECK-NEXT: ret i8* [[TMP7]] ; %2 = icmp eq i8* %0, null br i1 %2, label %5, label %3 @@ -340,17 +297,6 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 { -; -; CHECK: Function Attrs: nofree noinline nosync nounwind uwtable -; CHECK-LABEL: define {{[^@]+}}@f3b() local_unnamed_addr -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null -; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] -; CHECK: 2: -; CHECK-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree noundef nonnull readnone align 16 dereferenceable(1) "no-capture-maybe-returned" @a2) -; CHECK-NEXT: br label [[TMP4]] -; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ @a1, [[TMP0:%.*]] ] -; CHECK-NEXT: ret i8* [[TMP5]] ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 @@ -365,16 +311,14 @@ } define align 4 i32* @test7b(i32* align 32 %p) #0 { -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind uwtable +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7b ; IS__TUNIT____-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = tail call i8* @f1b(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) ; IS__TUNIT____-NEXT: ret i32* [[P]] ; -; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind uwtable +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test7b ; IS__CGSCC____-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = tail call i8* @f1b(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) @a1) ; IS__CGSCC____-NEXT: ret i32* [[P]] ; tail call i8* @f1b(i8* align 8 dereferenceable(1) @a1) diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll --- a/llvm/test/Transforms/Attributor/nocapture-1.ll +++ b/llvm/test/Transforms/Attributor/nocapture-1.ll @@ -672,18 +672,12 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmp ; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[X:%.*]]) -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* -; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp eq i8* [[TMP2]], null -; IS__TUNIT____-NEXT: ret i1 [[TMP3]] +; IS__TUNIT____-NEXT: ret i1 false ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmp ; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[X:%.*]]) -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp eq i8* [[TMP2]], null -; IS__CGSCC____-NEXT: ret i1 [[TMP3]] +; IS__CGSCC____-NEXT: ret i1 false ; %1 = getelementptr inbounds i32, i32* %x, i32 5 %2 = bitcast i32* %1 to i8* @@ -695,22 +689,16 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmpRev ; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[X:%.*]]) -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* -; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp eq i8* null, [[TMP2]] -; IS__TUNIT____-NEXT: ret i1 [[TMP3]] +; IS__TUNIT____-NEXT: ret i1 true ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmpRev ; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[X:%.*]]) -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp eq i8* null, [[TMP2]] -; IS__CGSCC____-NEXT: ret i1 [[TMP3]] +; IS__CGSCC____-NEXT: ret i1 true ; %1 = getelementptr inbounds i32, i32* %x, i32 5 %2 = bitcast i32* %1 to i8* - %3 = icmp eq i8* null, %2 + %3 = icmp ne i8* null, %2 ret i1 %3 } diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll --- a/llvm/test/Transforms/Attributor/nonnull.ll +++ b/llvm/test/Transforms/Attributor/nonnull.ll @@ -801,8 +801,7 @@ ; CHECK-NEXT: invoke void @use2nonnull(i8* nonnull [[A]], i8* nonnull [[B]]) ; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] ; CHECK: cont: -; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[B]], null -; CHECK-NEXT: ret i1 [[NULL_CHECK]] +; CHECK-NEXT: ret i1 false ; CHECK: exc: ; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: filter [0 x i8*] zeroinitializer