clang 24.0.0git
CIRBasicAliasAnalysis.cpp
Go to the documentation of this file.
1//===- CIRBasicAliasAnalysis.cpp - Basic CIR Alias Analysis ---------------===//
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
10#include "mlir/Interfaces/SideEffectInterfaces.h"
12#include "llvm/Support/DebugLog.h"
13
14#define DEBUG_TYPE "cir-basic-alias-analysis"
15
16using namespace llvm;
17using namespace cir;
18
19//===----------------------------------------------------------------------===//
20// Helpers
21//===----------------------------------------------------------------------===//
22
23mlir::Value CIRBasicAliasAnalysis::getUnderlyingObject(mlir::Value val) {
24 LDBG() << "Getting underlying object for: " << val;
25
26 // TODO: Walk through cir.ptr_stride, cir.cast, cir.get_member, etc.
27 // to find the root allocation (cir.alloca, cir.global_addr, function args).
28 LDBG() << "Not yet implemented";
29 return val;
30}
31
32bool CIRBasicAliasAnalysis::areDistinctObjects(mlir::Value lhs,
33 mlir::Value rhs) {
34 LDBG() << "Checking if " << lhs << " and " << rhs << " are distinct objects";
35
36 // Two values are distinct allocations if they originate from different
37 // cir.alloca operations (or other allocation ops) in the same function.
38 // TODO: Extend to cover global addresses, function arguments with noalias,
39 // and heap allocations.
40 mlir::Value lhsObj = getUnderlyingObject(lhs);
41 mlir::Value rhsObj = getUnderlyingObject(rhs);
42
43 if (lhsObj == rhsObj) {
44 LDBG() << "Identical values, not distinct";
45 return false;
46 }
47
48 // Different cir.alloca ops in the same function cannot alias.
49 if (mlir::isa_and_nonnull<cir::AllocaOp>(lhsObj.getDefiningOp()) &&
50 mlir::isa_and_nonnull<cir::AllocaOp>(rhsObj.getDefiningOp())) {
51 LDBG() << "Different cir.alloca ops in the same function, distinct";
52 return true;
53 }
54
55 LDBG() << "Conservative fallback, not distinct";
56 return false;
57}
58
59//===----------------------------------------------------------------------===//
60// CIRBasicAliasAnalysis
61//===----------------------------------------------------------------------===//
62
63mlir::AliasResult CIRBasicAliasAnalysis::alias(mlir::Value lhs,
64 mlir::Value rhs) {
65 LDBG() << "Checking alias between: " << lhs << " and " << rhs;
66
67 if (lhs == rhs) {
68 LDBG() << "Trivial alias between identical values";
69 return mlir::AliasResult::MustAlias;
70 }
71
72 if (areDistinctObjects(lhs, rhs)) {
73 LDBG() << "No alias between distinct objects";
74 return mlir::AliasResult::NoAlias;
75 }
76
77 // Conservative fallback — the aggregate will try other implementations.
78 LDBG() << "Conservative fallback, may alias";
79 return mlir::AliasResult::MayAlias;
80}
81
82mlir::ModRefResult CIRBasicAliasAnalysis::getModRef(mlir::Operation *op,
83 mlir::Value location) {
84 LDBG() << "getModRef: "
85 << mlir::OpWithFlags(op, mlir::OpPrintingFlags().skipRegions())
86 << " on location " << location;
87
88 auto effects = mlir::dyn_cast<mlir::MemoryEffectOpInterface>(op);
89 if (!effects) {
90 LDBG() << "No memory effect interface, returning ModAndRef";
91 return mlir::ModRefResult::getModAndRef();
92 }
93
95 effects.getEffects(effectList);
96
97 auto classifyEffect = [location, this](
98 const mlir::MemoryEffects::EffectInstance &effect) {
99 if (mlir::isa<mlir::MemoryEffects::Allocate>(effect.getEffect())) {
100 LDBG() << "Skipping allocate effect";
101 return mlir::ModRefResult::getNoModRef();
102 }
103
104 mlir::AliasResult aliasResult = mlir::AliasResult::MayAlias;
105 if (mlir::Value affectedLocation = effect.getValue()) {
106 LDBG() << " Checking alias between affected location "
107 << affectedLocation << " and query location " << location;
108 aliasResult = alias(affectedLocation, location);
109 LDBG() << " Alias result: "
110 << (aliasResult.isMust() ? "MustAlias"
111 : aliasResult.isNo() ? "NoAlias"
112 : "MayAlias");
113 } else {
114 // An effect on a non-addressable resource cannot affect a
115 // pointer-based location.
116 if (!effect.getResource()->isAddressable()) {
117 LDBG() << " Effect on non-addressable resource '"
118 << effect.getResource()->getName() << "', skipping (NoAlias)";
119 aliasResult = mlir::AliasResult::NoAlias;
120 } else {
121 LDBG() << " No effect value, assuming MayAlias";
122 }
123 }
124
125 // If the affected location doesn't alias with the query location,
126 // ignore this effect.
127 if (aliasResult.isNo()) {
128 LDBG() << "No alias with affected location";
129 return mlir::ModRefResult::getNoModRef();
130 }
131
132 // TODO: Consider whether Free should be NoModRef.
133 if (mlir::isa<mlir::MemoryEffects::Free>(effect.getEffect())) {
134 LDBG() << "Skipping free effect";
135 return mlir::ModRefResult::getModAndRef();
136 }
137
138 if (mlir::isa<mlir::MemoryEffects::Write>(effect.getEffect())) {
139 LDBG() << "Write effect, adding Mod";
140 return mlir::ModRefResult::getMod();
141 }
142
143 if (mlir::isa<mlir::MemoryEffects::Read>(effect.getEffect())) {
144 LDBG() << "Read effect, adding Ref";
145 return mlir::ModRefResult::getRef();
146 }
147
148 LDBG() << "Unexpected memory effect: " << effect.getEffect();
149 return mlir::ModRefResult::getNoModRef();
150 };
151
152 return llvm::accumulate(llvm::map_range(effectList, classifyEffect),
153 mlir::ModRefResult::getNoModRef(),
154 [](mlir::ModRefResult lhs, mlir::ModRefResult rhs) {
155 return lhs.merge(rhs);
156 });
157}
mlir::ModRefResult getModRef(mlir::Operation *op, mlir::Value location)
Return the modify-reference behavior of op on location.
mlir::AliasResult alias(mlir::Value lhs, mlir::Value rhs)
Return the aliasing behavior between two values.
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30