[Attributor] Simplify comparison against constant null pointer

Comparison against null is a common pattern that usually is followed by
error handling code and the likes. We now use AANonNull to simplify
these comparisons optimistically in order to make more code dead early
on.

Reviewed By: uenoku

Differential Revision: https://reviews.llvm.org/D86145
This commit is contained in:
Johannes Doerfert 2020-08-18 10:03:25 -05:00
parent d01ad217ba
commit 3edea15f9a
4 changed files with 123 additions and 126 deletions

View File

@ -4705,10 +4705,76 @@ struct AAValueSimplifyFloating : AAValueSimplifyImpl {
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<ConstantPointerNull>(ICmp->getOperand(0));
bool Op1IsNull = isa<ConstantPointerNull>(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<AANonNull>(
*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<ICmpInst>(&getAnchorValue()),
Changed))
return Changed;
auto VisitValueCB = [&](Value &V, const Instruction *CtxI, bool &,
bool Stripped) -> bool {
auto &AA = A.getAAFor<AAValueSimplify>(*this, IRPosition::value(V));

View File

@ -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 @@ define i32* @test6_2() #0 {
; 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__TUNIT____-NEXT: ret i8* [[TMP0]]
;
; 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__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 @@ define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 {
; 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 @@ define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
; 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 @@ define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 {
; 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 @@ define align 4 i8* @test7() #0 {
; 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_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____: 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_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 @@ define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 {
; 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 @@ define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 {
; 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 internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 {
}
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)

View File

@ -672,18 +672,12 @@ define i1 @nocaptureInboundsGEPICmp(i32* %x) {
; 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 @@ define i1 @nocaptureInboundsGEPICmpRev(i32* %x) {
; 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
}

View File

@ -801,8 +801,7 @@ define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (..
; 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