Skip to content

Commit

Permalink
Transforms: Split LowerAtomics into separate Utils and pass
Browse files Browse the repository at this point in the history
This will allow code sharing from AtomicExpandPass. Not entirely sure
why these exist as separate passes though.
  • Loading branch information
arsenm committed Apr 7, 2022
1 parent ea64828 commit 39f1568
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 92 deletions.
30 changes: 30 additions & 0 deletions llvm/include/llvm/Transforms/Scalar/LowerAtomicPass.h
@@ -0,0 +1,30 @@
//===- LowerAtomicPass.h - Lower atomic intrinsics --------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
// This pass lowers atomic intrinsics to non-atomic form for use in a known
// non-preemptible environment.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_TRANSFORMS_SCALAR_LOWERATOMICPASS_H
#define LLVM_TRANSFORMS_SCALAR_LOWERATOMICPASS_H

#include "llvm/IR/PassManager.h"

namespace llvm {

/// A pass that lowers atomic intrinsic into non-atomic intrinsics.
class LowerAtomicPass : public PassInfoMixin<LowerAtomicPass> {
public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
static bool isRequired() { return true; }
};

}

#endif // LLVM_TRANSFORMS_SCALAR_LOWERATOMICPASS_H
@@ -1,4 +1,4 @@
//===- LowerAtomic.cpp - Lower atomic intrinsics ----------------*- C++ -*-===//
//===- LowerAtomic.h - Lower atomic intrinsics ------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand All @@ -14,18 +14,13 @@
#ifndef LLVM_TRANSFORMS_SCALAR_LOWERATOMIC_H
#define LLVM_TRANSFORMS_SCALAR_LOWERATOMIC_H

#include "llvm/IR/PassManager.h"

namespace llvm {
class AtomicCmpXchgInst;
class AtomicRMWInst;

/// A pass that lowers atomic intrinsic into non-atomic intrinsics.
class LowerAtomicPass : public PassInfoMixin<LowerAtomicPass> {
public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
static bool isRequired() { return true; }
};
/// Convert the given Cmpxchg into primitive load and compare.
bool lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI);

class AtomicRMWInst;
/// Convert the given RMWI into primitive load and stores,
/// assuming that doing so is legal. Return true if the lowering
/// succeeds.
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Passes/PassBuilder.cpp
Expand Up @@ -185,7 +185,7 @@
#include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h"
#include "llvm/Transforms/Scalar/LoopUnrollPass.h"
#include "llvm/Transforms/Scalar/LoopVersioningLICM.h"
#include "llvm/Transforms/Scalar/LowerAtomic.h"
#include "llvm/Transforms/Scalar/LowerAtomicPass.h"
#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
#include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/NVPTX/NVPTXAtomicLower.cpp
Expand Up @@ -17,7 +17,7 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Transforms/Scalar/LowerAtomic.h"
#include "llvm/Transforms/Utils/LowerAtomic.h"

#include "MCTargetDesc/NVPTXBaseInfo.h"
using namespace llvm;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
Expand Up @@ -30,7 +30,7 @@
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/LowerAtomic.h"
#include "llvm/Transforms/Scalar/LowerAtomicPass.h"
#include "llvm/Transforms/Utils.h"
using namespace llvm;

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/CMakeLists.txt
Expand Up @@ -47,7 +47,7 @@ add_llvm_component_library(LLVMScalarOpts
LoopUnrollAndJamPass.cpp
LoopUnswitch.cpp
LoopVersioningLICM.cpp
LowerAtomic.cpp
LowerAtomicPass.cpp
LowerConstantIntrinsics.cpp
LowerExpectIntrinsic.cpp
LowerGuardIntrinsic.cpp
Expand Down
99 changes: 99 additions & 0 deletions llvm/lib/Transforms/Scalar/LowerAtomicPass.cpp
@@ -0,0 +1,99 @@
//===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This pass lowers atomic intrinsics to non-atomic form for use in a known
// non-preemptible environment.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/LowerAtomicPass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/LowerAtomic.h"
using namespace llvm;

#define DEBUG_TYPE "loweratomic"

static bool LowerFenceInst(FenceInst *FI) {
FI->eraseFromParent();
return true;
}

static bool LowerLoadInst(LoadInst *LI) {
LI->setAtomic(AtomicOrdering::NotAtomic);
return true;
}

static bool LowerStoreInst(StoreInst *SI) {
SI->setAtomic(AtomicOrdering::NotAtomic);
return true;
}

static bool runOnBasicBlock(BasicBlock &BB) {
bool Changed = false;
for (Instruction &Inst : make_early_inc_range(BB)) {
if (FenceInst *FI = dyn_cast<FenceInst>(&Inst))
Changed |= LowerFenceInst(FI);
else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&Inst))
Changed |= lowerAtomicCmpXchgInst(CXI);
else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&Inst))
Changed |= lowerAtomicRMWInst(RMWI);
else if (LoadInst *LI = dyn_cast<LoadInst>(&Inst)) {
if (LI->isAtomic())
LowerLoadInst(LI);
} else if (StoreInst *SI = dyn_cast<StoreInst>(&Inst)) {
if (SI->isAtomic())
LowerStoreInst(SI);
}
}
return Changed;
}

static bool lowerAtomics(Function &F) {
bool Changed = false;
for (BasicBlock &BB : F) {
Changed |= runOnBasicBlock(BB);
}
return Changed;
}

PreservedAnalyses LowerAtomicPass::run(Function &F, FunctionAnalysisManager &) {
if (lowerAtomics(F))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}

namespace {
class LowerAtomicLegacyPass : public FunctionPass {
public:
static char ID;

LowerAtomicLegacyPass() : FunctionPass(ID) {
initializeLowerAtomicLegacyPassPass(*PassRegistry::getPassRegistry());
}

bool runOnFunction(Function &F) override {
// Don't skip optnone functions; atomics still need to be lowered.
FunctionAnalysisManager DummyFAM;
auto PA = Impl.run(F, DummyFAM);
return !PA.areAllPreserved();
}

private:
LowerAtomicPass Impl;
};
}

char LowerAtomicLegacyPass::ID = 0;
INITIALIZE_PASS(LowerAtomicLegacyPass, "loweratomic",
"Lower atomic intrinsics to non-atomic form", false, false)

Pass *llvm::createLowerAtomicPass() { return new LowerAtomicLegacyPass(); }
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Utils/CMakeLists.txt
Expand Up @@ -44,6 +44,7 @@ add_llvm_component_library(LLVMTransformUtils
LoopUnrollRuntime.cpp
LoopUtils.cpp
LoopVersioning.cpp
LowerAtomic.cpp
LowerGlobalDtors.cpp
LowerInvoke.cpp
LowerMemIntrinsics.cpp
Expand Down
Expand Up @@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/LowerAtomic.h"
#include "llvm/Transforms/Utils/LowerAtomic.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/InitializePasses.h"
Expand All @@ -21,7 +21,7 @@ using namespace llvm;

#define DEBUG_TYPE "loweratomic"

static bool LowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) {
bool llvm::lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) {
IRBuilder<> Builder(CXI);
Value *Ptr = CXI->getPointerOperand();
Value *Cmp = CXI->getCompareOperand();
Expand Down Expand Up @@ -99,79 +99,3 @@ bool llvm::lowerAtomicRMWInst(AtomicRMWInst *RMWI) {
RMWI->eraseFromParent();
return true;
}

static bool LowerFenceInst(FenceInst *FI) {
FI->eraseFromParent();
return true;
}

static bool LowerLoadInst(LoadInst *LI) {
LI->setAtomic(AtomicOrdering::NotAtomic);
return true;
}

static bool LowerStoreInst(StoreInst *SI) {
SI->setAtomic(AtomicOrdering::NotAtomic);
return true;
}

static bool runOnBasicBlock(BasicBlock &BB) {
bool Changed = false;
for (Instruction &Inst : make_early_inc_range(BB)) {
if (FenceInst *FI = dyn_cast<FenceInst>(&Inst))
Changed |= LowerFenceInst(FI);
else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&Inst))
Changed |= LowerAtomicCmpXchgInst(CXI);
else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&Inst))
Changed |= lowerAtomicRMWInst(RMWI);
else if (LoadInst *LI = dyn_cast<LoadInst>(&Inst)) {
if (LI->isAtomic())
LowerLoadInst(LI);
} else if (StoreInst *SI = dyn_cast<StoreInst>(&Inst)) {
if (SI->isAtomic())
LowerStoreInst(SI);
}
}
return Changed;
}

static bool lowerAtomics(Function &F) {
bool Changed = false;
for (BasicBlock &BB : F) {
Changed |= runOnBasicBlock(BB);
}
return Changed;
}

PreservedAnalyses LowerAtomicPass::run(Function &F, FunctionAnalysisManager &) {
if (lowerAtomics(F))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}

namespace {
class LowerAtomicLegacyPass : public FunctionPass {
public:
static char ID;

LowerAtomicLegacyPass() : FunctionPass(ID) {
initializeLowerAtomicLegacyPassPass(*PassRegistry::getPassRegistry());
}

bool runOnFunction(Function &F) override {
// Don't skip optnone functions; atomics still need to be lowered.
FunctionAnalysisManager DummyFAM;
auto PA = Impl.run(F, DummyFAM);
return !PA.areAllPreserved();
}

private:
LowerAtomicPass Impl;
};
}

char LowerAtomicLegacyPass::ID = 0;
INITIALIZE_PASS(LowerAtomicLegacyPass, "loweratomic",
"Lower atomic intrinsics to non-atomic form", false, false)

Pass *llvm::createLowerAtomicPass() { return new LowerAtomicLegacyPass(); }

0 comments on commit 39f1568

Please sign in to comment.