95 lines · cpp
1//===----- RISCVZacasABIFix.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This pass implements a fence insertion for an atomic cmpxchg in a case that10// isn't easy to do with the current AtomicExpandPass hooks API.11//12//===----------------------------------------------------------------------===//13 14#include "RISCV.h"15#include "RISCVTargetMachine.h"16#include "llvm/ADT/Statistic.h"17#include "llvm/Analysis/ValueTracking.h"18#include "llvm/CodeGen/TargetPassConfig.h"19#include "llvm/IR/Dominators.h"20#include "llvm/IR/IRBuilder.h"21#include "llvm/IR/InstVisitor.h"22#include "llvm/IR/Intrinsics.h"23#include "llvm/InitializePasses.h"24#include "llvm/Pass.h"25 26using namespace llvm;27 28#define DEBUG_TYPE "riscv-zacas-abi-fix"29#define PASS_NAME "RISC-V Zacas ABI fix"30 31namespace {32 33class RISCVZacasABIFix : public FunctionPass,34 public InstVisitor<RISCVZacasABIFix, bool> {35 const RISCVSubtarget *ST;36 37public:38 static char ID;39 40 RISCVZacasABIFix() : FunctionPass(ID) {}41 42 bool runOnFunction(Function &F) override;43 44 StringRef getPassName() const override { return PASS_NAME; }45 46 void getAnalysisUsage(AnalysisUsage &AU) const override {47 AU.setPreservesCFG();48 AU.addRequired<TargetPassConfig>();49 }50 51 bool visitInstruction(Instruction &I) { return false; }52 bool visitAtomicCmpXchgInst(AtomicCmpXchgInst &I);53};54 55} // end anonymous namespace56 57// Insert a leading fence (needed for broadest atomics ABI compatibility)58// only if the Zacas extension is enabled and the AtomicCmpXchgInst has a59// SequentiallyConsistent failure ordering.60bool RISCVZacasABIFix::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {61 assert(ST->hasStdExtZacas() && "only necessary to run in presence of zacas");62 IRBuilder<> Builder(&I);63 if (I.getFailureOrdering() != AtomicOrdering::SequentiallyConsistent)64 return false;65 66 Builder.CreateFence(AtomicOrdering::SequentiallyConsistent);67 return true;68}69 70bool RISCVZacasABIFix::runOnFunction(Function &F) {71 auto &TPC = getAnalysis<TargetPassConfig>();72 auto &TM = TPC.getTM<RISCVTargetMachine>();73 ST = &TM.getSubtarget<RISCVSubtarget>(F);74 75 if (skipFunction(F) || !ST->hasStdExtZacas())76 return false;77 78 bool MadeChange = false;79 for (auto &BB : F)80 for (Instruction &I : llvm::make_early_inc_range(BB))81 MadeChange |= visit(I);82 83 return MadeChange;84}85 86INITIALIZE_PASS_BEGIN(RISCVZacasABIFix, DEBUG_TYPE, PASS_NAME, false, false)87INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)88INITIALIZE_PASS_END(RISCVZacasABIFix, DEBUG_TYPE, PASS_NAME, false, false)89 90char RISCVZacasABIFix::ID = 0;91 92FunctionPass *llvm::createRISCVZacasABIFixPass() {93 return new RISCVZacasABIFix();94}95