aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/LowerAtomic.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Transforms/Utils/LowerAtomic.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'llvm/lib/Transforms/Utils/LowerAtomic.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/LowerAtomic.cpp57
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");
}