[clang] 6c31295 - [clang] Refactor mustprogress handling, add it to all loops in c++11+.
Florian Hahn via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 30 06:24:11 PDT 2021
Author: Florian Hahn
Date: 2021-04-30T14:13:47+01:00
New Revision: 6c3129549374c0e81e28fd0a21e96f8087b63a78
URL: https://github.com/llvm/llvm-project/commit/6c3129549374c0e81e28fd0a21e96f8087b63a78
DIFF: https://github.com/llvm/llvm-project/commit/6c3129549374c0e81e28fd0a21e96f8087b63a78.diff
LOG: [clang] Refactor mustprogress handling, add it to all loops in c++11+.
Currently Clang does not add mustprogress to inifinite loops with a
known constant condition, matching C11 behavior. The forward progress
guarantee in C++11 and later should allow us to add mustprogress to any
loop (http://eel.is/c++draft/intro.progress#1).
This allows us to simplify the code dealing with adding mustprogress a
bit.
Reviewed By: aaron.ballman, lebedev.ri
Differential Revision: https://reviews.llvm.org/D96418
Added:
Modified:
clang/lib/CodeGen/CGStmt.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/test/CodeGen/attr-mustprogress.c
clang/test/CodeGenCXX/attr-mustprogress.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index b6f4f98fbd2ea..0fc0ba10e6674 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -816,20 +816,14 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
// while(1) is common, avoid extra exit blocks. Be sure
// to correctly handle break/continue though.
- bool EmitBoolCondBranch = true;
- bool LoopMustProgress = false;
- if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
- if (C->isOne()) {
- EmitBoolCondBranch = false;
- FnIsMustProgress = false;
- }
- } else if (LanguageRequiresProgress())
- LoopMustProgress = true;
-
+ llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
+ bool CondIsConstInt = C != nullptr;
+ bool EmitBoolCondBranch = !CondIsConstInt || !C->isOne();
const SourceRange &R = S.getSourceRange();
LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), CGM.getCodeGenOpts(),
WhileAttrs, SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
+ SourceLocToDebugLoc(R.getEnd()),
+ checkIfLoopMustProgress(CondIsConstInt));
// As long as the condition is true, go to the loop body.
llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
@@ -920,20 +914,15 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// "do {} while (0)" is common in macros, avoid extra blocks. Be sure
// to correctly handle break/continue though.
- bool EmitBoolCondBranch = true;
- bool LoopMustProgress = false;
- if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
- if (C->isZero())
- EmitBoolCondBranch = false;
- else if (C->isOne())
- FnIsMustProgress = false;
- } else if (LanguageRequiresProgress())
- LoopMustProgress = true;
+ llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
+ bool CondIsConstInt = C;
+ bool EmitBoolCondBranch = !C || !C->isZero();
const SourceRange &R = S.getSourceRange();
LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
+ SourceLocToDebugLoc(R.getEnd()),
+ checkIfLoopMustProgress(CondIsConstInt));
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch) {
@@ -971,20 +960,15 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
llvm::BasicBlock *CondBlock = CondDest.getBlock();
EmitBlock(CondBlock);
- bool LoopMustProgress = false;
Expr::EvalResult Result;
- if (LanguageRequiresProgress()) {
- if (!S.getCond()) {
- FnIsMustProgress = false;
- } else if (!S.getCond()->EvaluateAsInt(Result, getContext())) {
- LoopMustProgress = true;
- }
- }
+ bool CondIsConstInt =
+ !S.getCond() || S.getCond()->EvaluateAsInt(Result, getContext());
const SourceRange &R = S.getSourceRange();
LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs,
SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
+ SourceLocToDebugLoc(R.getEnd()),
+ checkIfLoopMustProgress(CondIsConstInt));
// Create a cleanup scope for the condition variable cleanups.
LexicalScope ConditionScope(*this, S.getSourceRange());
@@ -1033,10 +1017,6 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
BoolCondVal, Stmt::getLikelihood(S.getBody()));
- if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
- if (C->isOne())
- FnIsMustProgress = false;
-
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
if (ExitBlock != LoopExit.getBlock()) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 09d49c9aa0180..d1937fda92123 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1186,9 +1186,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
incrementProfileCounter(Body);
- if (CPlusPlusWithProgress())
- FnIsMustProgress = true;
-
if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
else
@@ -1196,7 +1193,7 @@ void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
// This is checked after emitting the function body so we know if there
// are any permitted infinite loops.
- if (FnIsMustProgress)
+ if (checkIfFunctionMustProgress())
CurFn->addFnAttr(llvm::Attribute::MustProgress);
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 7723382c9cb4f..325a246f94080 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -524,21 +524,28 @@ class CodeGenFunction : public CodeGenTypeCache {
// applies to. nullptr if there is no 'musttail' on the current statement.
const CallExpr *MustTailCall = nullptr;
- /// True if the current function should be marked mustprogress.
- bool FnIsMustProgress = false;
-
- /// True if the C++ Standard Requires Progress.
- bool CPlusPlusWithProgress() {
+ /// Returns true if a function must make progress, which means the
+ /// mustprogress attribute can be added.
+ bool checkIfFunctionMustProgress() {
if (CGM.getCodeGenOpts().getFiniteLoops() ==
CodeGenOptions::FiniteLoopsKind::Never)
return false;
- return getLangOpts().CPlusPlus11 || getLangOpts().CPlusPlus14 ||
- getLangOpts().CPlusPlus17 || getLangOpts().CPlusPlus20;
+ // C++11 and later guarantees that a thread eventually will do one of the
+ // following (6.9.2.3.1 in C++11):
+ // - terminate,
+ // - make a call to a library I/O function,
+ // - perform an access through a volatile glvalue, or
+ // - perform a synchronization operation or an atomic operation.
+ //
+ // Hence each function is 'mustprogress' in C++11 or later.
+ return getLangOpts().CPlusPlus11;
}
- /// True if the C Standard Requires Progress.
- bool CWithProgress() {
+ /// Returns true if a loop must make progress, which means the mustprogress
+ /// attribute can be added. \p HasConstantCond indicates whether the branch
+ /// condition is a known constant.
+ bool checkIfLoopMustProgress(bool HasConstantCond) {
if (CGM.getCodeGenOpts().getFiniteLoops() ==
CodeGenOptions::FiniteLoopsKind::Always)
return true;
@@ -546,13 +553,19 @@ class CodeGenFunction : public CodeGenTypeCache {
CodeGenOptions::FiniteLoopsKind::Never)
return false;
- return getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x;
- }
+ // If the containing function must make progress, loops also must make
+ // progress (as in C++11 and later).
+ if (checkIfFunctionMustProgress())
+ return true;
+
+ // Now apply rules for plain C (see 6.8.5.6 in C11).
+ // Loops with constant conditions do not have to make progress in any C
+ // version.
+ if (HasConstantCond)
+ return false;
- /// True if the language standard requires progress in functions or
- /// in infinite loops with non-constant conditionals.
- bool LanguageRequiresProgress() {
- return CWithProgress() || CPlusPlusWithProgress();
+ // Loops with non-constant conditions must make progress in C11 and later.
+ return getLangOpts().C11;
}
const CodeGen::CGBlockInfo *BlockInfo = nullptr;
diff --git a/clang/test/CodeGen/attr-mustprogress.c b/clang/test/CodeGen/attr-mustprogress.c
index ad5819db6541b..e690d2c209211 100644
--- a/clang/test/CodeGen/attr-mustprogress.c
+++ b/clang/test/CodeGen/attr-mustprogress.c
@@ -1,15 +1,18 @@
+// RUN: %clang_cc1 -std=c89 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s
// RUN: %clang_cc1 -std=c99 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s
// RUN: %clang_cc1 -std=c11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s
// RUN: %clang_cc1 -std=c18 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s
// RUN: %clang_cc1 -std=c2x -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s
//
// Check -ffinite-loops option in combination with various standard versions.
+// RUN: %clang_cc1 -std=c89 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s
// RUN: %clang_cc1 -std=c99 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s
// RUN: %clang_cc1 -std=c11 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s
// RUN: %clang_cc1 -std=c18 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s
// RUN: %clang_cc1 -std=c2x -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s
//
// Check -fno-finite-loops option in combination with various standard versions.
+// RUN: %clang_cc1 -std=c89 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s
// RUN: %clang_cc1 -std=c99 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s
// RUN: %clang_cc1 -std=c11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s
// RUN: %clang_cc1 -std=c18 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s
@@ -25,7 +28,9 @@ int b = 0;
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %for.cond
// CHECK: for.cond:
-// CHECK-NOT: br {{.*}}!llvm.loop
+// C99-NOT: br {{.*}}!llvm.loop
+// C11-NOT: br {{.*}}!llvm.loop
+// FINITE-NEXT: br {{.*}}!llvm.loop
//
void f0() {
for (; ;) ;
@@ -38,7 +43,9 @@ void f0() {
// CHECK: for.cond:
// CHECK-NEXT: br i1 true, label %for.body, label %for.end
// CHECK: for.body:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// C99-NOT: br {{.*}}, !llvm.loop
+// C11-NOT: br {{.*}}, !llvm.loop
+// FINITE-NEXT: br {{.*}}, !llvm.loop
// CHECK: for.end:
// CHECK-NEXT: ret void
//
@@ -75,7 +82,9 @@ void f2() {
// CHECK: for.cond:
// CHECK-NEXT: br i1 true, label %for.body, label %for.end
// CHECK: for.body:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// C99-NOT: br {{.*}}, !llvm.loop
+// C11-NOT: br {{.*}}, !llvm.loop
+// FINITE-NEXT: br {{.*}}, !llvm.loop
// CHECK: for.end:
// CHECK-NEXT: br label %for.cond1
// CHECK: for.cond1:
@@ -102,7 +111,9 @@ void F() {
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %while.body
// CHECK: while.body:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// C99-NOT: br {{.*}}, !llvm.loop
+// C11-NOT: br {{.*}}, !llvm.loop
+// FINITE-NEXT: br {{.*}}, !llvm.loop
//
void w1() {
while (1) {
@@ -141,12 +152,14 @@ void w2() {
// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end
// CHECK: while.body:
// C99-NOT: br {{.*}} !llvm.loop
-// C11: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
-// FINITE: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
+// C11-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
+// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
// CHECK: while.end:
// CHECK-NEXT: br label %while.body2
// CHECK: while.body2:
-// CHECK-NOT: br {{.*}} !llvm.loop
+// C99-NOT: br {{.*}} !llvm.loop
+// C11-NOT: br {{.*}} !llvm.loop
+// FINITE-NEXT: br {{.*}} !llvm.loop
//
void W() {
while (a == b) {
@@ -162,7 +175,9 @@ void W() {
// CHECK: do.body:
// CHECK-NEXT: br label %do.cond
// CHECK: do.cond:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// C99-NOT: br {{.*}}, !llvm.loop
+// C11-NOT: br {{.*}}, !llvm.loop
+// FINITE-NEXT: br {{.*}}, !llvm.loop
// CHECK: do.end:
// CHECK-NEXT: ret void
//
diff --git a/clang/test/CodeGenCXX/attr-mustprogress.cpp b/clang/test/CodeGenCXX/attr-mustprogress.cpp
index 1c0fecbb70bc9..ccc54114e32b8 100644
--- a/clang/test/CodeGenCXX/attr-mustprogress.cpp
+++ b/clang/test/CodeGenCXX/attr-mustprogress.cpp
@@ -23,20 +23,22 @@ int b = 0;
// CHECK: datalayout
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
-// FINITE-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
+// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2f0v(
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %for.cond
// CHECK: for.cond:
-// CHECK-NOT: br {{.*}} llvm.loop
+// CXX98-NOT: br {{.*}} llvm.loop
+// CXX11-NEXT: br label %for.cond, !llvm.loop [[LOOP1:!.*]]
+// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP1:!.*]]
void f0() {
for (; ;) ;
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2f1v(
// CHECK-NEXT: entry:
@@ -44,7 +46,9 @@ void f0() {
// CHECK: for.cond:
// CHECK-NEXT: br i1 true, label %for.body, label %for.end
// CHECK: for.body:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %for.cond, !llvm.loop [[LOOP2:!.*]]
+// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP2:!.*]]
// CHECK: for.end:
// CHECK-NEXT: ret void
//
@@ -53,8 +57,8 @@ void f1() {
;
}
-// CXX98-NOT: mustprogress
-// CXX11: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2f2v(
// CHECK-NEXT: entry:
@@ -66,8 +70,8 @@ void f1() {
// CHECK-NEXT: br i1 [[CMP]], label %for.body, label %for.end
// CHECK: for.body:
// CXX98-NOT: br {{.*}}, !llvm.loop
-// CXX11: br label %for.cond, !llvm.loop [[LOOP1:!.*]]
-// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP1:!.*]]
+// CXX11: br label %for.cond, !llvm.loop [[LOOP3:!.*]]
+// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]]
// CHECK: for.end:
// CHECK-NEXT: ret void
//
@@ -76,8 +80,8 @@ void f2() {
;
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z1Fv(
// CHECK-NEXT: entry:
@@ -85,7 +89,9 @@ void f2() {
// CHECK: for.cond:
// CHECK-NEXT: br i1 true, label %for.body, label %for.end
// CHECK: for.body:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %for.cond, !llvm.loop [[LOOP4:!.*]]
+// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP4:!.*]]
// CHECK: for.end:
// CHECK-NEXT: br label %for.cond1
// CHECK: for.cond1:
@@ -95,8 +101,8 @@ void f2() {
// CHECK-NEXT: br i1 [[CMP]], label %for.body2, label %for.end3
// CHECK: for.body2:
// CXX98-NOT: br {{.*}}, !llvm.loop
-// CXX11-NEXT: br label %for.cond1, !llvm.loop [[LOOP2:!.*]]
-// FINITE-NEXT: br label %for.cond1, !llvm.loop [[LOOP2:!.*]]
+// CXX11-NEXT: br label %for.cond1, !llvm.loop [[LOOP5:!.*]]
+// FINITE-NEXT: br label %for.cond1, !llvm.loop [[LOOP5:!.*]]
// CHECK: for.end3:
// CHECK-NEXT: ret void
//
@@ -107,8 +113,8 @@ void F() {
;
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2F2v(
// CHECK-NEXT: entry:
@@ -120,14 +126,16 @@ void F() {
// CHECK-NEXT: br i1 [[CMP]], label %for.body, label %for.end
// CHECK: for.body:
// CXX98_NOT: br {{.*}} !llvm.loop
-// CXX11-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]]
-// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]]
+// CXX11-NEXT: br label %for.cond, !llvm.loop [[LOOP6:!.*]]
+// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP6:!.*]]
// CHECK: for.end:
// CHECK-NEXT: br label %for.cond1
// CHECK: for.cond1:
// CHECK-NEXT: br i1 true, label %for.body2, label %for.end3
// CHECK: for.body2:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %for.cond1, !llvm.loop [[LOOP7:!.*]]
+// FINITE-NEXT: br label %for.cond1, !llvm.loop [[LOOP7:!.*]]
// CHECK: for.end3:
// CHECK-NEXT: ret void
//
@@ -138,22 +146,24 @@ void F2() {
;
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
-// FINITE-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
+// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2w1v(
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %while.body
// CHECK: while.body:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %while.body, !llvm.loop [[LOOP8:!.*]]
+// FINITE-NEXT: br label %while.body, !llvm.loop [[LOOP8:!.*]]
//
void w1() {
while (1)
;
}
-// CXX98-NOT: mustprogress
-// CXX11: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2w2v(
// CHECK-NEXT: entry:
@@ -165,8 +175,8 @@ void w1() {
// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end
// CHECK: while.body:
// CXX98-NOT: br {{.*}}, !llvm.loop
-// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
-// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
+// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP9:!.*]]
+// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP9:!.*]]
// CHECK: while.end:
// CHECK-NEXT: ret void
//
@@ -175,8 +185,8 @@ void w2() {
;
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z1Wv(
// CHECK-NEXT: entry:
@@ -188,12 +198,14 @@ void w2() {
// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end
// CHECK: while.body:
// CXX98-NOT: br {{.*}}, !llvm.loop
-// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP5:!.*]]
-// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP5:!.*]]
+// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP10:!.*]]
+// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP10:!.*]]
// CHECK: while.end:
// CHECK-NEXT: br label %while.body2
// CHECK: while.body2:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %while.body2, !llvm.loop [[LOOP11:!.*]]
+// FINITE-NEXT: br label %while.body2, !llvm.loop [[LOOP11:!.*]]
//
void W() {
while (a == b)
@@ -202,14 +214,16 @@ void W() {
;
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2W2v(
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %while.body
// CHECK: while.body:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %while.body, !llvm.loop [[LOOP12:!.*]]
+// FINITE-NEXT: br label %while.body, !llvm.loop [[LOOP12:!.*]]
//
void W2() {
while (1)
@@ -218,8 +232,8 @@ void W2() {
;
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2d1v(
// CHECK-NEXT: entry:
@@ -227,7 +241,9 @@ void W2() {
// CHECK: do.body:
// CHECK-NEXT: br label %do.cond
// CHECK: do.cond:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br i1 true, label %do.body, label %do.end, !llvm.loop [[LOOP13:!.*]]
+// FINITE-NEXT: br i1 true, label %do.body, label %do.end, !llvm.loop [[LOOP13:!.*]]
// CHECK: do.end:
// CHECK-NEXT: ret void
//
@@ -237,9 +253,9 @@ void d1() {
while (1);
}
-// CXX98-NOT: mustprogress
-// CXX11: mustprogress
-// FINITE-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
+// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2d2v(
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %do.body
@@ -250,8 +266,8 @@ void d1() {
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4
// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CXX98-NOT: br {{.*}}, !llvm.loop
-// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP6:!.*]]
-// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP6:!.*]]
+// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP14:!.*]]
+// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP14:!.*]]
// CHECK: do.end:
// CHECK-NEXT: ret void
//
@@ -261,16 +277,18 @@ void d2() {
while (a == b);
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
-// FINITE-NOT: mustprogress
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
+// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z1Dv(
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %do.body
// CHECK: do.body:
// CHECK-NEXT: br label %do.cond
// CHECK: do.cond:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br i1 true, label %do.body, label %do.end, !llvm.loop [[LOOP15:!.*]]
+// FINITE-NEXT: br i1 true, label %do.body, label %do.end, !llvm.loop [[LOOP15:!.*]]
// CHECK: do.end:
// CHECK-NEXT: br label %do.body1
// CHECK: do.body1:
@@ -280,8 +298,8 @@ void d2() {
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4
// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CXX98-NOT: br {{.*}}, !llvm.loop
-// CXX11-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP7:!.*]]
-// FINITE-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP7:!.*]]
+// CXX11-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP16:!.*]]
+// FINITE-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP16:!.*]]
// CHECK: do.end3:
// CHECK-NEXT: ret void
//
@@ -294,9 +312,9 @@ void D() {
while (a == b);
}
-// CXX98-NOT: mustprogress
-// CXX11-NOT: mustprogress
-// FINITE-NOT: mustprogress
+// CXX98-NOT : mustprogress
+// CXX11: mustprogress
+// FINITE-NOT: mustprogress
// CHECK-LABEL: @_Z2D2v(
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %do.body
@@ -307,14 +325,16 @@ void D() {
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4
// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
// CXX98-NOT: br {{.*}}, !llvm.loop
-// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP8:!.*]]
-// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP8:!.*]]
+// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP17:!.*]]
+// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP17:!.*]]
// CHECK: do.end:
// CHECK-NEXT: br label %do.body1
// CHECK: do.body1:
// CHECK-NEXT: br label %do.cond2
// CHECK: do.cond2:
-// CHECK-NOT: br {{.*}}, !llvm.loop
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br i1 true, label %do.body1, label %do.end3, !llvm.loop [[LOOP18:!.*]]
+// FINITE-NEXT: br i1 true, label %do.body1, label %do.end3, !llvm.loop [[LOOP18:!.*]]
// CHECK: do.end3:
// CHECK-NEXT: ret void
//
@@ -336,3 +356,13 @@ void D2() {
// CXX11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]}
// CXX11: [[LOOP7]] = distinct !{[[LOOP7]], [[MP]]}
// CXX11: [[LOOP8]] = distinct !{[[LOOP8]], [[MP]]}
+// CXX11: [[LOOP9]] = distinct !{[[LOOP9]], [[MP]]}
+// CXX11: [[LOOP10]] = distinct !{[[LOOP10]], [[MP]]}
+// CXX11: [[LOOP11]] = distinct !{[[LOOP11]], [[MP]]}
+// CXX11: [[LOOP12]] = distinct !{[[LOOP12]], [[MP]]}
+// CXX11: [[LOOP13]] = distinct !{[[LOOP13]], [[MP]]}
+// CXX11: [[LOOP14]] = distinct !{[[LOOP14]], [[MP]]}
+// CXX11: [[LOOP15]] = distinct !{[[LOOP15]], [[MP]]}
+// CXX11: [[LOOP16]] = distinct !{[[LOOP16]], [[MP]]}
+// CXX11: [[LOOP17]] = distinct !{[[LOOP17]], [[MP]]}
+// CXX11: [[LOOP18]] = distinct !{[[LOOP18]], [[MP]]}
More information about the cfe-commits
mailing list