1 //===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This pass lowers atomic intrinsics to non-atomic form for use in a known
10 // non-preemptible environment.
12 //===----------------------------------------------------------------------===//
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"
21 #define DEBUG_TYPE "loweratomic"
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();
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
);
34 Res
= Builder
.CreateInsertValue(PoisonValue::get(CXI
->getType()), Orig
, 0);
35 Res
= Builder
.CreateInsertValue(Res
, Equal
, 1);
37 CXI
->replaceAllUsesWith(Res
);
38 CXI
->eraseFromParent();
42 Value
*llvm::buildAtomicRMWValue(AtomicRMWInst::BinOp Op
,
43 IRBuilderBase
&Builder
, Value
*Loaded
,
47 case AtomicRMWInst::Xchg
:
49 case AtomicRMWInst::Add
:
50 return Builder
.CreateAdd(Loaded
, Inc
, "new");
51 case AtomicRMWInst::Sub
:
52 return Builder
.CreateSub(Loaded
, Inc
, "new");
53 case AtomicRMWInst::And
:
54 return Builder
.CreateAnd(Loaded
, Inc
, "new");
55 case AtomicRMWInst::Nand
:
56 return Builder
.CreateNot(Builder
.CreateAnd(Loaded
, Inc
), "new");
57 case AtomicRMWInst::Or
:
58 return Builder
.CreateOr(Loaded
, Inc
, "new");
59 case AtomicRMWInst::Xor
:
60 return Builder
.CreateXor(Loaded
, Inc
, "new");
61 case AtomicRMWInst::Max
:
62 NewVal
= Builder
.CreateICmpSGT(Loaded
, Inc
);
63 return Builder
.CreateSelect(NewVal
, Loaded
, Inc
, "new");
64 case AtomicRMWInst::Min
:
65 NewVal
= Builder
.CreateICmpSLE(Loaded
, Inc
);
66 return Builder
.CreateSelect(NewVal
, Loaded
, Inc
, "new");
67 case AtomicRMWInst::UMax
:
68 NewVal
= Builder
.CreateICmpUGT(Loaded
, Inc
);
69 return Builder
.CreateSelect(NewVal
, Loaded
, Inc
, "new");
70 case AtomicRMWInst::UMin
:
71 NewVal
= Builder
.CreateICmpULE(Loaded
, Inc
);
72 return Builder
.CreateSelect(NewVal
, Loaded
, Inc
, "new");
73 case AtomicRMWInst::FAdd
:
74 return Builder
.CreateFAdd(Loaded
, Inc
, "new");
75 case AtomicRMWInst::FSub
:
76 return Builder
.CreateFSub(Loaded
, Inc
, "new");
77 case AtomicRMWInst::FMax
:
78 return Builder
.CreateMaxNum(Loaded
, Inc
);
79 case AtomicRMWInst::FMin
:
80 return Builder
.CreateMinNum(Loaded
, Inc
);
82 llvm_unreachable("Unknown atomic op");
86 bool llvm::lowerAtomicRMWInst(AtomicRMWInst
*RMWI
) {
87 IRBuilder
<> Builder(RMWI
);
88 Value
*Ptr
= RMWI
->getPointerOperand();
89 Value
*Val
= RMWI
->getValOperand();
91 LoadInst
*Orig
= Builder
.CreateLoad(Val
->getType(), Ptr
);
92 Value
*Res
= buildAtomicRMWValue(RMWI
->getOperation(), Builder
, Orig
, Val
);
93 Builder
.CreateStore(Res
, Ptr
);
94 RMWI
->replaceAllUsesWith(Orig
);
95 RMWI
->eraseFromParent();