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