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"
20 #define DEBUG_TYPE "loweratomic"
22 bool llvm::lowerAtomicCmpXchgInst(AtomicCmpXchgInst
*CXI
) {
23 IRBuilder
<> Builder(CXI
);
24 Value
*Ptr
= CXI
->getPointerOperand();
25 Value
*Cmp
= CXI
->getCompareOperand();
26 Value
*Val
= CXI
->getNewValOperand();
28 LoadInst
*Orig
= Builder
.CreateLoad(Val
->getType(), Ptr
);
29 Value
*Equal
= Builder
.CreateICmpEQ(Orig
, Cmp
);
30 Value
*Res
= Builder
.CreateSelect(Equal
, Val
, Orig
);
31 Builder
.CreateStore(Res
, Ptr
);
33 Res
= Builder
.CreateInsertValue(PoisonValue::get(CXI
->getType()), Orig
, 0);
34 Res
= Builder
.CreateInsertValue(Res
, Equal
, 1);
36 CXI
->replaceAllUsesWith(Res
);
37 CXI
->eraseFromParent();
41 Value
*llvm::buildAtomicRMWValue(AtomicRMWInst::BinOp Op
,
42 IRBuilderBase
&Builder
, Value
*Loaded
,
46 case AtomicRMWInst::Xchg
:
48 case AtomicRMWInst::Add
:
49 return Builder
.CreateAdd(Loaded
, Val
, "new");
50 case AtomicRMWInst::Sub
:
51 return Builder
.CreateSub(Loaded
, Val
, "new");
52 case AtomicRMWInst::And
:
53 return Builder
.CreateAnd(Loaded
, Val
, "new");
54 case AtomicRMWInst::Nand
:
55 return Builder
.CreateNot(Builder
.CreateAnd(Loaded
, Val
), "new");
56 case AtomicRMWInst::Or
:
57 return Builder
.CreateOr(Loaded
, Val
, "new");
58 case AtomicRMWInst::Xor
:
59 return Builder
.CreateXor(Loaded
, Val
, "new");
60 case AtomicRMWInst::Max
:
61 NewVal
= Builder
.CreateICmpSGT(Loaded
, Val
);
62 return Builder
.CreateSelect(NewVal
, Loaded
, Val
, "new");
63 case AtomicRMWInst::Min
:
64 NewVal
= Builder
.CreateICmpSLE(Loaded
, Val
);
65 return Builder
.CreateSelect(NewVal
, Loaded
, Val
, "new");
66 case AtomicRMWInst::UMax
:
67 NewVal
= Builder
.CreateICmpUGT(Loaded
, Val
);
68 return Builder
.CreateSelect(NewVal
, Loaded
, Val
, "new");
69 case AtomicRMWInst::UMin
:
70 NewVal
= Builder
.CreateICmpULE(Loaded
, Val
);
71 return Builder
.CreateSelect(NewVal
, Loaded
, Val
, "new");
72 case AtomicRMWInst::FAdd
:
73 return Builder
.CreateFAdd(Loaded
, Val
, "new");
74 case AtomicRMWInst::FSub
:
75 return Builder
.CreateFSub(Loaded
, Val
, "new");
76 case AtomicRMWInst::FMax
:
77 return Builder
.CreateMaxNum(Loaded
, Val
);
78 case AtomicRMWInst::FMin
:
79 return Builder
.CreateMinNum(Loaded
, Val
);
80 case AtomicRMWInst::UIncWrap
: {
81 Constant
*One
= ConstantInt::get(Loaded
->getType(), 1);
82 Value
*Inc
= Builder
.CreateAdd(Loaded
, One
);
83 Value
*Cmp
= Builder
.CreateICmpUGE(Loaded
, Val
);
84 Constant
*Zero
= ConstantInt::get(Loaded
->getType(), 0);
85 return Builder
.CreateSelect(Cmp
, Zero
, Inc
, "new");
87 case AtomicRMWInst::UDecWrap
: {
88 Constant
*Zero
= ConstantInt::get(Loaded
->getType(), 0);
89 Constant
*One
= ConstantInt::get(Loaded
->getType(), 1);
91 Value
*Dec
= Builder
.CreateSub(Loaded
, One
);
92 Value
*CmpEq0
= Builder
.CreateICmpEQ(Loaded
, Zero
);
93 Value
*CmpOldGtVal
= Builder
.CreateICmpUGT(Loaded
, Val
);
94 Value
*Or
= Builder
.CreateOr(CmpEq0
, CmpOldGtVal
);
95 return Builder
.CreateSelect(Or
, Val
, Dec
, "new");
98 llvm_unreachable("Unknown atomic op");
102 bool llvm::lowerAtomicRMWInst(AtomicRMWInst
*RMWI
) {
103 IRBuilder
<> Builder(RMWI
);
104 Builder
.setIsFPConstrained(
105 RMWI
->getFunction()->hasFnAttribute(Attribute::StrictFP
));
107 Value
*Ptr
= RMWI
->getPointerOperand();
108 Value
*Val
= RMWI
->getValOperand();
110 LoadInst
*Orig
= Builder
.CreateLoad(Val
->getType(), Ptr
);
111 Value
*Res
= buildAtomicRMWValue(RMWI
->getOperation(), Builder
, Orig
, Val
);
112 Builder
.CreateStore(Res
, Ptr
);
113 RMWI
->replaceAllUsesWith(Orig
);
114 RMWI
->eraseFromParent();