aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/CodeMetrics.cpp
diff options
context:
space:
mode:
authorSameer Sahasrabuddhe <sameer.sahasrabuddhe@amd.com>2024-06-06 13:13:46 +0530
committerGitHub <noreply@github.com>2024-06-06 13:13:46 +0530
commite0ac087ff004f7a63ba64b9685f4f098d6ee54c5 (patch)
treead2430fdc681937715dff389529fa28d7b75471e /llvm/lib/Analysis/CodeMetrics.cpp
parent16e2ec82ac45701f9c55ab917e30f38dbae6f79a (diff)
downloadllvm-e0ac087ff004f7a63ba64b9685f4f098d6ee54c5.zip
llvm-e0ac087ff004f7a63ba64b9685f4f098d6ee54c5.tar.gz
llvm-e0ac087ff004f7a63ba64b9685f4f098d6ee54c5.tar.bz2
[LoopUnroll] Consider convergence control tokens when unrolling (#91715)
- There is no restriction on a loop with controlled convergent operations when the relevant tokens are defined and used within the loop. - When a token defined outside a loop is used inside (also called a loop convergence heart), unrolling is allowed only in the absence of remainder or runtime checks. - When a token defined inside a loop is used outside, such a loop is said to be "extended". This loop can only be unrolled by also duplicating the extended part lying outside the loop. Such unrolling is disabled for now. - Clean up loop hearts: When unrolling a loop with a heart, duplicating the heart will introduce multiple static uses of a convergence control token in a cycle that does not contain its definition. This violates the static rules for tokens, and needs to be cleaned up into a single occurrence of the intrinsic. - Spell out the initializer for UnrollLoopOptions to improve readability. Original implementation [D85605] by Nicolai Haehnle <nicolai.haehnle@amd.com>.
Diffstat (limited to 'llvm/lib/Analysis/CodeMetrics.cpp')
-rw-r--r--llvm/lib/Analysis/CodeMetrics.cpp53
1 files changed, 43 insertions, 10 deletions
diff --git a/llvm/lib/Analysis/CodeMetrics.cpp b/llvm/lib/Analysis/CodeMetrics.cpp
index 2637e2f..ea67b52 100644
--- a/llvm/lib/Analysis/CodeMetrics.cpp
+++ b/llvm/lib/Analysis/CodeMetrics.cpp
@@ -16,6 +16,7 @@
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/InstructionCost.h"
@@ -111,11 +112,24 @@ void CodeMetrics::collectEphemeralValues(
completeEphemeralValues(Visited, Worklist, EphValues);
}
+static bool extendsConvergenceOutsideLoop(const Instruction &I, const Loop *L) {
+ if (!L)
+ return false;
+ if (!isa<ConvergenceControlInst>(I))
+ return false;
+ for (const auto *U : I.users()) {
+ if (!L->contains(cast<Instruction>(U)))
+ return true;
+ }
+ return false;
+}
+
/// Fill in the current structure with information gleaned from the specified
/// block.
void CodeMetrics::analyzeBasicBlock(
const BasicBlock *BB, const TargetTransformInfo &TTI,
- const SmallPtrSetImpl<const Value *> &EphValues, bool PrepareForLTO) {
+ const SmallPtrSetImpl<const Value *> &EphValues, bool PrepareForLTO,
+ const Loop *L) {
++NumBlocks;
InstructionCost NumInstsBeforeThisBB = NumInsts;
for (const Instruction &I : *BB) {
@@ -163,19 +177,38 @@ void CodeMetrics::analyzeBasicBlock(
if (isa<ExtractElementInst>(I) || I.getType()->isVectorTy())
++NumVectorInsts;
- if (I.getType()->isTokenTy() && I.isUsedOutsideOfBlock(BB))
+ if (I.getType()->isTokenTy() && !isa<ConvergenceControlInst>(I) &&
+ I.isUsedOutsideOfBlock(BB)) {
+ LLVM_DEBUG(dbgs() << I
+ << "\n Cannot duplicate a token value used outside "
+ "the current block (except convergence control).\n");
notDuplicatable = true;
-
- if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
- if (CI->cannotDuplicate())
- notDuplicatable = true;
- if (CI->isConvergent())
- convergent = true;
}
- if (const InvokeInst *InvI = dyn_cast<InvokeInst>(&I))
- if (InvI->cannotDuplicate())
+ if (const CallBase *CB = dyn_cast<CallBase>(&I)) {
+ if (CB->cannotDuplicate())
notDuplicatable = true;
+ // Compute a meet over the visited blocks for the following partial order:
+ //
+ // None -> { Controlled, ExtendedLoop, Uncontrolled}
+ // Controlled -> ExtendedLoop
+ if (Convergence <= ConvergenceKind::Controlled && CB->isConvergent()) {
+ if (isa<ConvergenceControlInst>(CB) ||
+ CB->getConvergenceControlToken()) {
+ assert(Convergence != ConvergenceKind::Uncontrolled);
+ LLVM_DEBUG(dbgs() << "Found controlled convergence:\n" << I << "\n");
+ if (extendsConvergenceOutsideLoop(I, L))
+ Convergence = ConvergenceKind::ExtendedLoop;
+ else {
+ assert(Convergence != ConvergenceKind::ExtendedLoop);
+ Convergence = ConvergenceKind::Controlled;
+ }
+ } else {
+ assert(Convergence == ConvergenceKind::None);
+ Convergence = ConvergenceKind::Uncontrolled;
+ }
+ }
+ }
NumInsts += TTI.getInstructionCost(&I, TargetTransformInfo::TCK_CodeSize);
}