Index: llvm/lib/IR/Instructions.cpp =================================================================== --- llvm/lib/IR/Instructions.cpp +++ llvm/lib/IR/Instructions.cpp @@ -349,14 +349,26 @@ } bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const { - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasFnAttr(Kind); + Value *V = getCalledOperand(); + if (auto *CE = dyn_cast(V)) + if (CE->getOpcode() == BitCast) + V = CE->getOperand(0); + + if (isa(V)) + return cast(V)->getAttributes().hasFnAttr(Kind); + return false; } bool CallBase::hasFnAttrOnCalledFunction(StringRef Kind) const { - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasFnAttr(Kind); + Value *V = getCalledOperand(); + if (auto *CE = dyn_cast(V)) + if (CE->getOpcode() == BitCast) + V = CE->getOperand(0); + + if (isa(V)) + return cast(V)->getAttributes().hasFnAttr(Kind); + return false; } Index: llvm/test/Analysis/MemorySSA/call-bitcast.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/MemorySSA/call-bitcast.ll @@ -0,0 +1,14 @@ +; RUN: opt -aa-pipeline=basic-aa -passes='print,verify' -disable-output < %s 2>&1 | FileCheck %s +; +; Ensures that MemorySSA leverages the ground truth of the function being called when wrapped in a bitcast. + +declare i1 @opaque_true(i1) nounwind readonly + +define i1 @foo(i32* %ptr, i1 %cond) { + %cond_wide = zext i1 %cond to i32 +; CHECK: MemoryUse(liveOnEntry) MayAlias +; CHECK-NEXT: call i32 bitcast + %cond_hidden_wide = call i32 bitcast (i1 (i1)* @opaque_true to i32 (i32)*)(i32 %cond_wide) + %cond_hidden = trunc i32 %cond_hidden_wide to i1 + ret i1 %cond_hidden +} Index: llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll =================================================================== --- llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll +++ llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll @@ -36,10 +36,16 @@ ; FIXME we should recognize this as UB and make it an unreachable. define dso_local i16 @foo(i16 %a) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i16 [[A:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16)*)(i16 [[A]]) -; CHECK-NEXT: ret i16 [[CALL]] +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; NOT_CGSCC_NPM-SAME: (i16 [[A:%.*]]) { +; NOT_CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16)*)(i16 [[A]]) +; NOT_CGSCC_NPM-NEXT: ret i16 [[CALL]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; IS__CGSCC_NPM-SAME: (i16 [[A:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16)*)(i16 [[A]]) +; IS__CGSCC_NPM-NEXT: ret i16 [[CALL]] ; %call = call i16 bitcast (i16 (i16, i16) * @bar to i16 (i16) *)(i16 %a) ret i16 %call @@ -51,19 +57,30 @@ ; IS__TUNIT____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT____-NEXT: ret i16 0 ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@bar -; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR0:[0-9]+]] { -; IS__CGSCC____-NEXT: ret i16 0 +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC_OPM-NEXT: ret i16 0 +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_NPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR1:[0-9]+]] { +; IS__CGSCC_NPM-NEXT: ret i16 0 ; ret i16 0 } define dso_local i16 @foo2(i16 %a) { -; CHECK-LABEL: define {{[^@]+}}@foo2 -; CHECK-SAME: (i16 [[A:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar2 to i16 (i16)*)(i16 [[A]]) -; CHECK-NEXT: ret i16 [[CALL]] +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@foo2 +; NOT_CGSCC_NPM-SAME: (i16 [[A:%.*]]) { +; NOT_CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar2 to i16 (i16)*)(i16 [[A]]) +; NOT_CGSCC_NPM-NEXT: ret i16 [[CALL]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo2 +; IS__CGSCC_NPM-SAME: (i16 [[A:%.*]]) #[[ATTR0]] { +; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar2 to i16 (i16)*)(i16 [[A]]) +; IS__CGSCC_NPM-NEXT: ret i16 [[CALL]] ; %call = call i16 bitcast (i16 (i16, i16) * @bar2 to i16 (i16) *)(i16 %a) ret i16 %call @@ -76,11 +93,17 @@ ; IS__TUNIT____-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] ; IS__TUNIT____-NEXT: ret i16 [[A]] ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@bar2 -; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] -; IS__CGSCC____-NEXT: ret i16 [[A]] +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar2 +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR0]] { +; IS__CGSCC_OPM-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] +; IS__CGSCC_OPM-NEXT: ret i16 [[A]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@bar2 +; IS__CGSCC_NPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] +; IS__CGSCC_NPM-NEXT: ret i16 [[A]] ; %a = add i16 %p1, %p2 ret i16 %a @@ -93,11 +116,18 @@ ; been provided), define dso_local i16 @vararg_tests(i16 %a) { -; CHECK-LABEL: define {{[^@]+}}@vararg_tests -; CHECK-SAME: (i16 [[A:%.*]]) { -; CHECK-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 noundef 7) -; CHECK-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] -; CHECK-NEXT: ret i16 [[ADD]] +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@vararg_tests +; NOT_CGSCC_NPM-SAME: (i16 [[A:%.*]]) { +; NOT_CGSCC_NPM-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 noundef 7) +; NOT_CGSCC_NPM-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] +; NOT_CGSCC_NPM-NEXT: ret i16 [[ADD]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@vararg_tests +; IS__CGSCC_NPM-SAME: (i16 [[A:%.*]]) #[[ATTR0]] { +; IS__CGSCC_NPM-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 noundef 7) +; IS__CGSCC_NPM-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] +; IS__CGSCC_NPM-NEXT: ret i16 [[ADD]] ; %call1 = call i16 (i16, ...) @vararg_prop(i16 7, i16 8, i16 %a) %call2 = call i16 bitcast (i16 (i16, i16, ...) * @vararg_no_prop to i16 (i16) *) (i16 7) @@ -106,10 +136,15 @@ } define internal i16 @vararg_prop(i16 %p1, ...) { -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_prop -; IS__CGSCC____-SAME: (i16 [[P1:%.*]], ...) #[[ATTR0]] { -; IS__CGSCC____-NEXT: ret i16 undef +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vararg_prop +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], ...) #[[ATTR0]] { +; IS__CGSCC_OPM-NEXT: ret i16 undef +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@vararg_prop +; IS__CGSCC_NPM-SAME: (i16 [[P1:%.*]], ...) #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: ret i16 undef ; ret i16 %p1 } @@ -120,10 +155,15 @@ ; IS__TUNIT____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { ; IS__TUNIT____-NEXT: ret i16 7 ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_no_prop -; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { -; IS__CGSCC____-NEXT: ret i16 7 +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vararg_no_prop +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { +; IS__CGSCC_OPM-NEXT: ret i16 7 +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@vararg_no_prop +; IS__CGSCC_NPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: ret i16 7 ; ret i16 %p1 } @@ -131,5 +171,8 @@ ;. ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn } ;. -; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } +;. +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } ;. Index: llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll =================================================================== --- llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll +++ llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll @@ -8,10 +8,16 @@ ; argument type between the caller and callee. define dso_local i16 @foo(i16 %a) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i16 [[A:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16, i32)*)(i16 [[A]], i32 7) -; CHECK-NEXT: ret i16 [[CALL]] +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; NOT_CGSCC_NPM-SAME: (i16 [[A:%.*]]) { +; NOT_CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16, i32)*)(i16 [[A]], i32 7) +; NOT_CGSCC_NPM-NEXT: ret i16 [[CALL]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; IS__CGSCC_NPM-SAME: (i16 [[A:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16, i32)*)(i16 [[A]], i32 7) +; IS__CGSCC_NPM-NEXT: ret i16 [[CALL]] ; %call = call i16 bitcast (i16 (i16, i16) * @bar to i16 (i16, i32) *)(i16 %a, i32 7) ret i16 %call @@ -23,10 +29,15 @@ ; IS__TUNIT____-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT____-NEXT: ret i16 [[P2]] ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@bar -; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) #[[ATTR0:[0-9]+]] { -; IS__CGSCC____-NEXT: ret i16 [[P2]] +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC_OPM-NEXT: ret i16 [[P2]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_NPM-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) #[[ATTR1:[0-9]+]] { +; IS__CGSCC_NPM-NEXT: ret i16 [[P2]] ; ret i16 %p2 } @@ -35,5 +46,8 @@ ;. ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn } ;. -; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } +;. +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } ;. Index: llvm/test/Transforms/Attributor/liveness.ll =================================================================== --- llvm/test/Transforms/Attributor/liveness.ll +++ llvm/test/Transforms/Attributor/liveness.ll @@ -2473,33 +2473,59 @@ @e = global %struct.a* null define i32 @main() { -; CHECK-LABEL: define {{[^@]+}}@main() { -; CHECK-NEXT: entry: -; CHECK-NEXT: [[F:%.*]] = alloca i32, align 4 -; CHECK-NEXT: br label [[FOR_COND_0:%.*]] -; CHECK: for.cond.0: -; CHECK-NEXT: [[G_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_0:%.*]] ] -; CHECK-NEXT: [[CMP_0:%.*]] = icmp ult i32 [[G_0]], 100 -; CHECK-NEXT: br i1 [[CMP_0]], label [[FOR_BODY_0]], label [[FOR_END_0:%.*]] -; CHECK: for.body.0: -; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[G_0]], 1 -; CHECK-NEXT: br label [[FOR_COND_0]] -; CHECK: for.end.0: -; CHECK-NEXT: [[CALL:%.*]] = call i8* @malloc(i64 noundef 8) -; CHECK-NEXT: store i8* [[CALL]], i8** bitcast (%struct.a** @e to i8**), align 8 -; CHECK-NEXT: [[B:%.*]] = bitcast i8* [[CALL]] to %struct.a** -; CHECK-NEXT: store %struct.a* null, %struct.a** [[B]], align 8 -; CHECK-NEXT: br label [[FOR_COND_1:%.*]] -; CHECK: for.cond.1: -; CHECK-NEXT: [[G_1:%.*]] = phi i32 [ 0, [[FOR_END_0]] ], [ [[INC6:%.*]], [[FOR_BODY_1:%.*]] ] -; CHECK-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[G_1]], 100 -; CHECK-NEXT: br i1 [[CMP_1]], label [[FOR_BODY_1]], label [[FOR_END_1:%.*]] -; CHECK: for.body.1: -; CHECK-NEXT: [[CALL4:%.*]] = call i32 (i32*, ...) bitcast (i32 (i32)* @h to i32 (i32*, ...)*)(i32* nonnull [[F]]) -; CHECK-NEXT: [[INC6]] = add nuw nsw i32 [[G_1]], 1 -; CHECK-NEXT: br label [[FOR_COND_1]] -; CHECK: for.end.1: -; CHECK-NEXT: ret i32 0 +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@main() { +; NOT_CGSCC_NPM-NEXT: entry: +; NOT_CGSCC_NPM-NEXT: [[F:%.*]] = alloca i32, align 4 +; NOT_CGSCC_NPM-NEXT: br label [[FOR_COND_0:%.*]] +; NOT_CGSCC_NPM: for.cond.0: +; NOT_CGSCC_NPM-NEXT: [[G_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_0:%.*]] ] +; NOT_CGSCC_NPM-NEXT: [[CMP_0:%.*]] = icmp ult i32 [[G_0]], 100 +; NOT_CGSCC_NPM-NEXT: br i1 [[CMP_0]], label [[FOR_BODY_0]], label [[FOR_END_0:%.*]] +; NOT_CGSCC_NPM: for.body.0: +; NOT_CGSCC_NPM-NEXT: [[INC]] = add nuw nsw i32 [[G_0]], 1 +; NOT_CGSCC_NPM-NEXT: br label [[FOR_COND_0]] +; NOT_CGSCC_NPM: for.end.0: +; NOT_CGSCC_NPM-NEXT: [[CALL:%.*]] = call i8* @malloc(i64 noundef 8) +; NOT_CGSCC_NPM-NEXT: store i8* [[CALL]], i8** bitcast (%struct.a** @e to i8**), align 8 +; NOT_CGSCC_NPM-NEXT: [[B:%.*]] = bitcast i8* [[CALL]] to %struct.a** +; NOT_CGSCC_NPM-NEXT: store %struct.a* null, %struct.a** [[B]], align 8 +; NOT_CGSCC_NPM-NEXT: br label [[FOR_COND_1:%.*]] +; NOT_CGSCC_NPM: for.cond.1: +; NOT_CGSCC_NPM-NEXT: [[G_1:%.*]] = phi i32 [ 0, [[FOR_END_0]] ], [ [[INC6:%.*]], [[FOR_BODY_1:%.*]] ] +; NOT_CGSCC_NPM-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[G_1]], 100 +; NOT_CGSCC_NPM-NEXT: br i1 [[CMP_1]], label [[FOR_BODY_1]], label [[FOR_END_1:%.*]] +; NOT_CGSCC_NPM: for.body.1: +; NOT_CGSCC_NPM-NEXT: [[CALL4:%.*]] = call i32 (i32*, ...) bitcast (i32 (i32)* @h to i32 (i32*, ...)*)(i32* nonnull [[F]]) +; NOT_CGSCC_NPM-NEXT: [[INC6]] = add nuw nsw i32 [[G_1]], 1 +; NOT_CGSCC_NPM-NEXT: br label [[FOR_COND_1]] +; NOT_CGSCC_NPM: for.end.1: +; NOT_CGSCC_NPM-NEXT: ret i32 0 +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@main() { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[FOR_COND_0:%.*]] +; IS__CGSCC____: for.cond.0: +; IS__CGSCC____-NEXT: [[G_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_0:%.*]] ] +; IS__CGSCC____-NEXT: [[CMP_0:%.*]] = icmp ult i32 [[G_0]], 100 +; IS__CGSCC____-NEXT: br i1 [[CMP_0]], label [[FOR_BODY_0]], label [[FOR_END_0:%.*]] +; IS__CGSCC____: for.body.0: +; IS__CGSCC____-NEXT: [[INC]] = add nuw nsw i32 [[G_0]], 1 +; IS__CGSCC____-NEXT: br label [[FOR_COND_0]] +; IS__CGSCC____: for.end.0: +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i8* @malloc(i64 noundef 8) +; IS__CGSCC____-NEXT: store i8* [[CALL]], i8** bitcast (%struct.a** @e to i8**), align 8 +; IS__CGSCC____-NEXT: [[B:%.*]] = bitcast i8* [[CALL]] to %struct.a** +; IS__CGSCC____-NEXT: store %struct.a* null, %struct.a** [[B]], align 8 +; IS__CGSCC____-NEXT: br label [[FOR_COND_1:%.*]] +; IS__CGSCC____: for.cond.1: +; IS__CGSCC____-NEXT: [[G_1:%.*]] = phi i32 [ 0, [[FOR_END_0]] ], [ [[INC6:%.*]], [[FOR_BODY_1:%.*]] ] +; IS__CGSCC____-NEXT: [[CMP_1:%.*]] = icmp ult i32 [[G_1]], 100 +; IS__CGSCC____-NEXT: br i1 [[CMP_1]], label [[FOR_BODY_1]], label [[FOR_END_1:%.*]] +; IS__CGSCC____: for.body.1: +; IS__CGSCC____-NEXT: [[INC6]] = add nuw nsw i32 [[G_1]], 1 +; IS__CGSCC____-NEXT: br label [[FOR_COND_1]] +; IS__CGSCC____: for.end.1: +; IS__CGSCC____-NEXT: ret i32 0 ; entry: %f = alloca i32