[clang] ac73b73 - [clang] Add mustprogress and llvm.loop.mustprogress attribute deduction
Author: Atmn Patel Date: 2020-11-04T22:03:14-05:00 New Revision: ac73b73c16526c9e51943759ea6cab285a57e33f URL: https://github.com/llvm/llvm-project/commit/ac73b73c16526c9e51943759ea6cab285a57e33f DIFF: https://github.com/llvm/llvm-project/commit/ac73b73c16526c9e51943759ea6cab285a57e33f.diff LOG: [clang] Add mustprogress and llvm.loop.mustprogress attribute deduction Since C++11, the C++ standard has a forward progress guarantee [intro.progress], so all such functions must have the `mustprogress` requirement. In addition, from C11 and onwards, loops without a non-zero constant conditional or no conditional are also required to make progress (C11 6.8.5p6). This patch implements these attribute deductions so they can be used by the optimization passes. Differential Revision: https://reviews.llvm.org/D86841 Added: clang/test/CodeGen/attr-mustprogress-0.c clang/test/CodeGen/attr-mustprogress-0.cpp clang/test/CodeGen/attr-mustprogress-1.c clang/test/CodeGen/attr-mustprogress-1.cpp Modified: clang/lib/CodeGen/CGLoopInfo.cpp clang/lib/CodeGen/CGLoopInfo.h clang/lib/CodeGen/CGStmt.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/lib/CodeGen/CodeGenFunction.h clang/test/CodeGen/address-safety-attr-flavors.cpp clang/test/CodeGen/address-safety-attr.cpp clang/test/CodeGen/memtag-attr.cpp clang/test/CodeGen/no-builtin.cpp clang/test/CodeGen/pragma-do-while.cpp clang/test/CodeGenCXX/attr-likelihood-iteration-stmt.cpp clang/test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp clang/test/CodeGenCXX/debug-info-line-if.cpp clang/test/CodeGenCXX/debug-info-loops.cpp clang/test/CodeGenCXX/fno-unroll-loops-metadata.cpp clang/test/CodeGenCXX/pragma-followup_inner.cpp clang/test/CodeGenCXX/pragma-followup_outer.cpp clang/test/CodeGenCXX/pragma-loop-distribute.cpp clang/test/CodeGenCXX/pragma-loop-pr27643.cpp clang/test/CodeGenCXX/pragma-loop-predicate.cpp clang/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp clang/test/CodeGenCXX/pragma-loop-safety-nested.cpp clang/test/CodeGenCXX/pragma-loop-safety-outer.cpp clang/test/CodeGenCXX/pragma-loop-safety.cpp clang/test/CodeGenCXX/pragma-loop.cpp clang/test/CodeGenCXX/pragma-pipeline.cpp clang/test/CodeGenCXX/pragma-unroll-and-jam.cpp clang/test/CodeGenCXX/pragma-unroll.cpp clang/test/CodeGenCXX/thunks-ehspec.cpp clang/test/CodeGenCXX/thunks.cpp clang/test/OpenMP/simd_metadata.c clang/test/Profile/c-unprofiled-blocks.c clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected clang/test/utils/update_cc_test_checks/Inputs/check-attributes.cpp.funcattrs.expected clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.no-generated.expected Removed: diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index a02d832b84b4..be4993e802f8 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -411,10 +411,14 @@ MDNode *LoopInfo::createMetadata( LoopProperties.push_back(EndLoc.getAsMDNode()); } + LLVMContext &Ctx = Header->getContext(); + if (Attrs.MustProgress) +LoopProperties.push_back( +MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress"))); + assert(!!AccGroup == Attrs.IsParallel && "There must be an access group iff the loop is parallel"); if (Attrs.IsParallel) { -LLVMContext &Ctx = Header->getContext(); LoopProperties.push_back(MDNode::get( Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup})); } @@ -431,7 +435,7 @@ LoopAttributes::LoopAttributes(bool IsParallel) VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0), InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0), DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false), - PipelineInitiationInterval(0) {} + PipelineInitiationInterval(0), MustProgress(false) {} void LoopAttributes::clear() { IsParallel = false; @@ -446,6 +450,7 @@ void LoopAttributes::clear() { DistributeEnable = LoopAttributes::Unspecified; PipelineDisabled = false; PipelineInitiationInterval = 0; + MustProgress = false; } LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs, @@ -469,7 +474,7 @@ LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs, Attrs.UnrollEnable == LoopAttributes::Unspecified && Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified && Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc && - !EndLoc) + !EndLoc && !Attrs.MustProgress) return; TempLoopID = MDNode::getTemporary(Header->getContext(), None); @@ -570,8 +575,7 @@ void LoopInfoStack::push(Basic
[clang] 0b17c6e - [LoopDeletion] Allows deletion of possibly infinite side-effect free loops
Author: Atmn Patel Date: 2020-11-06T22:06:58-05:00 New Revision: 0b17c6e4479d62bd4ff05c48d6cdf340b198832f URL: https://github.com/llvm/llvm-project/commit/0b17c6e4479d62bd4ff05c48d6cdf340b198832f DIFF: https://github.com/llvm/llvm-project/commit/0b17c6e4479d62bd4ff05c48d6cdf340b198832f.diff LOG: [LoopDeletion] Allows deletion of possibly infinite side-effect free loops >From C11 and C++11 onwards, a forward-progress requirement has been introduced for both languages. In the case of C, loops with non-constant conditionals that do not have any observable side-effects (as defined by 6.8.5p6) can be assumed by the implementation to terminate, and in the case of C++, this assumption extends to all functions. The clang frontend will emit the `mustprogress` function attribute for C++ functions (D86233, D85393, D86841) and emit the loop metadata `llvm.loop.mustprogress` for every loop in C11 or later that has a non-constant conditional. This patch modifies LoopDeletion so that only loops with the `llvm.loop.mustprogress` metadata or loops contained in functions that are required to make progress (`mustprogress` or `willreturn`) are checked for observable side-effects. If these loops do not have an observable side-effect, then we delete them. Loops without observable side-effects that do not satisfy the above conditions will not be deleted. Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D86844 Added: llvm/test/Transforms/LoopDeletion/mustprogress.ll Modified: clang/test/Misc/loop-opt-setup.c llvm/include/llvm/Transforms/Utils/LoopUtils.h llvm/lib/Transforms/Scalar/LoopDeletion.cpp llvm/lib/Transforms/Utils/LoopUtils.cpp llvm/test/Other/loop-deletion-printer.ll llvm/test/Other/loop-pm-invalidation.ll llvm/test/Transforms/LICM/2003-02-27-PreheaderProblem.ll llvm/test/Transforms/LoopDeletion/2017-07-11-incremental-dt.ll llvm/test/Transforms/LoopDeletion/basic-remark.ll llvm/test/Transforms/LoopDeletion/diundef.ll llvm/test/Transforms/LoopDeletion/invalidation.ll llvm/test/Transforms/LoopDeletion/multiple-exit-conditions.ll llvm/test/Transforms/LoopDeletion/multiple-exits.ll llvm/test/Transforms/LoopDeletion/no-exit-blocks.ll llvm/test/Transforms/LoopDeletion/unreachable-loops.ll llvm/test/Transforms/LoopDeletion/use-in-unreachable.ll llvm/test/Transforms/SCCP/calltest.ll llvm/test/Transforms/SimpleLoopUnswitch/pr37888.ll Removed: diff --git a/clang/test/Misc/loop-opt-setup.c b/clang/test/Misc/loop-opt-setup.c index 322f5e0e6d4a..43a9f85bca27 100644 --- a/clang/test/Misc/loop-opt-setup.c +++ b/clang/test/Misc/loop-opt-setup.c @@ -25,6 +25,6 @@ void Helper() { // Check br i1 to make sure the loop is gone, there will still be a label branch for the infinite loop. // CHECK-LABEL: Helper -// CHECK: br label +// CHECK: entry: // CHECK-NOT: br i1 -// CHECK: br label +// CHECK-NEXT: ret void diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h index d741b5142e5b..076ea2f4453b 100644 --- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h +++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h @@ -229,6 +229,9 @@ bool hasDisableAllTransformsHint(const Loop *L); /// Look for the loop attribute that disables the LICM transformation heuristics. bool hasDisableLICMTransformsHint(const Loop *L); +/// Look for the loop attribute that requires progress within the loop. +bool hasMustProgress(const Loop *L); + /// The mode sets how eager a transformation should be applied. enum TransformationMode { /// The pass can use heuristics to determine whether a transformation should diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp index 065db647561e..0db50d06ff26 100644 --- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -210,8 +210,10 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT, // Don't remove loops for which we can't solve the trip count. // They could be infinite, in which case we'd be changing program behavior. const SCEV *S = SE.getConstantMaxBackedgeTakenCount(L); - if (isa(S)) { -LLVM_DEBUG(dbgs() << "Could not compute SCEV MaxBackedgeTakenCount.\n"); + if (isa(S) && + !L->getHeader()->getParent()->mustProgress() && !hasMustProgress(L)) { +LLVM_DEBUG(dbgs() << "Could not compute SCEV MaxBackedgeTakenCount and was " + "not required to make progress.\n"); return Changed ? LoopDeletionResult::Modified : LoopDeletionResult::Unmodified; } diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index e10a2306547a..4210cd66f3f6 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.
[clang] 569abb5 - [LoopDeletion] Fixes failing test
Author: Atmn Patel Date: 2020-11-06T22:45:28-05:00 New Revision: 569abb530ece721675032d3127bd6d63f252b12b URL: https://github.com/llvm/llvm-project/commit/569abb530ece721675032d3127bd6d63f252b12b DIFF: https://github.com/llvm/llvm-project/commit/569abb530ece721675032d3127bd6d63f252b12b.diff LOG: [LoopDeletion] Fixes failing test The commit 0b17c6e4479d62bd4ff05c48d6cdf340b198832f occasionally causes this test to fail, this fixes it. Added: Modified: clang/test/Misc/loop-opt-setup.c Removed: diff --git a/clang/test/Misc/loop-opt-setup.c b/clang/test/Misc/loop-opt-setup.c index 43a9f85bca27..7d26905b2ccc 100644 --- a/clang/test/Misc/loop-opt-setup.c +++ b/clang/test/Misc/loop-opt-setup.c @@ -25,6 +25,5 @@ void Helper() { // Check br i1 to make sure the loop is gone, there will still be a label branch for the infinite loop. // CHECK-LABEL: Helper -// CHECK: entry: // CHECK-NOT: br i1 -// CHECK-NEXT: ret void +// CHECK: ret void ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] b1878b4 - [CodeGen] Fixes sanitizer test
Author: Atmn Patel Date: 2020-11-06T23:53:38-05:00 New Revision: b1878b4641e06baa754ce6e3e0387b1e7d7dc143 URL: https://github.com/llvm/llvm-project/commit/b1878b4641e06baa754ce6e3e0387b1e7d7dc143 DIFF: https://github.com/llvm/llvm-project/commit/b1878b4641e06baa754ce6e3e0387b1e7d7dc143.diff LOG: [CodeGen] Fixes sanitizer test By turning the loop into an infinite one, the loop can't be deleted anymore so the test will continue to pass. Added: Modified: clang/test/CodeGen/sanitizer-module-constructor.c Removed: diff --git a/clang/test/CodeGen/sanitizer-module-constructor.c b/clang/test/CodeGen/sanitizer-module-constructor.c index 3e29a923a9f1..ee4c4f7e1019 100644 --- a/clang/test/CodeGen/sanitizer-module-constructor.c +++ b/clang/test/CodeGen/sanitizer-module-constructor.c @@ -11,7 +11,7 @@ struct a { int d; b e; static void f(b g) { - for (d = g->c;;) + for (d = g->c; 1 ;) ; } void h() { f(e); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] d3e75d3 - Revert "[CodeGen] Fixes sanitizer test"
Author: Atmn Patel Date: 2020-11-07T00:32:12-05:00 New Revision: d3e75d31e3c831d00277518caee80b15b72666a8 URL: https://github.com/llvm/llvm-project/commit/d3e75d31e3c831d00277518caee80b15b72666a8 DIFF: https://github.com/llvm/llvm-project/commit/d3e75d31e3c831d00277518caee80b15b72666a8.diff LOG: Revert "[CodeGen] Fixes sanitizer test" This reverts commit b1878b4641e06baa754ce6e3e0387b1e7d7dc143. This does fix the test but it means that ac73b73c1652 is not implemented correctly. Reverting for now, and will be reverting the commit that causes this to fail. Added: Modified: clang/test/CodeGen/sanitizer-module-constructor.c Removed: diff --git a/clang/test/CodeGen/sanitizer-module-constructor.c b/clang/test/CodeGen/sanitizer-module-constructor.c index ee4c4f7e1019..3e29a923a9f1 100644 --- a/clang/test/CodeGen/sanitizer-module-constructor.c +++ b/clang/test/CodeGen/sanitizer-module-constructor.c @@ -11,7 +11,7 @@ struct a { int d; b e; static void f(b g) { - for (d = g->c; 1 ;) + for (d = g->c;;) ; } void h() { f(e); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] fd3cad7 - [clang] Fix ForStmt mustprogress handling
Author: Atmn Patel Date: 2020-11-09T11:38:06-05:00 New Revision: fd3cad7a60168b49f7bc160354655d7605847d41 URL: https://github.com/llvm/llvm-project/commit/fd3cad7a60168b49f7bc160354655d7605847d41 DIFF: https://github.com/llvm/llvm-project/commit/fd3cad7a60168b49f7bc160354655d7605847d41.diff LOG: [clang] Fix ForStmt mustprogress handling D86841 had an error where for statements with no conditional were required to make progress. This is not true, this patch removes that line, and adds regression tests. Differential Revision: https://reviews.llvm.org/D91075 Added: Modified: clang/lib/CodeGen/CGStmt.cpp clang/test/CodeGen/attr-mustprogress-1.c clang/test/CodeGen/attr-mustprogress-1.cpp Removed: diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 972da3d4ea2d..d8be0ef4e525 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -947,7 +947,6 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S, Expr::EvalResult Result; if (LanguageRequiresProgress()) { if (!S.getCond()) { - LoopMustProgress = true; FnIsMustProgress = false; } else if (!S.getCond()->EvaluateAsInt(Result, getContext())) { LoopMustProgress = true; diff --git a/clang/test/CodeGen/attr-mustprogress-1.c b/clang/test/CodeGen/attr-mustprogress-1.c index a5a8595218a1..2ff068b8b90a 100644 --- a/clang/test/CodeGen/attr-mustprogress-1.c +++ b/clang/test/CodeGen/attr-mustprogress-1.c @@ -7,6 +7,17 @@ int a = 0; int b = 0; +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @f0( +// CHECK-NEXT: entry: +// CHECK-NEXT:br label [[FOR_COND:%.*]] +// CHECK: for.cond: +// CHECK-NOT:br label [[FOR_COND]], !llvm.loop !{{.*}} +// +void f0() { + for (; ;) ; +} + // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: @f1( // CHECK-NEXT: entry: diff --git a/clang/test/CodeGen/attr-mustprogress-1.cpp b/clang/test/CodeGen/attr-mustprogress-1.cpp index 6d53d2d1148d..945d74663c6d 100644 --- a/clang/test/CodeGen/attr-mustprogress-1.cpp +++ b/clang/test/CodeGen/attr-mustprogress-1.cpp @@ -7,6 +7,16 @@ int a = 0; int b = 0; +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @_Z2f0v( +// CHECK-NEXT: entry: +// CHECK-NEXT:br label [[FOR_COND:%.*]] +// CHECK: for.cond: +// CHECK-NOT:br label [[FOR_COND]], !llvm.loop !{{.*}} +void f0() { + for (; ;) ; +} + // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: @_Z2f1v( // CHECK-NEXT: entry: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] f88a797 - [LoopDeletion] Allows deletion of possibly infinite side-effect free loops
Author: Atmn Patel Date: 2021-01-05T09:56:16-05:00 New Revision: f88a7975210fc995197af4b393e3bb5030e97a5c URL: https://github.com/llvm/llvm-project/commit/f88a7975210fc995197af4b393e3bb5030e97a5c DIFF: https://github.com/llvm/llvm-project/commit/f88a7975210fc995197af4b393e3bb5030e97a5c.diff LOG: [LoopDeletion] Allows deletion of possibly infinite side-effect free loops >From C11 and C++11 onwards, a forward-progress requirement has been introduced for both languages. In the case of C, loops with non-constant conditionals that do not have any observable side-effects (as defined by 6.8.5p6) can be assumed by the implementation to terminate, and in the case of C++, this assumption extends to all functions. The clang frontend will emit the `mustprogress` function attribute for C++ functions (D86233, D85393, D86841) and emit the loop metadata `llvm.loop.mustprogress` for every loop in C11 or later that has a non-constant conditional. This patch modifies LoopDeletion so that only loops with the `llvm.loop.mustprogress` metadata or loops contained in functions that are required to make progress (`mustprogress` or `willreturn`) are checked for observable side-effects. If these loops do not have an observable side-effect, then we delete them. Loops without observable side-effects that do not satisfy the above conditions will not be deleted. Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D86844 Added: llvm/test/Transforms/LoopDeletion/mustprogress.ll Modified: clang/test/Misc/loop-opt-setup.c llvm/include/llvm/Transforms/Utils/LoopUtils.h llvm/lib/Transforms/Scalar/LoopDeletion.cpp llvm/lib/Transforms/Utils/LoopUtils.cpp llvm/test/Transforms/LoopDeletion/no-exit-blocks.ll Removed: diff --git a/clang/test/Misc/loop-opt-setup.c b/clang/test/Misc/loop-opt-setup.c index 9cea02a8bcb3..e9a9c1e8ae2d 100644 --- a/clang/test/Misc/loop-opt-setup.c +++ b/clang/test/Misc/loop-opt-setup.c @@ -1,5 +1,6 @@ -// This relies on %clang_cc1, %clang does not emit the block names in Release mode. +// This tests loop unrolling and loop deletion (enabled under -O1) // RUN: %clang_cc1 -O1 -fno-unroll-loops -S -o - %s -emit-llvm | FileCheck %s +// RUN: %clang_cc1 -std=c99 -O1 -fno-unroll-loops -S -o - %s -emit-llvm | FileCheck %s --check-prefix C99 extern int a[16]; int b = 0; @@ -25,7 +26,12 @@ void Helper() { } // Check br i1 to make sure the loop is gone, there will still be a label branch for the infinite loop. +// In C99, there was no forward progress requirement, so we expect the infinite loop to still exist, +// but for C11 and onwards, the infinite loop can be deleted. // CHECK-LABEL: Helper -// CHECK: br label -// CHECK-NOT: br i1 -// CHECK: br label +// C99: br label +// C99-NOT: br i1 +// C99: br label +// CHECK: entry: +// CHECK-NOT: br i1 +// CHECK-NEXT: ret void diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h index d606fa954f95..80c6b09d9cf0 100644 --- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h +++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h @@ -255,6 +255,9 @@ bool hasDisableAllTransformsHint(const Loop *L); /// Look for the loop attribute that disables the LICM transformation heuristics. bool hasDisableLICMTransformsHint(const Loop *L); +/// Look for the loop attribute that requires progress within the loop. +bool hasMustProgress(const Loop *L); + /// The mode sets how eager a transformation should be applied. enum TransformationMode { /// The pass can use heuristics to determine whether a transformation should diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp index 065db647561e..814cfc7ac6a9 100644 --- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -128,10 +128,11 @@ static bool isLoopNeverExecuted(Loop *L) { /// Remove a loop if it is dead. /// -/// A loop is considered dead if it does not impact the observable behavior of -/// the program other than finite running time. This never removes a loop that -/// might be infinite (unless it is never executed), as doing so could change -/// the halting/non-halting nature of a program. +/// A loop is considered dead either if it does not impact the observable +/// behavior of the program other than finite running time, or if it is +/// required to make progress by an attribute such as 'mustprogress' or +/// 'llvm.loop.mustprogress' and does not make any. This may remove +/// infinite loops that have been required to make progress. /// /// This entire process relies pretty heavily on LoopSimplify form and LCSSA in /// order to make various safety checks work. @@ -207,11 +208,13 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT, : LoopDeletionResult::Unmodifie