[Attributor] Check nonnull attribute violation in AAUndefinedBehavior

This patch makes it possible to handle nonnull attribute violation at callsites in AAUndefinedBehavior.
If null pointer is passed to callee at a callsite and the corresponding argument of callee has nonnull attribute, the behavior of the callee is undefined.
In this patch, violations of argument nonnull attributes is only handled.
But violations of returned nonnull attributes can be handled and I will implement that in a follow-up patch.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D84733
This commit is contained in:
Shinji Okumura 2020-08-03 17:02:49 +09:00
parent 414b9bec6d
commit 434cf2ded3
2 changed files with 351 additions and 0 deletions

View file

@ -1983,6 +1983,61 @@ struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
return true;
};
auto InspectCallSiteForUB = [&](Instruction &I) {
// Check whether a callsite always cause UB or not
// Skip instructions that are already saved.
if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
return true;
// Check nonnull and noundef argument attribute violation for each
// callsite.
CallBase &CB = cast<CallBase>(I);
Function *Callee = CB.getCalledFunction();
if (!Callee)
return true;
for (unsigned idx = 0; idx < CB.getNumArgOperands(); idx++) {
// If current argument is known to be simplified to null pointer and the
// corresponding argument position is known to have nonnull attribute,
// the argument is poison. Furthermore, if the argument is poison and
// the position is known to have noundef attriubte, this callsite is
// considered UB.
// TODO: Check also nopoison attribute if it is introduced.
if (idx >= Callee->arg_size())
break;
Value *ArgVal = CB.getArgOperand(idx);
if(!ArgVal)
continue;
IRPosition CalleeArgumentIRP =
IRPosition::argument(*Callee->getArg(idx));
if (!CalleeArgumentIRP.hasAttr({Attribute::NoUndef}))
continue;
auto &NonNullAA = A.getAAFor<AANonNull>(*this, CalleeArgumentIRP);
if (!NonNullAA.isKnownNonNull())
continue;
const auto &ValueSimplifyAA =
A.getAAFor<AAValueSimplify>(*this, IRPosition::value(*ArgVal));
Optional<Value *> SimplifiedVal =
ValueSimplifyAA.getAssumedSimplifiedValue(A);
if (!ValueSimplifyAA.isKnown())
continue;
// Here, we handle three cases.
// (1) Not having a value means it is dead. (we can replace the value
// with undef)
// (2) Simplified to null pointer. The argument is a poison value and
// violate noundef attribute.
// (3) Simplified to undef. The argument violate noundef attriubte.
if (!SimplifiedVal.hasValue() ||
isa<ConstantPointerNull>(*SimplifiedVal.getValue()) ||
isa<UndefValue>(*SimplifiedVal.getValue())) {
KnownUBInsts.insert(&I);
return true;
}
}
return true;
};
A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
{Instruction::Load, Instruction::Store,
Instruction::AtomicCmpXchg,
@ -1990,6 +2045,7 @@ struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
/* CheckBBLivenessOnly */ true);
A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br},
/* CheckBBLivenessOnly */ true);
A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this);
if (NoUBPrevSize != AssumedNoUBInsts.size() ||
UBPrevSize != KnownUBInsts.size())
return ChangeStatus::CHANGED;

View file

@ -579,3 +579,298 @@ define i32 @foo() {
%X = call i32 @callee(i1 false, i32* null)
ret i32 %X
}
; Tests for nonnull attribute violation.
define void @arg_nonnull_1(i32* nonnull %a) {
; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_1
; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A:%.*]])
; IS__TUNIT____-NEXT: store i32 0, i32* [[A]], align 4
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_1
; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A:%.*]])
; IS__CGSCC____-NEXT: store i32 0, i32* [[A]], align 4
; IS__CGSCC____-NEXT: ret void
;
store i32 0, i32* %a
ret void
}
define void @arg_nonnull_1_noundef_1(i32* nonnull noundef %a) {
; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_1_noundef_1
; IS__TUNIT____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]])
; IS__TUNIT____-NEXT: store i32 0, i32* [[A]], align 4
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_1_noundef_1
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]])
; IS__CGSCC____-NEXT: store i32 0, i32* [[A]], align 4
; IS__CGSCC____-NEXT: ret void
;
store i32 0, i32* %a
ret void
}
define void @arg_nonnull_12(i32* nonnull %a, i32* nonnull %b, i32* %c) {
; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_12
; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]])
; IS__TUNIT____-NEXT: [[D:%.*]] = icmp eq i32* [[C]], null
; IS__TUNIT____-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____: t:
; IS__TUNIT____-NEXT: store i32 0, i32* [[A]], align 4
; IS__TUNIT____-NEXT: br label [[RET:%.*]]
; IS__TUNIT____: f:
; IS__TUNIT____-NEXT: store i32 1, i32* [[B]], align 4
; IS__TUNIT____-NEXT: br label [[RET]]
; IS__TUNIT____: ret:
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_12
; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]])
; IS__CGSCC____-NEXT: [[D:%.*]] = icmp eq i32* [[C]], null
; IS__CGSCC____-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____: t:
; IS__CGSCC____-NEXT: store i32 0, i32* [[A]], align 4
; IS__CGSCC____-NEXT: br label [[RET:%.*]]
; IS__CGSCC____: f:
; IS__CGSCC____-NEXT: store i32 1, i32* [[B]], align 4
; IS__CGSCC____-NEXT: br label [[RET]]
; IS__CGSCC____: ret:
; IS__CGSCC____-NEXT: ret void
;
%d = icmp eq i32* %c, null
br i1 %d, label %t, label %f
t:
store i32 0, i32* %a
br label %ret
f:
store i32 1, i32* %b
br label %ret
ret:
ret void
}
define void @arg_nonnull_12_noundef_2(i32* nonnull %a, i32* noundef nonnull %b, i32* %c) {
; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_12_noundef_2
; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree noundef nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]])
; IS__TUNIT____-NEXT: [[D:%.*]] = icmp eq i32* [[C]], null
; IS__TUNIT____-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____: t:
; IS__TUNIT____-NEXT: store i32 0, i32* [[A]], align 4
; IS__TUNIT____-NEXT: br label [[RET:%.*]]
; IS__TUNIT____: f:
; IS__TUNIT____-NEXT: store i32 1, i32* [[B]], align 4
; IS__TUNIT____-NEXT: br label [[RET]]
; IS__TUNIT____: ret:
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_12_noundef_2
; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree noundef nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]])
; IS__CGSCC____-NEXT: [[D:%.*]] = icmp eq i32* [[C]], null
; IS__CGSCC____-NEXT: br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____: t:
; IS__CGSCC____-NEXT: store i32 0, i32* [[A]], align 4
; IS__CGSCC____-NEXT: br label [[RET:%.*]]
; IS__CGSCC____: f:
; IS__CGSCC____-NEXT: store i32 1, i32* [[B]], align 4
; IS__CGSCC____-NEXT: br label [[RET]]
; IS__CGSCC____: ret:
; IS__CGSCC____-NEXT: ret void
;
%d = icmp eq i32* %c, null
br i1 %d, label %t, label %f
t:
store i32 0, i32* %a
br label %ret
f:
store i32 1, i32* %b
br label %ret
ret:
ret void
}
; Pass null directly to argument with nonnull attribute
define void @arg_nonnull_violation1_1() {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation1_1()
; IS__TUNIT____-NEXT: call void @arg_nonnull_1(i32* noalias nocapture nofree nonnull writeonly align 536870912 null)
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation1_1()
; IS__CGSCC____-NEXT: call void @arg_nonnull_1(i32* noalias nocapture nofree nonnull writeonly align 536870912 dereferenceable(4) null)
; IS__CGSCC____-NEXT: ret void
;
call void @arg_nonnull_1(i32* null)
ret void
}
define void @arg_nonnull_violation1_2() {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation1_2()
; IS__TUNIT____-NEXT: unreachable
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation1_2()
; IS__CGSCC____-NEXT: unreachable
;
call void @arg_nonnull_1_noundef_1(i32* null)
ret void
}
; A case that depends on value simplification
define void @arg_nonnull_violation2_1(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation2_1
; IS__TUNIT____-SAME: (i1 [[C:%.*]])
; IS__TUNIT____-NEXT: call void @arg_nonnull_1(i32* nocapture nofree nonnull writeonly align 536870912 null)
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation2_1
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
; IS__CGSCC____-NEXT: call void @arg_nonnull_1(i32* nocapture nofree nonnull writeonly align 536870912 dereferenceable(4) null)
; IS__CGSCC____-NEXT: ret void
;
%null = getelementptr i32, i32* null, i32 0
%mustnull = select i1 %c, i32* null, i32* %null
call void @arg_nonnull_1(i32* %mustnull)
ret void
}
define void @arg_nonnull_violation2_2(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation2_2
; IS__TUNIT____-SAME: (i1 [[C:%.*]])
; IS__TUNIT____-NEXT: unreachable
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation2_2
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
; IS__CGSCC____-NEXT: unreachable
;
%null = getelementptr i32, i32* null, i32 0
%mustnull = select i1 %c, i32* null, i32* %null
call void @arg_nonnull_1_noundef_1(i32* %mustnull)
ret void
}
; Cases for single and multiple violation at a callsite
define void @arg_nonnull_violation3_1(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_1
; IS__TUNIT____-SAME: (i1 [[C:%.*]])
; IS__TUNIT____-NEXT: [[PTR:%.*]] = alloca i32, align 4
; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____: t:
; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__TUNIT____-NEXT: br label [[RET:%.*]]
; IS__TUNIT____: f:
; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__TUNIT____-NEXT: call void @arg_nonnull_12(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__TUNIT____-NEXT: br label [[RET]]
; IS__TUNIT____: ret:
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_1
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
; IS__CGSCC____-NEXT: [[PTR:%.*]] = alloca i32, align 4
; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____: t:
; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__CGSCC____-NEXT: br label [[RET:%.*]]
; IS__CGSCC____: f:
; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__CGSCC____-NEXT: call void @arg_nonnull_12(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__CGSCC____-NEXT: br label [[RET]]
; IS__CGSCC____: ret:
; IS__CGSCC____-NEXT: ret void
;
%ptr = alloca i32
br i1 %c, label %t, label %f
t:
call void @arg_nonnull_12(i32* %ptr, i32* %ptr, i32* %ptr)
call void @arg_nonnull_12(i32* %ptr, i32* %ptr, i32* null)
call void @arg_nonnull_12(i32* %ptr, i32* null, i32* %ptr)
call void @arg_nonnull_12(i32* %ptr, i32* null, i32* null)
br label %ret
f:
call void @arg_nonnull_12(i32* null, i32* %ptr, i32* %ptr)
call void @arg_nonnull_12(i32* null, i32* %ptr, i32* null)
call void @arg_nonnull_12(i32* null, i32* null, i32* %ptr)
call void @arg_nonnull_12(i32* null, i32* null, i32* null)
br label %ret
ret:
ret void
}
define void @arg_nonnull_violation3_2(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_2
; IS__TUNIT____-SAME: (i1 [[C:%.*]])
; IS__TUNIT____-NEXT: [[PTR:%.*]] = alloca i32, align 4
; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____: t:
; IS__TUNIT____-NEXT: call void @arg_nonnull_12_noundef_2(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__TUNIT____-NEXT: call void @arg_nonnull_12_noundef_2(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__TUNIT____-NEXT: unreachable
; IS__TUNIT____: f:
; IS__TUNIT____-NEXT: call void @arg_nonnull_12_noundef_2(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__TUNIT____-NEXT: call void @arg_nonnull_12_noundef_2(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__TUNIT____-NEXT: unreachable
; IS__TUNIT____: ret:
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_2
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
; IS__CGSCC____-NEXT: [[PTR:%.*]] = alloca i32, align 4
; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____: t:
; IS__CGSCC____-NEXT: call void @arg_nonnull_12_noundef_2(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__CGSCC____-NEXT: call void @arg_nonnull_12_noundef_2(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__CGSCC____-NEXT: unreachable
; IS__CGSCC____: f:
; IS__CGSCC____-NEXT: call void @arg_nonnull_12_noundef_2(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]])
; IS__CGSCC____-NEXT: call void @arg_nonnull_12_noundef_2(i32* noalias nocapture nofree nonnull writeonly align 536870912 null, i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree writeonly align 536870912 null)
; IS__CGSCC____-NEXT: unreachable
; IS__CGSCC____: ret:
; IS__CGSCC____-NEXT: ret void
;
%ptr = alloca i32
br i1 %c, label %t, label %f
t:
call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* %ptr, i32* %ptr)
call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* %ptr, i32* null)
call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* null, i32* %ptr)
call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* null, i32* null)
br label %ret
f:
call void @arg_nonnull_12_noundef_2(i32* null, i32* %ptr, i32* %ptr)
call void @arg_nonnull_12_noundef_2(i32* null, i32* %ptr, i32* null)
call void @arg_nonnull_12_noundef_2(i32* null, i32* null, i32* %ptr)
call void @arg_nonnull_12_noundef_2(i32* null, i32* null, i32* null)
br label %ret
ret:
ret void
}