Skip to content

Commit

Permalink
Simplified global volatile access clobbering checker.
Browse files Browse the repository at this point in the history
Misc: vc::getUnderlyingGlobalVariable and genx::getBitCastedValue to support arbitrary chains of instruction- and constant-expression- -typed bitcasts
Test GVClobberingChecker/global_volatile_clobbering_checker_fixup.ll reduced.
  • Loading branch information
lsatanov authored and igcbot committed Sep 14, 2023
1 parent b7e0f3e commit 8f3cded
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 198 deletions.
2 changes: 1 addition & 1 deletion IGC/VectorCompiler/lib/GenXCodeGen/GenX.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ ModulePass *createGenXNumberingWrapperPass();
ModulePass *createGenXLiveRangesWrapperPass();
ModulePass *createGenXRematerializationWrapperPass();
ModulePass *createGenXCoalescingWrapperPass();
ModulePass *createGenXGVClobberCheckerWrapperPass();
ModulePass *createGenXGVClobberCheckerPass();
ModulePass *createGenXAddressCommoningWrapperPass();
ModulePass *createGenXArgIndirectionWrapperPass();
FunctionPass *createGenXTidyControlFlowPass();
Expand Down
135 changes: 60 additions & 75 deletions IGC/VectorCompiler/lib/GenXCodeGen/GenXGVClobberChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ SPDX-License-Identifier: MIT
#include "vc/Support/GenXDiagnostic.h"
#include "vc/Utils/GenX/GlobalVariable.h"

#include <map>
#include <unordered_map>

#define DEBUG_TYPE "GENX_CLOBBER_CHECKER"

Expand All @@ -82,7 +82,7 @@ static cl::opt<bool> CheckGVClobberingCollectRelatedGVStoreCallSites(

namespace {

class GenXGVClobberChecker : public FGPassImplInterface,
class GenXGVClobberChecker : public ModulePass,
public IDMixin<GenXGVClobberChecker> {
private:
GenXBaling *Baling = nullptr;
Expand All @@ -92,34 +92,34 @@ class GenXGVClobberChecker : public FGPassImplInterface,
llvm::SetVector<Instruction *> *SIs);

public:
explicit GenXGVClobberChecker() {}
static StringRef getPassName() { return "GenX GV clobber checker/fixup"; }
static void getAnalysisUsage(AnalysisUsage &AU) {
AU.addRequired<GenXLiveness>();
AU.addRequired<GenXGroupBaling>();
explicit GenXGVClobberChecker() : ModulePass(ID) {}
StringRef getPassName() const override {
return "GenX GV clobber checker/fixup";
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addUsedIfAvailable<GenXLiveness>();
AU.addUsedIfAvailable<GenXGroupBaling>();
if (!CheckGVClobberingTryFixup)
AU.setPreservesAll();
}
bool runOnFunctionGroup(FunctionGroup &FG) override;
bool runOnModule(Module &) override;
};
} // namespace

namespace llvm {
void initializeGenXGVClobberCheckerWrapperPass(PassRegistry &);
using GenXGVClobberCheckerWrapper =
FunctionGroupWrapperPass<GenXGVClobberChecker>;
void initializeGenXGVClobberCheckerPass(PassRegistry &);
} // namespace llvm
INITIALIZE_PASS_BEGIN(GenXGVClobberCheckerWrapper,
"GenXGVClobberCheckerWrapper",

INITIALIZE_PASS_BEGIN(GenXGVClobberChecker, "GenXGVClobberChecker",
"GenX global volatile clobbering checker", false, false)
INITIALIZE_PASS_DEPENDENCY(GenXGroupBalingWrapper)
INITIALIZE_PASS_DEPENDENCY(GenXLivenessWrapper)
INITIALIZE_PASS_END(GenXGVClobberCheckerWrapper, "GenXGVClobberCheckerWrapper",
INITIALIZE_PASS_END(GenXGVClobberChecker, "GenXGVClobberChecker",
"GenX global volatile clobbering checker", false, false)

ModulePass *llvm::createGenXGVClobberCheckerWrapperPass() {
initializeGenXGVClobberCheckerWrapperPass(*PassRegistry::getPassRegistry());
return new GenXGVClobberCheckerWrapper();
ModulePass *llvm::createGenXGVClobberCheckerPass() {
initializeGenXGVClobberCheckerPass(*PassRegistry::getPassRegistry());
return new GenXGVClobberChecker();
}

bool GenXGVClobberChecker::checkGVClobberingByInterveningStore(
Expand All @@ -130,9 +130,7 @@ bool GenXGVClobberChecker::checkGVClobberingByInterveningStore(
if (!UI)
continue;

const StringRef DiagPrefix =
"Global volatile clobbering checker: clobbering detected,"
" some optimizations resulted in over-optimization,";
const StringRef DiagPrefix = "potential clobbering detected:";

if (auto *SI = genx::getInterveningGVStoreOrNull(LI, UI, SIs)) {
vc::diagnose(LI->getContext(), DiagPrefix,
Expand All @@ -148,18 +146,26 @@ bool GenXGVClobberChecker::checkGVClobberingByInterveningStore(
<< __FUNCTION__ << ": User: ";
UI->print(dbgs()); dbgs() << "\n";);
if (CheckGVClobberingTryFixup) {
if (!Baling || !Liveness)
vc::diagnose(LI->getContext(), DiagPrefix,
"Either Baling or Liveness analysis results are not "
"available",
DS_Warning, vc::WarningName::Generic, UI);

if (GenXIntrinsic::isRdRegion(UI) &&
isa<Constant>(
UI->getOperand(GenXIntrinsic::GenXRegion::RdIndexOperandNum))) {
if (Baling->isBaled(UI))
Baling->unbale(UI);
UI->moveAfter(LI);
if (Liveness->getLiveRangeOrNull(UI))
Liveness->removeValue(UI);
auto *LR = Liveness->getOrCreateLiveRange(UI);
LR->setCategory(Liveness->getLiveRangeOrNull(LI)->getCategory());
LR->setLogAlignment(
Liveness->getLiveRangeOrNull(LI)->getLogAlignment());
if (Baling && Baling->isBaled(UI))
Baling->unbale(UI);
if (Liveness) {
if (Liveness->getLiveRangeOrNull(UI))
Liveness->removeValue(UI);
auto *LR = Liveness->getOrCreateLiveRange(UI);
LR->setCategory(Liveness->getLiveRangeOrNull(LI)->getCategory());
LR->setLogAlignment(
Liveness->getLiveRangeOrNull(LI)->getLogAlignment());
}
Changed |= true;
} else {
vc::diagnose(
Expand All @@ -176,55 +182,34 @@ bool GenXGVClobberChecker::checkGVClobberingByInterveningStore(
return Changed;
};

bool GenXGVClobberChecker::runOnFunctionGroup(FunctionGroup &FG) {
bool GenXGVClobberChecker::runOnModule(Module &M) {
bool Changed = false;
Baling = &getAnalysis<GenXGroupBaling>();
Liveness = &getAnalysis<GenXLiveness>();

for (auto &GV : FG.getModule()->globals()) {
if (!GV.hasAttribute(genx::FunctionMD::GenXVolatile))
continue;

auto *GvLiveRange = Liveness->getLiveRangeOrNull(&GV);
if (!GvLiveRange)
continue;

llvm::SetVector<Instruction *> LoadsInFunctionGroup;
std::map<Function *, llvm::SetVector<Instruction *>>
GVStoreRelatedCallSitesPerFunction{};

for (const auto &User : GV.users()) {
auto *GVUserInst = dyn_cast<Instruction>(User);
if (!GVUserInst)
continue;

if (llvm::find(FG, GVUserInst->getFunction()) == FG.end())
continue;

if (isa<LoadInst>(GVUserInst))
LoadsInFunctionGroup.insert(GVUserInst);
else if (CheckGVClobberingCollectRelatedGVStoreCallSites &&
isa<StoreInst>(GVUserInst))
genx::collectRelatedCallSitesPerFunction(
GVUserInst, &FG, GVStoreRelatedCallSitesPerFunction);

// Global variable is used in a constexpr.
if (&GV != vc::getUnderlyingGlobalVariable(GVUserInst))
continue;

// Loads preceded by bitcasts.
for (const auto &User : GVUserInst->users())
if (auto *Load = dyn_cast<LoadInst>(User))
if (llvm::find(FG, Load->getFunction()) != FG.end())
LoadsInFunctionGroup.insert(Load);
}

for (const auto &LI : LoadsInFunctionGroup)
Changed |= checkGVClobberingByInterveningStore(
LI, CheckGVClobberingCollectRelatedGVStoreCallSites
? &GVStoreRelatedCallSitesPerFunction[LI->getFunction()]
: nullptr);
Baling = getAnalysisIfAvailable<GenXGroupBaling>();
Liveness = getAnalysisIfAvailable<GenXLiveness>();

llvm::SetVector<Instruction *> Loads;
std::unordered_map<
Value *, std::unordered_map<Function *, llvm::SetVector<Instruction *>>>
ClobberingInsns{};

for (auto &F : M.functions()) {
for (auto &BB : F)
for (auto &I : BB)
if (genx::isGlobalVolatileLoad(&I))
Loads.insert(&I);
else if (CheckGVClobberingCollectRelatedGVStoreCallSites &&
genx::isGlobalVolatileStore(&I))
genx::collectRelatedCallSitesPerFunction(
&I, nullptr,
ClobberingInsns[genx::getBitCastedValue(I.getOperand(1))]);
}

for (const auto &LI : Loads)
Changed |= checkGVClobberingByInterveningStore(
LI, CheckGVClobberingCollectRelatedGVStoreCallSites
? &ClobberingInsns[genx::getBitCastedValue(LI->getOperand(0))]
[LI->getFunction()]
: nullptr);

return Changed;
}
4 changes: 2 additions & 2 deletions IGC/VectorCompiler/lib/GenXCodeGen/GenXTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void initializeGenXPasses(PassRegistry &registry) {
initializeGenXCFSimplificationPass(registry);
initializeGenXCisaBuilderWrapperPass(registry);
initializeGenXCoalescingWrapperPass(registry);
initializeGenXGVClobberCheckerWrapperPass(registry);
initializeGenXGVClobberCheckerPass(registry);
initializeGenXDeadVectorRemovalPass(registry);
initializeGenXDepressurizerWrapperPass(registry);
initializeGenXEarlySimdCFConformancePass(registry);
Expand Down Expand Up @@ -609,7 +609,7 @@ bool GenXTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
vc::addPass(PM, createGenXLiveRangesWrapperPass());
/// .. include:: GenXGVClobberChecker.cpp
if (BackendConfig.checkGVClobbering())
vc::addPass(PM, createGenXGVClobberCheckerWrapperPass());
vc::addPass(PM, createGenXGVClobberCheckerPass());
/// .. include:: GenXCoalescing.cpp
vc::addPass(PM, createGenXCoalescingWrapperPass());
/// .. include:: GenXAddressCommoning.cpp
Expand Down
2 changes: 1 addition & 1 deletion IGC/VectorCompiler/lib/GenXCodeGen/GenXTargetMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ void initializeGenXCategoryWrapperPass(PassRegistry &);
void initializeGenXCFSimplificationPass(PassRegistry &);
void initializeGenXCisaBuilderWrapperPass(PassRegistry &);
void initializeGenXCoalescingWrapperPass(PassRegistry &);
void initializeGenXGVClobberCheckerWrapperPass(PassRegistry &);
void initializeGenXGVClobberCheckerPass(PassRegistry &);
void initializeGenXDeadVectorRemovalPass(PassRegistry &);
void initializeGenXDepressurizerWrapperPass(PassRegistry &);
void initializeGenXEarlySimdCFConformancePass(PassRegistry &);
Expand Down
11 changes: 7 additions & 4 deletions IGC/VectorCompiler/lib/GenXCodeGen/GenXUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1575,8 +1575,11 @@ void genx::LayoutBlocks(Function &func)
}

Value *genx::getBitCastedValue(Value *V) {
while (auto *BCI = dyn_cast<BitCastInst>(V))
V = BCI->getOperand(0);
while (isa<BitCastInst>(V) ||
(isa<ConstantExpr>(V) &&
cast<ConstantExpr>(V)->getOpcode() == CastInst::BitCast))
V = isa<BitCastInst>(V) ? cast<Instruction>(V)->getOperand(0)
: cast<ConstantExpr>(V)->getOperand(0);
return V;
}

Expand Down Expand Up @@ -2397,7 +2400,7 @@ genx::getInterveningGVStoreOrNull(Instruction *LI, Instruction *UIOrPos,

void genx::collectRelatedCallSitesPerFunction(
Instruction *SI, FunctionGroup *FG,
std::map<Function *, llvm::SetVector<Instruction *>>
std::unordered_map<Function *, llvm::SetVector<Instruction *>>
&CallSitesPerFunction) {
using FuncsSeenT = llvm::SetVector<Function *>;
auto collectRelatedCallSites = [&](Function *Func, FuncsSeenT *FuncsSeen,
Expand All @@ -2409,7 +2412,7 @@ void genx::collectRelatedCallSitesPerFunction(
if (isa<CallBase>(FuncUser)) {
auto *Call = dyn_cast<Instruction>(FuncUser);
auto *curFunction = Call->getFunction();
if (llvm::find(*FG, curFunction) == FG->end())
if (FG && llvm::find(*FG, curFunction) == FG->end())
continue;
CallSitesPerFunction[curFunction].insert(Call);
collectRelatedCallSites(curFunction, FuncsSeen,
Expand Down
2 changes: 1 addition & 1 deletion IGC/VectorCompiler/lib/GenXCodeGen/GenXUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ bool checkGVClobberingByInterveningStore(

void collectRelatedCallSitesPerFunction(
Instruction *SI, class FunctionGroup *FG,
std::map<Function *, llvm::SetVector<Instruction *>>
std::unordered_map<Function *, llvm::SetVector<Instruction *>>
&InstAndRelatedCallSitesPerFunction);

llvm::SetVector<Instruction *> getAncestorGVLoads(Instruction *I,
Expand Down
13 changes: 5 additions & 8 deletions IGC/VectorCompiler/lib/Utils/GenX/GlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,11 @@ bool vc::isRealGlobalVariable(const GlobalVariable &GV) {
}

const GlobalVariable *vc::getUnderlyingGlobalVariable(const Value *V) {
while (auto *BI = dyn_cast<BitCastInst>(V))
V = BI->getOperand(0);
while (auto *CE = dyn_cast_or_null<ConstantExpr>(V)) {
if (CE->getOpcode() == CastInst::BitCast)
V = CE->getOperand(0);
else
break;
}
while (isa<BitCastInst>(V) ||
(isa<ConstantExpr>(V) &&
cast<ConstantExpr>(V)->getOpcode() == CastInst::BitCast))
V = isa<BitCastInst>(V) ? cast<Instruction>(V)->getOperand(0)
: cast<ConstantExpr>(V)->getOperand(0);
return dyn_cast_or_null<GlobalVariable>(V);
}

Expand Down
Loading

0 comments on commit 8f3cded

Please sign in to comment.