116 const mlir::DataLayout &dataLayout) {
117 LDBG() <<
"Decomposing pointer: " << val;
119 std::optional<int64_t> offset = 0;
122 mlir::Operation *defOp = val.getDefiningOp();
124 LDBG() <<
"No defining operation, stopping";
130 if (
auto castOp = mlir::dyn_cast<cir::CastOp>(defOp)) {
131 if (castOp.isAllocaPreservingCast() ||
132 castOp.getKind() == cir::CastKind::array_to_ptrdecay) {
133 LDBG() <<
"Walking past cast operation";
134 val = castOp.getSrc();
137 LDBG() <<
"Opaque cast operation, stopping";
142 if (
auto strideOp = mlir::dyn_cast<cir::PtrStrideOp>(defOp)) {
143 LDBG() <<
"Walking past PtrStrideOp";
148 val = strideOp.getBase();
153 if (
auto memberOp = mlir::dyn_cast<cir::GetMemberOp>(defOp)) {
154 LDBG() <<
"Walking past GetMemberOp";
156 mlir::cast<cir::RecordType>(memberOp.getAddrTy().getPointee());
157 std::optional<int64_t> memberOffset;
158 if (!recordTy.isIncomplete())
160 recordTy.getElementOffset(dataLayout, memberOp.getIndex());
162 val = memberOp.getAddr();
167 if (
auto elementOp = mlir::dyn_cast<cir::GetElementOp>(defOp)) {
168 LDBG() <<
"Walking past GetElementOp";
173 val = elementOp.getBase();
181 if (
auto baseOp = mlir::dyn_cast<cir::BaseClassAddrOp>(defOp)) {
182 LDBG() <<
"Walking past BaseClassAddrOp";
183 addToOffset(offset, baseOp.getOffset().tryZExtValue());
184 val = baseOp.getDerivedAddr();
192 if (
auto derivedOp = mlir::dyn_cast<cir::DerivedClassAddrOp>(defOp)) {
193 LDBG() <<
"Walking past DerivedClassAddrOp";
194 std::optional<int64_t> baseOffset = derivedOp.getOffset().tryZExtValue();
196 baseOffset = -*baseOffset;
198 val = derivedOp.getBaseAddr();
204 if (
auto realOp = mlir::dyn_cast<cir::ComplexRealPtrOp>(defOp)) {
205 LDBG() <<
"Walking past ComplexRealPtrOp";
206 val = realOp.getOperand();
209 if (
auto imagOp = mlir::dyn_cast<cir::ComplexImagPtrOp>(defOp)) {
210 LDBG() <<
"Walking past ComplexImagPtrOp";
211 auto ptrTy = mlir::cast<cir::PointerType>(imagOp.getOperand().getType());
212 auto complexTy = mlir::cast<cir::ComplexType>(ptrTy.getPointee());
215 val = imagOp.getOperand();
219 LDBG() <<
"Unhandled operation, stopping";
223 return {val, offset};
243 LDBG() <<
"Checking alias between: " << lhs <<
" and " << rhs;
246 LDBG() <<
"Trivial alias between identical values";
247 return mlir::AliasResult::MustAlias;
253 if (lhsPtr.base != rhsPtr.base) {
255 LDBG() <<
"No alias between pointers into distinct objects";
256 return mlir::AliasResult::NoAlias;
258 LDBG() <<
"Unrelated base objects, may alias";
259 return mlir::AliasResult::MayAlias;
264 if (!lhsPtr.offset || !rhsPtr.offset) {
265 LDBG() <<
"Same object at an unknown offset, may alias";
266 return mlir::AliasResult::MayAlias;
271 if (*lhsPtr.offset == *rhsPtr.offset) {
272 LDBG() <<
"Must alias at the same address within the same object";
273 return mlir::AliasResult::MustAlias;
279 LDBG() <<
"Same object at different offsets, may alias";
280 return mlir::AliasResult::MayAlias;
284 mlir::Value location) {
285 LDBG() <<
"getModRef: "
286 << mlir::OpWithFlags(op, mlir::OpPrintingFlags().skipRegions())
287 <<
" on location " << location;
289 auto effects = mlir::dyn_cast<mlir::MemoryEffectOpInterface>(op);
291 LDBG() <<
"No memory effect interface, returning ModAndRef";
292 return mlir::ModRefResult::getModAndRef();
296 effects.getEffects(effectList);
298 auto classifyEffect = [location,
this](
299 const mlir::MemoryEffects::EffectInstance &effect) {
300 if (mlir::isa<mlir::MemoryEffects::Allocate>(effect.getEffect())) {
301 LDBG() <<
"Skipping allocate effect";
302 return mlir::ModRefResult::getNoModRef();
305 mlir::AliasResult aliasResult = mlir::AliasResult::MayAlias;
306 if (mlir::Value affectedLocation = effect.getValue()) {
307 LDBG() <<
" Checking alias between affected location "
308 << affectedLocation <<
" and query location " << location;
309 aliasResult =
alias(affectedLocation, location);
310 LDBG() <<
" Alias result: " << aliasResult;
314 if (!effect.getResource()->isAddressable()) {
315 LDBG() <<
" Effect on non-addressable resource '"
316 << effect.getResource()->getName() <<
"', skipping (NoAlias)";
317 aliasResult = mlir::AliasResult::NoAlias;
319 LDBG() <<
" No effect value, assuming MayAlias";
325 if (aliasResult.isNo()) {
326 LDBG() <<
"No alias with affected location";
327 return mlir::ModRefResult::getNoModRef();
331 if (mlir::isa<mlir::MemoryEffects::Free>(effect.getEffect())) {
332 LDBG() <<
"Skipping free effect";
333 return mlir::ModRefResult::getModAndRef();
336 if (mlir::isa<mlir::MemoryEffects::Write>(effect.getEffect())) {
337 LDBG() <<
"Write effect, adding Mod";
338 return mlir::ModRefResult::getMod();
341 if (mlir::isa<mlir::MemoryEffects::Read>(effect.getEffect())) {
342 LDBG() <<
"Read effect, adding Ref";
343 return mlir::ModRefResult::getRef();
346 LDBG() <<
"Unexpected memory effect: " << effect.getEffect();
347 return mlir::ModRefResult::getNoModRef();
350 return llvm::accumulate(llvm::map_range(effectList, classifyEffect),
351 mlir::ModRefResult::getNoModRef(),
352 [](mlir::ModRefResult lhs, mlir::ModRefResult rhs) {
353 return lhs.merge(rhs);
static void addToOffset(std::optional< int64_t > &offset, std::optional< int64_t > delta)
Add delta bytes to offset, making the offset unknown if delta is unknown or if the sum overflows.
static std::optional< int64_t > getTypeSizeInBytes(mlir::Type type, const mlir::DataLayout &dataLayout)
Return the size in bytes of type, or std::nullopt when that size isn't statically known (void,...
static std::optional< int64_t > scaleOffset(std::optional< int64_t > count, std::optional< int64_t > size)
Return count * size, or std::nullopt if either input is unknown or the product overflows.
static PointerOffset decomposePointer(mlir::Value val, const mlir::DataLayout &dataLayout)
Trace val back to the object it points into, accumulating the byte offset of val from the start of th...