forked from OSchip/llvm-project
[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:
parent
d01ad217ba
commit
3edea15f9a
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue