1//===- ReduceOpcodes.cpp - Specialized Delta Pass -------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "ReduceMemoryOperations.h"
10#include "llvm/IR/InstIterator.h"
11#include "llvm/IR/Instructions.h"
12#include "llvm/IR/IntrinsicInst.h"
13
14using namespace llvm;
15
16static void removeVolatileInFunction(Oracle &O, Function &F) {
17 LLVMContext &Ctx = F.getContext();
18 for (Instruction &I : instructions(F)) {
19 if (LoadInst *LI = dyn_cast<LoadInst>(Val: &I)) {
20 if (LI->isVolatile() && !O.shouldKeep())
21 LI->setVolatile(false);
22 } else if (StoreInst *SI = dyn_cast<StoreInst>(Val: &I)) {
23 if (SI->isVolatile() && !O.shouldKeep())
24 SI->setVolatile(false);
25 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(Val: &I)) {
26 if (RMW->isVolatile() && !O.shouldKeep())
27 RMW->setVolatile(false);
28 } else if (AtomicCmpXchgInst *CmpXChg = dyn_cast<AtomicCmpXchgInst>(Val: &I)) {
29 if (CmpXChg->isVolatile() && !O.shouldKeep())
30 CmpXChg->setVolatile(false);
31 } else if (MemIntrinsic *MemIntrin = dyn_cast<MemIntrinsic>(Val: &I)) {
32 if (MemIntrin->isVolatile() && !O.shouldKeep())
33 MemIntrin->setVolatile(ConstantInt::getFalse(Context&: Ctx));
34 }
35 }
36}
37
38void llvm::reduceVolatileInstructionsDeltaPass(Oracle &O,
39 ReducerWorkItem &WorkItem) {
40 for (Function &F : WorkItem.getModule())
41 removeVolatileInFunction(O, F);
42}
43
44static void reduceAtomicSyncScopesInFunction(Oracle &O, Function &F) {
45 for (Instruction &I : instructions(F)) {
46 if (LoadInst *LI = dyn_cast<LoadInst>(Val: &I)) {
47 if (LI->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
48 LI->setSyncScopeID(SyncScope::System);
49 } else if (StoreInst *SI = dyn_cast<StoreInst>(Val: &I)) {
50 if (SI->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
51 SI->setSyncScopeID(SyncScope::System);
52 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(Val: &I)) {
53 if (RMW->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
54 RMW->setSyncScopeID(SyncScope::System);
55 } else if (AtomicCmpXchgInst *CmpXChg = dyn_cast<AtomicCmpXchgInst>(Val: &I)) {
56 if (CmpXChg->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
57 CmpXChg->setSyncScopeID(SyncScope::System);
58 } else if (FenceInst *Fence = dyn_cast<FenceInst>(Val: &I)) {
59 if (Fence->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
60 Fence->setSyncScopeID(SyncScope::System);
61 }
62 }
63}
64
65void llvm::reduceAtomicSyncScopesDeltaPass(Oracle &O,
66 ReducerWorkItem &WorkItem) {
67 for (Function &F : WorkItem.getModule())
68 reduceAtomicSyncScopesInFunction(O, F);
69}
70
71// TODO: Might be helpful to incrementally relax orders
72static void reduceAtomicOrderingInFunction(Oracle &O, Function &F) {
73 for (Instruction &I : instructions(F)) {
74 if (LoadInst *LI = dyn_cast<LoadInst>(Val: &I)) {
75 if (LI->getOrdering() != AtomicOrdering::NotAtomic && !O.shouldKeep())
76 LI->setAtomic(Ordering: AtomicOrdering::NotAtomic);
77 } else if (StoreInst *SI = dyn_cast<StoreInst>(Val: &I)) {
78 if (SI->getOrdering() != AtomicOrdering::NotAtomic && !O.shouldKeep())
79 SI->setAtomic(Ordering: AtomicOrdering::NotAtomic);
80 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(Val: &I)) {
81 if (RMW->getOrdering() != AtomicOrdering::Monotonic && !O.shouldKeep())
82 RMW->setOrdering(AtomicOrdering::Monotonic);
83 } else if (AtomicCmpXchgInst *CmpXChg = dyn_cast<AtomicCmpXchgInst>(Val: &I)) {
84 if (CmpXChg->getSuccessOrdering() != AtomicOrdering::Monotonic &&
85 !O.shouldKeep())
86 CmpXChg->setSuccessOrdering(AtomicOrdering::Monotonic);
87 if (CmpXChg->getFailureOrdering() != AtomicOrdering::Monotonic &&
88 !O.shouldKeep())
89 CmpXChg->setFailureOrdering(AtomicOrdering::Monotonic);
90 }
91 }
92}
93
94void llvm::reduceAtomicOrderingDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {
95 for (Function &F : WorkItem.getModule())
96 reduceAtomicOrderingInFunction(O, F);
97}
98