diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Transforms/Utils/LowerAtomic.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'llvm/lib/Transforms/Utils/LowerAtomic.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/LowerAtomic.cpp | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/llvm/lib/Transforms/Utils/LowerAtomic.cpp b/llvm/lib/Transforms/Utils/LowerAtomic.cpp index 2247b8107739..b6f40de0daa6 100644 --- a/llvm/lib/Transforms/Utils/LowerAtomic.cpp +++ b/llvm/lib/Transforms/Utils/LowerAtomic.cpp @@ -41,43 +41,60 @@ bool llvm::lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) { Value *llvm::buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, - Value *Inc) { + Value *Val) { Value *NewVal; switch (Op) { case AtomicRMWInst::Xchg: - return Inc; + return Val; case AtomicRMWInst::Add: - return Builder.CreateAdd(Loaded, Inc, "new"); + return Builder.CreateAdd(Loaded, Val, "new"); case AtomicRMWInst::Sub: - return Builder.CreateSub(Loaded, Inc, "new"); + return Builder.CreateSub(Loaded, Val, "new"); case AtomicRMWInst::And: - return Builder.CreateAnd(Loaded, Inc, "new"); + return Builder.CreateAnd(Loaded, Val, "new"); case AtomicRMWInst::Nand: - return Builder.CreateNot(Builder.CreateAnd(Loaded, Inc), "new"); + return Builder.CreateNot(Builder.CreateAnd(Loaded, Val), "new"); case AtomicRMWInst::Or: - return Builder.CreateOr(Loaded, Inc, "new"); + return Builder.CreateOr(Loaded, Val, "new"); case AtomicRMWInst::Xor: - return Builder.CreateXor(Loaded, Inc, "new"); + return Builder.CreateXor(Loaded, Val, "new"); case AtomicRMWInst::Max: - NewVal = Builder.CreateICmpSGT(Loaded, Inc); - return Builder.CreateSelect(NewVal, Loaded, Inc, "new"); + NewVal = Builder.CreateICmpSGT(Loaded, Val); + return Builder.CreateSelect(NewVal, Loaded, Val, "new"); case AtomicRMWInst::Min: - NewVal = Builder.CreateICmpSLE(Loaded, Inc); - return Builder.CreateSelect(NewVal, Loaded, Inc, "new"); + NewVal = Builder.CreateICmpSLE(Loaded, Val); + return Builder.CreateSelect(NewVal, Loaded, Val, "new"); case AtomicRMWInst::UMax: - NewVal = Builder.CreateICmpUGT(Loaded, Inc); - return Builder.CreateSelect(NewVal, Loaded, Inc, "new"); + NewVal = Builder.CreateICmpUGT(Loaded, Val); + return Builder.CreateSelect(NewVal, Loaded, Val, "new"); case AtomicRMWInst::UMin: - NewVal = Builder.CreateICmpULE(Loaded, Inc); - return Builder.CreateSelect(NewVal, Loaded, Inc, "new"); + NewVal = Builder.CreateICmpULE(Loaded, Val); + return Builder.CreateSelect(NewVal, Loaded, Val, "new"); case AtomicRMWInst::FAdd: - return Builder.CreateFAdd(Loaded, Inc, "new"); + return Builder.CreateFAdd(Loaded, Val, "new"); case AtomicRMWInst::FSub: - return Builder.CreateFSub(Loaded, Inc, "new"); + return Builder.CreateFSub(Loaded, Val, "new"); case AtomicRMWInst::FMax: - return Builder.CreateMaxNum(Loaded, Inc); + return Builder.CreateMaxNum(Loaded, Val); case AtomicRMWInst::FMin: - return Builder.CreateMinNum(Loaded, Inc); + return Builder.CreateMinNum(Loaded, Val); + case AtomicRMWInst::UIncWrap: { + Constant *One = ConstantInt::get(Loaded->getType(), 1); + Value *Inc = Builder.CreateAdd(Loaded, One); + Value *Cmp = Builder.CreateICmpUGE(Loaded, Val); + Constant *Zero = ConstantInt::get(Loaded->getType(), 0); + return Builder.CreateSelect(Cmp, Zero, Inc, "new"); + } + case AtomicRMWInst::UDecWrap: { + Constant *Zero = ConstantInt::get(Loaded->getType(), 0); + Constant *One = ConstantInt::get(Loaded->getType(), 1); + + Value *Dec = Builder.CreateSub(Loaded, One); + Value *CmpEq0 = Builder.CreateICmpEQ(Loaded, Zero); + Value *CmpOldGtVal = Builder.CreateICmpUGT(Loaded, Val); + Value *Or = Builder.CreateOr(CmpEq0, CmpOldGtVal); + return Builder.CreateSelect(Or, Val, Dec, "new"); + } default: llvm_unreachable("Unknown atomic op"); } |