mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-21 20:12:56 +02:00
74b2a804dd
Fixes cases like the new test @nonuniform. In that test, %cc itself is a uniform value; however, when reading it after the end of the loop in basic block %if, its value is effectively non-uniform, so the branch is non-uniform. This problem was encountered in https://bugs.freedesktop.org/show_bug.cgi?id=103743; however, this change in itself is not sufficient to fix that bug, as there is another issue in the AMDGPU backend. As discovered after committing an earlier version of this change, this exposes a subtle interaction between this pass and DivergenceAnalysis: since we remove and re-create branch instructions, we can no longer rely on DivergenceAnalysis for branches in subregions that were already processed by the pass. Explicitly remove branch instructions from DivergenceAnalysis to avoid dangling pointers as a matter of defensive programming, and change how we detect non-uniform subregions. Change-Id: I32bbffece4a32f686fab54964dae1a5dd72949d4 Differential Revision: https://reviews.llvm.org/D43743 llvm-svn: 329165
61 lines
2.0 KiB
C++
61 lines
2.0 KiB
C++
//===- llvm/Analysis/DivergenceAnalysis.h - Divergence Analysis -*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// The divergence analysis is an LLVM pass which can be used to find out
|
|
// if a branch instruction in a GPU program is divergent or not. It can help
|
|
// branch optimizations such as jump threading and loop unswitching to make
|
|
// better decisions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#ifndef LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
|
|
#define LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
|
|
|
|
#include "llvm/ADT/DenseSet.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/Pass.h"
|
|
|
|
namespace llvm {
|
|
class Value;
|
|
class DivergenceAnalysis : public FunctionPass {
|
|
public:
|
|
static char ID;
|
|
|
|
DivergenceAnalysis() : FunctionPass(ID) {
|
|
initializeDivergenceAnalysisPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
|
|
|
bool runOnFunction(Function &F) override;
|
|
|
|
// Print all divergent branches in the function.
|
|
void print(raw_ostream &OS, const Module *) const override;
|
|
|
|
// Returns true if V is divergent at its definition.
|
|
//
|
|
// Even if this function returns false, V may still be divergent when used
|
|
// in a different basic block.
|
|
bool isDivergent(const Value *V) const { return DivergentValues.count(V); }
|
|
|
|
// Returns true if V is uniform/non-divergent.
|
|
//
|
|
// Even if this function returns true, V may still be divergent when used
|
|
// in a different basic block.
|
|
bool isUniform(const Value *V) const { return !isDivergent(V); }
|
|
|
|
// Keep the analysis results uptodate by removing an erased value.
|
|
void removeValue(const Value *V) { DivergentValues.erase(V); }
|
|
|
|
private:
|
|
// Stores all divergent values.
|
|
DenseSet<const Value *> DivergentValues;
|
|
};
|
|
} // End llvm namespace
|
|
|
|
#endif //LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
|