1 //===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This pass lowers atomic intrinsics to non-atomic form for use in a known 10 // non-preemptible environment. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Transforms/Utils/LowerAtomic.h" 15 #include "llvm/IR/Function.h" 16 #include "llvm/IR/IRBuilder.h" 17 #include "llvm/InitializePasses.h" 18 #include "llvm/Pass.h" 19 using namespace llvm; 20 21 #define DEBUG_TYPE "loweratomic" 22 23 bool llvm::lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) { 24 IRBuilder<> Builder(CXI); 25 Value *Ptr = CXI->getPointerOperand(); 26 Value *Cmp = CXI->getCompareOperand(); 27 Value *Val = CXI->getNewValOperand(); 28 29 LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr); 30 Value *Equal = Builder.CreateICmpEQ(Orig, Cmp); 31 Value *Res = Builder.CreateSelect(Equal, Val, Orig); 32 Builder.CreateStore(Res, Ptr); 33 34 Res = Builder.CreateInsertValue(UndefValue::get(CXI->getType()), Orig, 0); 35 Res = Builder.CreateInsertValue(Res, Equal, 1); 36 37 CXI->replaceAllUsesWith(Res); 38 CXI->eraseFromParent(); 39 return true; 40 } 41 42 bool llvm::lowerAtomicRMWInst(AtomicRMWInst *RMWI) { 43 IRBuilder<> Builder(RMWI); 44 Value *Ptr = RMWI->getPointerOperand(); 45 Value *Val = RMWI->getValOperand(); 46 47 LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr); 48 Value *Res = nullptr; 49 50 switch (RMWI->getOperation()) { 51 default: llvm_unreachable("Unexpected RMW operation"); 52 case AtomicRMWInst::Xchg: 53 Res = Val; 54 break; 55 case AtomicRMWInst::Add: 56 Res = Builder.CreateAdd(Orig, Val); 57 break; 58 case AtomicRMWInst::Sub: 59 Res = Builder.CreateSub(Orig, Val); 60 break; 61 case AtomicRMWInst::And: 62 Res = Builder.CreateAnd(Orig, Val); 63 break; 64 case AtomicRMWInst::Nand: 65 Res = Builder.CreateNot(Builder.CreateAnd(Orig, Val)); 66 break; 67 case AtomicRMWInst::Or: 68 Res = Builder.CreateOr(Orig, Val); 69 break; 70 case AtomicRMWInst::Xor: 71 Res = Builder.CreateXor(Orig, Val); 72 break; 73 case AtomicRMWInst::Max: 74 Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val), 75 Val, Orig); 76 break; 77 case AtomicRMWInst::Min: 78 Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val), 79 Orig, Val); 80 break; 81 case AtomicRMWInst::UMax: 82 Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val), 83 Val, Orig); 84 break; 85 case AtomicRMWInst::UMin: 86 Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val), 87 Orig, Val); 88 break; 89 case AtomicRMWInst::FAdd: 90 Res = Builder.CreateFAdd(Orig, Val); 91 break; 92 case AtomicRMWInst::FSub: 93 Res = Builder.CreateFSub(Orig, Val); 94 break; 95 } 96 Builder.CreateStore(Res, Ptr); 97 RMWI->replaceAllUsesWith(Orig); 98 RMWI->eraseFromParent(); 99 return true; 100 } 101