Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Utils/LowerAtomic.cpp
35271 views
//===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This pass lowers atomic intrinsics to non-atomic form for use in a known9// non-preemptible environment.10//11//===----------------------------------------------------------------------===//1213#include "llvm/Transforms/Utils/LowerAtomic.h"14#include "llvm/IR/Function.h"15#include "llvm/IR/IRBuilder.h"1617using namespace llvm;1819#define DEBUG_TYPE "loweratomic"2021bool llvm::lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) {22IRBuilder<> Builder(CXI);23Value *Ptr = CXI->getPointerOperand();24Value *Cmp = CXI->getCompareOperand();25Value *Val = CXI->getNewValOperand();2627LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);28Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);29Value *Res = Builder.CreateSelect(Equal, Val, Orig);30Builder.CreateStore(Res, Ptr);3132Res = Builder.CreateInsertValue(PoisonValue::get(CXI->getType()), Orig, 0);33Res = Builder.CreateInsertValue(Res, Equal, 1);3435CXI->replaceAllUsesWith(Res);36CXI->eraseFromParent();37return true;38}3940Value *llvm::buildAtomicRMWValue(AtomicRMWInst::BinOp Op,41IRBuilderBase &Builder, Value *Loaded,42Value *Val) {43Value *NewVal;44switch (Op) {45case AtomicRMWInst::Xchg:46return Val;47case AtomicRMWInst::Add:48return Builder.CreateAdd(Loaded, Val, "new");49case AtomicRMWInst::Sub:50return Builder.CreateSub(Loaded, Val, "new");51case AtomicRMWInst::And:52return Builder.CreateAnd(Loaded, Val, "new");53case AtomicRMWInst::Nand:54return Builder.CreateNot(Builder.CreateAnd(Loaded, Val), "new");55case AtomicRMWInst::Or:56return Builder.CreateOr(Loaded, Val, "new");57case AtomicRMWInst::Xor:58return Builder.CreateXor(Loaded, Val, "new");59case AtomicRMWInst::Max:60NewVal = Builder.CreateICmpSGT(Loaded, Val);61return Builder.CreateSelect(NewVal, Loaded, Val, "new");62case AtomicRMWInst::Min:63NewVal = Builder.CreateICmpSLE(Loaded, Val);64return Builder.CreateSelect(NewVal, Loaded, Val, "new");65case AtomicRMWInst::UMax:66NewVal = Builder.CreateICmpUGT(Loaded, Val);67return Builder.CreateSelect(NewVal, Loaded, Val, "new");68case AtomicRMWInst::UMin:69NewVal = Builder.CreateICmpULE(Loaded, Val);70return Builder.CreateSelect(NewVal, Loaded, Val, "new");71case AtomicRMWInst::FAdd:72return Builder.CreateFAdd(Loaded, Val, "new");73case AtomicRMWInst::FSub:74return Builder.CreateFSub(Loaded, Val, "new");75case AtomicRMWInst::FMax:76return Builder.CreateMaxNum(Loaded, Val);77case AtomicRMWInst::FMin:78return Builder.CreateMinNum(Loaded, Val);79case AtomicRMWInst::UIncWrap: {80Constant *One = ConstantInt::get(Loaded->getType(), 1);81Value *Inc = Builder.CreateAdd(Loaded, One);82Value *Cmp = Builder.CreateICmpUGE(Loaded, Val);83Constant *Zero = ConstantInt::get(Loaded->getType(), 0);84return Builder.CreateSelect(Cmp, Zero, Inc, "new");85}86case AtomicRMWInst::UDecWrap: {87Constant *Zero = ConstantInt::get(Loaded->getType(), 0);88Constant *One = ConstantInt::get(Loaded->getType(), 1);8990Value *Dec = Builder.CreateSub(Loaded, One);91Value *CmpEq0 = Builder.CreateICmpEQ(Loaded, Zero);92Value *CmpOldGtVal = Builder.CreateICmpUGT(Loaded, Val);93Value *Or = Builder.CreateOr(CmpEq0, CmpOldGtVal);94return Builder.CreateSelect(Or, Val, Dec, "new");95}96default:97llvm_unreachable("Unknown atomic op");98}99}100101bool llvm::lowerAtomicRMWInst(AtomicRMWInst *RMWI) {102IRBuilder<> Builder(RMWI);103Builder.setIsFPConstrained(104RMWI->getFunction()->hasFnAttribute(Attribute::StrictFP));105106Value *Ptr = RMWI->getPointerOperand();107Value *Val = RMWI->getValOperand();108109LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);110Value *Res = buildAtomicRMWValue(RMWI->getOperation(), Builder, Orig, Val);111Builder.CreateStore(Res, Ptr);112RMWI->replaceAllUsesWith(Orig);113RMWI->eraseFromParent();114return true;115}116117118