|
88 | 88 | #include "llvm/IR/DerivedUser.h"
|
89 | 89 | #include "llvm/IR/Dominators.h"
|
90 | 90 | #include "llvm/IR/Module.h"
|
| 91 | +#include "llvm/IR/Operator.h" |
91 | 92 | #include "llvm/IR/Type.h"
|
92 | 93 | #include "llvm/IR/Use.h"
|
93 | 94 | #include "llvm/IR/User.h"
|
@@ -1217,27 +1218,61 @@ class upward_defs_iterator
|
1217 | 1218 | BasicBlock *getPhiArgBlock() const { return DefIterator.getPhiArgBlock(); }
|
1218 | 1219 |
|
1219 | 1220 | private:
|
| 1221 | + /// Returns true if \p Ptr is guaranteed to be loop invariant for any possible |
| 1222 | + /// loop. In particular, this guarantees that it only references a single |
| 1223 | + /// MemoryLocation during execution of the containing function. |
| 1224 | + bool IsGuaranteedLoopInvariant(Value *Ptr) const { |
| 1225 | + auto IsGuaranteedLoopInvariantBase = [](Value *Ptr) { |
| 1226 | + Ptr = Ptr->stripPointerCasts(); |
| 1227 | + if (auto *I = dyn_cast<Instruction>(Ptr)) { |
| 1228 | + if (isa<AllocaInst>(Ptr)) |
| 1229 | + return true; |
| 1230 | + return false; |
| 1231 | + } |
| 1232 | + return true; |
| 1233 | + }; |
| 1234 | + |
| 1235 | + Ptr = Ptr->stripPointerCasts(); |
| 1236 | + if (auto *GEP = dyn_cast<GEPOperator>(Ptr)) { |
| 1237 | + return IsGuaranteedLoopInvariantBase(GEP->getPointerOperand()) && |
| 1238 | + GEP->hasAllConstantIndices(); |
| 1239 | + } |
| 1240 | + return IsGuaranteedLoopInvariantBase(Ptr); |
| 1241 | + } |
| 1242 | + |
1220 | 1243 | void fillInCurrentPair() {
|
1221 | 1244 | CurrentPair.first = *DefIterator;
|
| 1245 | + CurrentPair.second = Location; |
1222 | 1246 | if (WalkingPhi && Location.Ptr) {
|
| 1247 | + // Mark size as unknown, if the location is not guaranteed to be |
| 1248 | + // loop-invariant for any possible loop in the function. Setting the size |
| 1249 | + // to unknown guarantees that any memory accesses that access locations |
| 1250 | + // after the pointer are considered as clobbers, which is important to |
| 1251 | + // catch loop carried dependences. |
| 1252 | + if (Location.Ptr && |
| 1253 | + !IsGuaranteedLoopInvariant(const_cast<Value *>(Location.Ptr))) |
| 1254 | + CurrentPair.second = Location.getWithNewSize(LocationSize::unknown()); |
1223 | 1255 | PHITransAddr Translator(
|
1224 | 1256 | const_cast<Value *>(Location.Ptr),
|
1225 | 1257 | OriginalAccess->getBlock()->getModule()->getDataLayout(), nullptr);
|
| 1258 | + |
1226 | 1259 | if (!Translator.PHITranslateValue(OriginalAccess->getBlock(),
|
1227 | 1260 | DefIterator.getPhiArgBlock(), DT,
|
1228 | 1261 | true)) {
|
1229 |
| - if (Translator.getAddr() != Location.Ptr) { |
1230 |
| - CurrentPair.second = Location.getWithNewPtr(Translator.getAddr()); |
| 1262 | + Value *TransAddr = Translator.getAddr(); |
| 1263 | + if (TransAddr != Location.Ptr) { |
| 1264 | + CurrentPair.second = CurrentPair.second.getWithNewPtr(TransAddr); |
| 1265 | + |
| 1266 | + if (TransAddr && |
| 1267 | + !IsGuaranteedLoopInvariant(const_cast<Value *>(TransAddr))) |
| 1268 | + CurrentPair.second = |
| 1269 | + CurrentPair.second.getWithNewSize(LocationSize::unknown()); |
| 1270 | + |
1231 | 1271 | if (PerformedPhiTranslation)
|
1232 | 1272 | *PerformedPhiTranslation = true;
|
1233 |
| - return; |
1234 | 1273 | }
|
1235 |
| - } else { |
1236 |
| - CurrentPair.second = Location.getWithNewSize(LocationSize::unknown()); |
1237 |
| - return; |
1238 | 1274 | }
|
1239 | 1275 | }
|
1240 |
| - CurrentPair.second = Location; |
1241 | 1276 | }
|
1242 | 1277 |
|
1243 | 1278 | MemoryAccessPair CurrentPair;
|
|
0 commit comments