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 @@ -1983,6 +1983,61 @@ 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(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(*this, CalleeArgumentIRP); + if (!NonNullAA.isKnownNonNull()) + continue; + const auto &ValueSimplifyAA = + A.getAAFor(*this, IRPosition::value(*ArgVal)); + Optional 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(*SimplifiedVal.getValue()) || + isa(*SimplifiedVal.getValue())) { + KnownUBInsts.insert(&I); + return true; + } + } + return true; + }; + A.checkForAllInstructions(InspectMemAccessInstForUB, *this, {Instruction::Load, Instruction::Store, Instruction::AtomicCmpXchg, @@ -1990,6 +2045,7 @@ /* CheckBBLivenessOnly */ true); A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br}, /* CheckBBLivenessOnly */ true); + A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this); if (NoUBPrevSize != AssumedNoUBInsts.size() || UBPrevSize != KnownUBInsts.size()) return ChangeStatus::CHANGED; diff --git a/llvm/test/Transforms/Attributor/undefined_behavior.ll b/llvm/test/Transforms/Attributor/undefined_behavior.ll --- a/llvm/test/Transforms/Attributor/undefined_behavior.ll +++ b/llvm/test/Transforms/Attributor/undefined_behavior.ll @@ -579,3 +579,298 @@ %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 +}