mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 05:36:06 +00:00
[IR] Look through bitcast in hasFnAttribute()
A logic incompleteness may lead MemorySSA to be too conservative in its results. Specifically, when dealing with a call of kind `call i32 bitcast (i1 (i1)* @test to i32 (i32)*)(i32 %1)`, where the function `test` is declared with readonly attribute, the bitcast is not looked through, obscuring function attributes. Hence, some methods of CallBase (e.g., doesNotReadMemory) could provide suboptimal results. Differential Revision: https://reviews.llvm.org/D109888
This commit is contained in:
parent
248342b7c7
commit
43d6991c2a
@ -349,14 +349,26 @@ bool CallBase::paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
|
||||
}
|
||||
|
||||
bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const {
|
||||
if (const Function *F = getCalledFunction())
|
||||
Value *V = getCalledOperand();
|
||||
if (auto *CE = dyn_cast<ConstantExpr>(V))
|
||||
if (CE->getOpcode() == BitCast)
|
||||
V = CE->getOperand(0);
|
||||
|
||||
if (auto *F = dyn_cast<Function>(V))
|
||||
return F->getAttributes().hasFnAttr(Kind);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CallBase::hasFnAttrOnCalledFunction(StringRef Kind) const {
|
||||
if (const Function *F = getCalledFunction())
|
||||
Value *V = getCalledOperand();
|
||||
if (auto *CE = dyn_cast<ConstantExpr>(V))
|
||||
if (CE->getOpcode() == BitCast)
|
||||
V = CE->getOperand(0);
|
||||
|
||||
if (auto *F = dyn_cast<Function>(V))
|
||||
return F->getAttributes().hasFnAttr(Kind);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
14
llvm/test/Analysis/MemorySSA/call-bitcast.ll
Normal file
14
llvm/test/Analysis/MemorySSA/call-bitcast.ll
Normal file
@ -0,0 +1,14 @@
|
||||
; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -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
|
||||
}
|
@ -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 @@ define internal i16 @bar(i16 %p1, i16 %p2) {
|
||||
; 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 @@ define internal i16 @bar2(i16 %p1, i16 %p2) {
|
||||
; 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 @@ define internal i16 @bar2(i16 %p1, i16 %p2) {
|
||||
; 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 dso_local i16 @vararg_tests(i16 %a) {
|
||||
}
|
||||
|
||||
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 @@ define internal i16 @vararg_no_prop(i16 %p1, i16 %p2, ...) {
|
||||
; 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 @@ define internal i16 @vararg_no_prop(i16 %p1, i16 %p2, ...) {
|
||||
;.
|
||||
; 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 }
|
||||
;.
|
||||
|
@ -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 @@ define internal i16 @bar(i16 %p1, i16 %p2) {
|
||||
; 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 @@ define internal i16 @bar(i16 %p1, i16 %p2) {
|
||||
;.
|
||||
; 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 }
|
||||
;.
|
||||
|
@ -2473,33 +2473,59 @@ indirectgoto: ; preds = %lab0, %entry
|
||||
@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
|
||||
|
Loading…
x
Reference in New Issue
Block a user