brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.9 KiB · 613b434 Raw
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