[llvm] 43d6991 - [IR] Look through bitcast in hasFnAttribute()

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 21 12:57:10 PDT 2021


Author: Antonio Frighetto
Date: 2021-09-21T21:57:02+02:00
New Revision: 43d6991c2a4cc2ac374e68c029634f2b59ffdfdf

URL: https://github.com/llvm/llvm-project/commit/43d6991c2a4cc2ac374e68c029634f2b59ffdfdf
DIFF: https://github.com/llvm/llvm-project/commit/43d6991c2a4cc2ac374e68c029634f2b59ffdfdf.diff

LOG: [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

Added: 
    llvm/test/Analysis/MemorySSA/call-bitcast.ll

Modified: 
    llvm/lib/IR/Instructions.cpp
    llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll
    llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll
    llvm/test/Transforms/Attributor/liveness.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 2ca68212fa109..60e311549c1ab 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -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;
 }
 

diff  --git a/llvm/test/Analysis/MemorySSA/call-bitcast.ll b/llvm/test/Analysis/MemorySSA/call-bitcast.ll
new file mode 100644
index 0000000000000..c4bfdbee77ad5
--- /dev/null
+++ b/llvm/test/Analysis/MemorySSA/call-bitcast.ll
@@ -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
+}

diff  --git a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll
index 485cf2865fe6c..ff040b5e5c407 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll
+++ b/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 @@ 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 }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll b/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll
index 3bbd2534c4397..80cf75fc1a37f 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll
+++ b/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 @@ 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 }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll
index faf82079cc49e..393000bacd537 100644
--- a/llvm/test/Transforms/Attributor/liveness.ll
+++ b/llvm/test/Transforms/Attributor/liveness.ll
@@ -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


        


More information about the llvm-commits mailing list