MLIR: lib/Analysis/AliasAnalysis/LocalAliasAnalysis.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

10

25 #include "llvm/Support/Casting.h"

26 #include

27 #include

28 #include

29

30 using namespace mlir;

31

32

33

34

35

36

37

39

40

44

45

46

47

48

51 unsigned inputIndex,

52 unsigned maxDepth,

55

56

57

58

59 auto getOperandIndexIfPred =

62 branch.getSuccessorRegions(pred, successors);

64 if (successor.getSuccessor() != region)

65 continue;

66

67 ValueRange inputs = successor.getSuccessorInputs();

68 if (inputs.empty()) {

69 output.push_back(inputValue);

70 break;

71 }

72 unsigned firstInputIndex, lastInputIndex;

73 if (region) {

74 firstInputIndex = cast(inputs[0]).getArgNumber();

75 lastInputIndex = cast(inputs.back()).getArgNumber();

76 } else {

77 firstInputIndex = cast(inputs[0]).getResultNumber();

78 lastInputIndex = cast(inputs.back()).getResultNumber();

79 }

80 if (firstInputIndex > inputIndex || lastInputIndex < inputIndex) {

81 output.push_back(inputValue);

82 break;

83 }

84 return inputIndex - firstInputIndex;

85 }

86 return std::nullopt;

87 };

88

89

91 if (region)

92 branchPoint = region;

93

94 if (std::optional operandIndex =

97 branch.getEntrySuccessorOperands(branchPoint)[*operandIndex], maxDepth,

98 visited, output);

99 }

100

101 Operation *op = branch.getOperation();

103 if (std::optional operandIndex = getOperandIndexIfPred(region)) {

104 for (Block &block : region) {

105

106

107 if (auto term = dyn_cast(

108 block.getTerminator())) {

110 term.getSuccessorOperands(branchPoint)[*operandIndex], maxDepth,

111 visited, output);

112 } else if (block.getNumSuccessors()) {

113

114

115 output.push_back(inputValue);

116 return;

117 }

118 }

119 }

120 }

121 }

122

123

128

129

130 if (ViewLikeOpInterface view = dyn_cast(op))

132 visited, output);

133

134 if (auto branch = dyn_cast(op)) {

137 visited, output);

138 }

139

140 output.push_back(result);

141 }

142

143

144

150

151

153 for (auto it = block->pred_begin(), e = block->pred_end(); it != e; ++it) {

154 auto branch = dyn_cast((*it)->getTerminator());

155 if (!branch) {

156

157 output.push_back(arg);

158 return;

159 }

160

161

162 unsigned index = it.getSuccessorIndex();

163 Value operand = branch.getSuccessorOperands(index)[argNumber];

164 if (!operand) {

165

166 output.push_back(arg);

167 return;

168 }

170 }

171 return;

172 }

173

174

177 if (auto branch = dyn_cast(op)) {

179 maxDepth, visited, output);

180 }

181

182

183 output.push_back(arg);

184 }

185

186

190

191 if (!visited.insert(value).second)

192 return;

193 if (maxDepth == 0) {

194 output.push_back(value);

195 return;

196 }

197 --maxDepth;

198

199 if (BlockArgument arg = dyn_cast(value))

202 output);

203 }

204

205

210 output);

211 }

212

213

214

215

216

217

218

219

220

221

222

223 static LogicalResult

225 std::optionalMemoryEffects::EffectInstance &effect,

227

229 if (BlockArgument arg = dyn_cast(value))

231 else

232 op = cast(value).getOwner();

233 MemoryEffectOpInterface interface = dyn_cast(op);

234 if (!interface)

235 return failure();

236

237

239 return failure();

240

241

242

243

244 if (llvm::isaSideEffects::AutomaticAllocationScopeResource(

245 effect->getResource())) {

247 return success();

248 }

249

250

251

252

253

254 allocScopeOp = op->getParentOfType();

255 return success();

256 }

257

258

260 if (lhs == rhs)

262 Operation *lhsAllocScope = nullptr, *rhsAllocScope = nullptr;

263 std::optionalMemoryEffects::EffectInstance lhsAlloc, rhsAlloc;

264

265

268

269

270

273

274

275

276 return succeeded(getAllocEffectFor(rhs, rhsAlloc, rhsAllocScope))

279 }

280

282

283

284 return succeeded(getAllocEffectFor(lhs, lhsAlloc, lhsAllocScope))

287 }

288

289

290

291 bool lhsHasAlloc = succeeded(getAllocEffectFor(lhs, lhsAlloc, lhsAllocScope));

292 bool rhsHasAlloc = succeeded(getAllocEffectFor(rhs, rhsAlloc, rhsAllocScope));

293 if (lhsHasAlloc == rhsHasAlloc) {

294

295

297 }

298

299

300

301

302 if (rhsHasAlloc) {

303 std::swap(lhs, rhs);

304 lhsAlloc = rhsAlloc;

305 lhsAllocScope = rhsAllocScope;

306 }

307

308

309

310 if (lhsAllocScope) {

311

312

313

317 if (rhsParentOp == lhsAllocScope) {

318 BlockArgument rhsArg = dyn_cast(rhs);

321 }

322 }

323

324

325

327 }

328

329

331 if (lhs == rhs)

333

334

338

339

340

341 if (lhsValues.empty() || rhsValues.empty())

343

344

345 std::optional result;

346 for (Value lhsVal : lhsValues) {

347 for (Value rhsVal : rhsValues) {

349 result = result ? result->merge(nextResult) : nextResult;

350 }

351 }

352

353

354 return *result;

355 }

356

357

358

359

360

362

364

365

366

367

368

370 }

371

372

373 MemoryEffectOpInterface interface = dyn_cast(op);

374 if (!interface)

376

377

378

380 interface.getEffects(effects);

381

384 if (isa<MemoryEffects::Allocate, MemoryEffects::Free>(effect.getEffect()))

385 continue;

386

387

388

390 if (Value effectValue = effect.getValue())

391 aliasResult = alias(effectValue, location);

392

393

394 if (aliasResult.isNo())

395 continue;

396

397

398 if (isaMemoryEffects::Read(effect.getEffect())) {

400 } else {

401 assert(isaMemoryEffects::Write(effect.getEffect()));

403 }

405 break;

406 }

407 return result;

408 }

static LogicalResult getAllocEffectFor(Value value, std::optional< MemoryEffects::EffectInstance > &effect, Operation *&allocScopeOp)

Given a value, try to get an allocation effect attached to it.

static void collectUnderlyingAddressValues(Value value, unsigned maxDepth, DenseSet< Value > &visited, SmallVectorImpl< Value > &output)

Given a value, collect all of the underlying values being addressed.

static constexpr unsigned maxUnderlyingValueSearchDepth

The maximum depth that will be searched when trying to find an underlying value.

The possible results of an alias query.

bool isNo() const

Returns if this result indicates no possibility of aliasing.

@ MustAlias

The two locations precisely alias each other.

@ MayAlias

The two locations may or may not alias.

@ NoAlias

The two locations do not alias at all.

Attributes are known-constant values of operations.

This class represents an argument of a Block.

Block * getOwner() const

Returns the block that owns this argument.

unsigned getArgNumber() const

Returns the number of this argument.

Block represents an ordered list of Operations.

Region * getParent() const

Provide a 'getParent' method for ilist_node_with_parent methods.

pred_iterator pred_begin()

bool isEntryBlock()

Return if this block is the entry block in the parent region.

ModRefResult getModRef(Operation *op, Value location)

Return the modify-reference behavior of op on location.

virtual AliasResult aliasImpl(Value lhs, Value rhs)

Given the two values, return their aliasing behavior.

AliasResult alias(Value lhs, Value rhs)

Given two values, return their aliasing behavior.

The possible results of whether a memory access modifies or references a memory location.

bool isModAndRef() const

Returns if this result modifies and references memory.

ModRefResult merge(const ModRefResult &other)

Merge this ModRef result with other and return the result.

static ModRefResult getRef()

Return a new result that indicates that the memory access may reference the value stored in memory.

static ModRefResult getNoModRef()

Return a new result that indicates that the memory access neither references nor modifies the value s...

static ModRefResult getModAndRef()

Return a new result that indicates that the memory access may reference and may modify the value stor...

static ModRefResult getMod()

Return a new result that indicates that the memory access may modify the value stored in memory.

This is a value defined by a result of an operation.

Operation * getOwner() const

Returns the operation that owns this result.

unsigned getResultNumber() const

Returns the number of this result.

A trait of region holding operations that define a new scope for automatic allocations,...

This trait indicates that the memory effects of an operation includes the effects of operations neste...

Operation is the basic unit of execution within MLIR.

bool hasTrait()

Returns true if the operation was registered with a particular trait, e.g.

Operation * getParentOp()

Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...

OpTy getParentOfType()

Return the closest surrounding parent operation that is of type 'OpTy'.

Operation * getParentWithTrait()

Returns the closest surrounding parent operation with trait Trait.

MutableArrayRef< Region > getRegions()

Returns the regions held by this operation.

bool isProperAncestor(Operation *other)

Return true if this operation is a proper ancestor of the other operation.

This class represents a point being branched from in the methods of the RegionBranchOpInterface.

static constexpr RegionBranchPoint parent()

Returns an instance of RegionBranchPoint representing the parent operation.

This class represents a successor of a region.

This class contains a list of basic blocks and a link to the parent operation it is attached to.

Operation * getParentOp()

Return the parent operation this region is attached to.

This class represents a specific instance of an effect.

This class provides an abstraction over the different types of ranges over Values.

This class represents an instance of an SSA value in the MLIR system, representing a computable value...

Block * getParentBlock()

Return the Block in which this Value is defined.

Region * getParentRegion()

Return the Region in which this Value is defined.

Include the generated interface declarations.

bool matchPattern(Value value, const Pattern &pattern)

Entry point for matching a pattern over a Value.

detail::constant_op_matcher m_Constant()

Matches a constant foldable operation.

The following effect indicates that the operation allocates from some resource.