Commit Graph

149 Commits

Author SHA1 Message Date
Matthias Springer
695a5a6a66 [mlir][IR] Trigger notifyOperationRemoved callback for nested ops (#66771)
When cloning an op, the `notifyOperationInserted` callback is triggered
for all nested ops. Similarly, the `notifyOperationRemoved` callback
should be triggered for all nested ops when removing an op.

Listeners may inspect the IR during a `notifyOperationRemoved` callback.
Therefore, when multiple ops are removed in a single
`RewriterBase::eraseOp` call, the notifications must be triggered in an
order in which the ops could have been removed one-by-one:

* Op removals must be interleaved with `notifyOperationRemoved`
callbacks. A callback is triggered right before the respective op is
removed.
* Ops are removed post-order and in reverse order. Other traversal
orders could delete an op that still has uses. (This is not avoidable in
graph regions and with cyclic block graphs.)

Differential Revision: Imported from https://reviews.llvm.org/D144193.
2023-09-20 08:45:46 +02:00
Joel Wee
8498c9e948 [mlir][GreedyPatternRewriter] Add out param to detect changes in IR in applyPatternsAndFoldGreedily
This allows users of `applyPatternsAndFoldGreedily` to detect if any MLIR changes have occurred. An example use-case is where we expect the `applyPatternsAndFoldGreedily` to change the IR and want to validate that it indeed does change it.

Differential Revision: https://reviews.llvm.org/D153986
2023-06-29 12:48:00 +02:00
Matthias Springer
ce954e1cda [mlir][Transforms] GreedyPatternRewriteDriver: Worklist randomizer
Instead of always taking the last op from the worklist, take a random one. For testing/debugging purposes only. This feature can be used to ensure that lowering pipelines work correctly regardless of the order in which ops are processed by the GreedyPatternRewriteDriver.

The randomizer can be enabled by setting a numeric `MLIR_GREEDY_REWRITE_RANDOMIZER_SEED` option.

Note: When enabled, 27 tests are currently failing. Partly because FileCheck tests are looking for exact IR.

Discussion: https://discourse.llvm.org/t/discussion-fuzzing-pattern-application/67911

Differential Revision: https://reviews.llvm.org/D142447
2023-05-31 09:38:34 +02:00
Matthias Springer
ca7167d5a0 [mlir][Transforms][NFC] GreedyPatternRewriteDriver: Add worklist class
Encapsulate all worklist-related functionality in a separate `Worklist` class. This makes the remaining code more readable and allows for custom worklist implementations (e.g., a randomized worklist for fuzzing pattern application: D142447).

Differential Revision: https://reviews.llvm.org/D151345
2023-05-25 09:16:13 +02:00
Matthias Springer
5e10a8c436 [mlir][Transforms] Fix mlir-config flag check
Boolean compiler flags (such as `DMLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS`) show up in `mlir-config.h` as preprocessor defines that are either 0 or 1. Use `#if` instead of `#ifdef`.

This should have been part of D144552.
2023-05-24 16:32:58 +02:00
Matthias Springer
e6d90a0d5e [mlir][Transforms] GreedyPatternRewriteDriver debugging: Detect faulty patterns
Compute operation finger prints to detect incorrect API usage in RewritePatterns. Does not work for dialect conversion patterns.

Detect patterns that:
* Returned `failure` but changed the IR.
* Returned `success` but did not change the IR.
* Inserted/removed/modified ops, bypassing the rewriter. Not all cases are detected.

These new checks are quite expensive, so they are only enabled with `-DMLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS=ON`. Failures manifest as fatal errors (`llvm::report_fatal_error`) or crashes (accessing deallocated memory). To get better debugging information, run `mlir-opt -debug` (to see which pattern is broken) with ASAN (to see where memory was deallocated).

Differential Revision: https://reviews.llvm.org/D144552
2023-05-24 16:22:08 +02:00
Matthias Springer
aa051a0950 [mlir][Transforms][NFC] GreedyPatternRewriteDriver: Reformat debug logic
Do not duplicate code that is performing actual work, put debug code around it.

Differential Revision: https://reviews.llvm.org/D151207
2023-05-24 16:05:43 +02:00
Mehdi Amini
87e6e490e7 Add an action for each iteration of the GreedyPatternRewriteDriver
Differential Revision: https://reviews.llvm.org/D149101
2023-04-29 23:37:11 -07:00
Ingo Müller
daf4189070 [mlir] Fix GreedyPatternRewriteDriver::notifyOperationModified.
The previous implementation did not notify the attached listener.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D145049
2023-03-01 10:48:01 +00:00
Matthias Springer
9bdfa8df0d [mlir][IR] Use Listener for IR callbacks in OperationFolder
Remove the IR modification callbacks from `OperationFolder`. Instead, an optional `RewriterBase::Listener` can be specified.
* `processGeneratedConstants` => `notifyOperationCreated`
* `preReplaceAction` => `notifyOperationReplaced`

This simplifies the GreedyPatternRewriterDriver because we no longer need special handling for IR modifications due to op folding.

A folded operation is now enqueued on the GreedyPatternRewriteDriver's worklist if it was modified in-place. (There may be new patterns that apply after folding.)

Also fixes a bug in `TestOpInPlaceFold::fold`. The folder could previously be applied over and over and did not return a "null" OpFoldResult if the IR was not modified. (This is similar to a pattern that returns `success` without modifying IR; it can trigger an infinite loop in the GreedyPatternRewriteDriver.)

Differential Revision: https://reviews.llvm.org/D144463
2023-02-23 08:56:43 +01:00
Matthias Springer
bafc4dfc76 [mlir] RewriterBase::Listener: Add notifyOperationModified callback
This callback is triggered by `finalizeRootUpdate`. This allows listeners to listen for in-place op modifications without creating a new RewriterBase subclass.

Differential Revision: https://reviews.llvm.org/D143380
2023-02-22 10:41:57 +01:00
Matthias Springer
279c1d2ba7 [mlir] GreedyPatternRewriteDriver: Support optional Listener
Allow an optional `RewriterBase::Listener` to be attached to greedy pattern rewrites, so that clients can listen for IR modifications.

Differential Revision: https://reviews.llvm.org/D143340
2023-02-22 10:32:16 +01:00
Matthias Springer
c65328305e This change makes RewriterBase symmetric to OpBuilder.
```
  OpBuilder           OpBuilder::Listener
      ^                        ^
      |                        |
RewriterBase        RewriterBase::Listener
```

* Clients can listen to IR modifications with `RewriterBase::Listener`.
* `RewriterBase` no longer inherits from `OpBuilder::Listener`.
* Only a single listener can be registered at the moment (same as `OpBuilder`).

RFC: https://discourse.llvm.org/t/rfc-listeners-for-rewriterbase/68198

Differential Revision: https://reviews.llvm.org/D143339
2023-02-22 09:18:27 +01:00
Matthias Springer
724a0e2c2d [mlir] GreedyPatternRewriteDriver: Ignore scope when rewriting top-level ops
Top-level ModuleOps cannot be transformed with the GreedyPatternRewriteDriver since D141945 because they do not have an enclosing region that could be used as a scope. Make the scope optional inside GreedyPatternRewriteDriver, so that top-level ops can be processed when they are on the initial list of ops.

Note: This does not allow users to bypass the scoping mechanism by setting `config.scope = nullptr`.

Fixes #60462.

Differential Revision: https://reviews.llvm.org/D143151
2023-02-03 09:56:55 +01:00
Matthias Springer
9d5c63f641 [mlir][NFC] GreedyPatternRewriteDriver: Merge region-based and multi-op-based drivers
Deduplicate large parts of the worklist processing (`GreedyPatternRewriteDriver::processWorklist`).

The new class hierarchy is as follows:
```
          GreedyPatternRewriteDriver (abstract)
                       ^
                       |
      -----------------------------------
      |                                 |
RegionPatternRewriteDriver         MultiOpPatternRewriteDriver
```

Also update the Markdown documentation.

Differential Revision: https://reviews.llvm.org/D141396
2023-01-27 17:32:00 +01:00
Matthias Springer
6bdecbcb99 [mlir] GreedyPatternRewriteDriver: Move strict mode to GreedyPatternRewriteDriver
`strictMode` is moved to GreedyRewriteConfig to simplify the API and state of rewriter classes. The region-based GreedyPatternRewriteDriver now also supports strict mode.

MultiOpPatternRewriteDriver becomes simpler: fewer method must be overridden.

Differential Revision: https://reviews.llvm.org/D142623
2023-01-27 15:52:01 +01:00
Matthias Springer
977cddb95e [mlir] GreedyPatternRewriteDriver: All entry points take a config
The multi-op entry point now also takes a GreedyPatternRewriteConfig and respects config.maxNumRewrites. The scope is also a part of the config now.

Differential Revision: https://reviews.llvm.org/D142614
2023-01-27 14:33:54 +01:00
Matthias Springer
a2b837ab04 [mlir] GreedyPatternRewriteDriver: Entry point takes single region
The rewrite driver is typically applied to a single region or all regions of the same op. There is no longer an overload to apply the rewrite driver to a list of regions.

This simplifies the rewrite driver implementation because the scope is now a single region as opposed to a list of regions.

Note: This change is not NFC because `config.maxIterations` and `config.maxNumRewrites` is now counted for each region separately. Furthermore, worklist filtering (`scope`) is now applied to each region separately.

Differential Revision: https://reviews.llvm.org/D142611
2023-01-27 11:23:04 +01:00
Matthias Springer
67760d7e31 [mlir] GreedyPatternRewriteDriver: Make classes single-use
Less mutable state, more `const`. This is to address a concern about complexity of state in D140304.

Differential Revision: https://reviews.llvm.org/D141949
2023-01-27 10:55:16 +01:00
Matthias Springer
cadd5666a6 [mlir][NFC] GreedyPatternRewriteDriver: Remove OpPatternRewriteDriver
The `MultiOpPatternRewriteDriver` can be reused. This gives us better debug messages and more code reuse. Debug messages such as `** Replace: (op name)` were previously not printed when using the `applyOpPatternsAndFold(Operation *, ...)` overload.

Differential Revision: https://reviews.llvm.org/D142613
2023-01-27 10:43:18 +01:00
Matthias Springer
e195e6bad6 [mlir] GreedyPatternRewriteDriver: Enqueue ancestors in MultiOpPatternRewriteDriver
The `GreedyPatternRewriteDriver` was extended to enqueue ancestors in D140304. With this change, `MultiOpPatternRewriteDriver` behaves the same way.

Note: `MultiOpPatternRewriteDriver` now also has a scope that limits how far we go when checking ancestors. By default, this is the first common region of all given ops.

Differential Revision: https://reviews.llvm.org/D141945
2023-01-27 10:39:10 +01:00
Matthias Springer
774416bdb3 [mlir] GreedyPatternRewriteDriver: Keep track of surviving ops
This change adds `allErased` to the `applyOpPatternsAndFold(ArrayRef<Operation *>, ...)` overload. This overload now supports all functionality that is also supported by `applyOpPatternsAndFold(Operation *, ...)` and can be used as a replacement.

This change has no performance implications when `allErased = nullptr`.

The single-operation overload is removed in a subsequent NFC change.

Differential Revision: https://reviews.llvm.org/D141920
2023-01-26 09:21:51 +01:00
Matthias Springer
87e345b1bd [mlir] GreedyPatternRewriteDriver: Add new strict mode option
There are now three options:
* `AnyOp` (previously `false`)
* `ExistingAndNewOps` (previously `true`)
* `ExistingOps`: this one is new.

The last option corresponds to what the `applyOpPatternsAndFold(Operation*, ...)` overload is doing. It is now also supported on the `applyOpPatternsAndFold(ArrayRef<Operation *>, ...)` overload.

Differential Revision: https://reviews.llvm.org/D141904
2023-01-20 10:08:11 +01:00
Matthias Springer
11a9c05bcb [mlir] GreedyPatternRewriteDriver: Fix termination criteria in OpPatternRewriteDriver
This driver should iterate until convergence or until the specified op was erased. However, it used to stop when any op was erased.

Differential Revision: https://reviews.llvm.org/D141921
2023-01-18 15:11:06 +01:00
Matthias Springer
fefe655baa [mlir][NFC] GreedyPatternRewriteDriver: Consistent return values
All `apply...` functions now return a LogicalResult indicating whether the iterative process converged or not.

Differential Revision: https://reviews.llvm.org/D141845
2023-01-16 16:30:12 +01:00
Matthias Springer
6e5021b8dc [mlir][NFC] GreedyPatternRewriteDriver: Remove overridden eraseOp
It is not necessary to override `eraseOp`, we can use the existing `notifyOperationRemoved`.

Differential Revision: https://reviews.llvm.org/D141844
2023-01-16 16:18:53 +01:00
Matthias Springer
ed9194be6d [mlir] GreedyPatternRewriter: Add ancestors to worklist
When adding an op to the worklist, also add its ancestors to the worklist. This allows for RewritePatterns to match an op `a` based on what is inside of the body of `a`.

This change fixes a problem that became apparent with `vector.warp_execute_on_lane_0`, but could probably be triggered with similar patterns. The pattern extracts an op `b` with `eligible = true` from the body of an op `a`:
```
test.a {
  %0 = test.b() {eligible = true}
  yield %0
}
```

Afterwards:
```
%0 = test.b() {eligible = true}
test.a {
  yield %0
}
```

The pattern is an `OpRewritePattern<OpA>`. For some reason, `test.a` is not on the GreedyPatternRewriter's worklist. E.g., because no pattern could be applied and it was removed. Now, another pattern updates `test.b`, so that `eligible` is changed from `true` to `false`. The `OpRewritePattern<OpA>` could now be applied, but (without this revision) `test.a` is still not on the worklist.

Note: In the above example, an `OpRewritePattern<OpB>` could have been used instead of an `OpRewritePattern<OpA>`. With such a design, we can run into the same problem (when the `eligible` attr is on `test.a` and `test.b` is removed from the worklist because no patterns could be applied).

Note: This change uncovered an unrelated bug in TestSCFUtils.cpp that was triggered due to a change in the order in which ops are processed. A TODO is added to the broken code and test cases are adapted so that the bug is no longer triggered.

Differential Revision: https://reviews.llvm.org/D140304
2023-01-13 10:51:28 +01:00
Matthias Springer
0e4735546e [mlir] Fix worklist bug in MultiOpPatternRewriteDriver
When `strict = true`, only pre-existing and newly-created ops are rewritten and/or folded. Such ops are stored in `strictModeFilteredOps`.

Newly-created ops were previously added to `strictModeFilteredOps` after calling `addToWorklist` (via `GreedyPatternRewriteDriver::notifyOperationInserted`). Therefore, newly-created ops were never added to the worklist.

Also fix a test case that should have gone into an infinite loop (`test.replace_with_new_op` was replaced with itself, which should have caused the op to be rewritten over and over), but did not due to this bug.

Differential Revision: https://reviews.llvm.org/D141141
2023-01-10 15:33:22 +01:00
Matthias Springer
0ff3cf0c0c [mlir] GreedyPatternRewriter: fix counting of iterations
The GreedyPatternRewriteDriver did previously not count the first iteration. I.e., when setting `config.maxIterations = 1`, two iterations were performed. In pratice, this number is not really important; we usually just need a limit in some reasonable order of magnitude. However, this fix allows us to write better convergence/worklist tests with carefully crafted test patterns to purposely trigger edge cases in the driver.

Similarly, the first rewrite was previously not counted towards `config.maxNumRewrites`.

For consistency, `OpPatternRewriteDriver` now uses `config.maxNumRewrites` instead of `config.maxIterations`; this driver does not have "iterations", it consists of a single loop (corresponding to the inner loop in the GreedyPatternRewriteDriver).

Differential Revision: https://reviews.llvm.org/D141365
2023-01-10 12:21:08 +01:00
Matthias Springer
391cb54122 [mlir] Add option to limit number of pattern rewrites in CanonicalizerPass
The greedy pattern rewriter consists of two nested loops. `config.maxIterations` (which configurable on the CanonicalizerPass) controls the maximum number of iterations of the outer loop.

```
/// This specifies the maximum number of times the rewriter will iterate
/// between applying patterns and simplifying regions. Use `kNoLimit` to
/// disable this iteration limit.
int64_t maxIterations = 10;
```

This change adds `config.maxNumRewrites` which controls the maximum number of pattern rewrites within an iteration. (It effectively control the maximum number of iterations of the inner loop.)

This flag is meant for debugging and useful in cases where one or multiple faulty patterns can be applied indefinitely, resulting in an infinite loop.

Differential Revision: https://reviews.llvm.org/D140525
2022-12-23 13:08:53 +01:00
Matthias Springer
2fea658a74 [mlir] GreedyPatternRewriter: Reprocess modified ops
Ops that were modifed in-place (`finalizeRootUpdate` was called) should be reprocessed by the GreedyPatternRewriter. This is currently not happening with `GreedyRewriteConfig::maxIterations = 1`.

Note: If your project goes into an infinite loop because of this change, you likely have one or multiple faulty patterns that modify the same operations in-place (`updateRootInplace`) indefinitely.

Differential Revision: https://reviews.llvm.org/D138038
2022-11-18 11:43:44 +01:00
Alex Zinenko
e8aaf75810 [mlir] specify the values when notifying about op replacement
It is useful for PatternRewriter listeners to know the values that are
replacing the op in addition to only the fact of the op being replaced
for being able to keep track of changes or for debugging.

Reviewed By: Mogball

Differential Revision: https://reviews.llvm.org/D134748
2022-09-27 16:22:35 +00:00
Chia-hung Duan
ba3a9f51ff [mlir:MultiOpDriver] Add operands to worklist should be checked
Operand's defining op may not be valid for adding to the worklist under
stict mode

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D127180
2022-06-11 15:56:23 +00:00
Chia-hung Duan
633ad1d864 [mlir:MultiOpDriver] Quick fix the assertion position
The assertion should come after null check
2022-06-02 23:25:35 +00:00
Chia-hung Duan
2aeffc6d8d [mlir:MultiOpDriver] Don't add ops which are not in the allowed list
In strict mode, only the new inserted operation is allowed to add to the
worklist. Before this change, it would add the users of a replaced op
and it didn't check if the users are allowed to be pushed into the
worklist

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D126899
2022-06-02 18:27:37 +00:00
River Riddle
aa568e082b [mlir:GreedyDriver] Return WalkResult::skip after deleting a known constant
This avoids use-after-free when trying to access the regions after visiting
the operation.
2022-05-18 02:14:02 -07:00
rkayaith
7814b559bd [GreedyPatternRewriter] Avoid reversing constant order
The previous fix from af371f9f98 only applied when using a bottom-up
traversal. The change here applies the constant preprocessing logic to the
top-down case as well. This resolves the issue with the canonicalizer pass still
reordering constants, since it uses a top-down traversal by default.

Fixes #51892

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D125623
2022-05-18 00:55:59 -07:00
Frederik Gossen
673e9828be [MLIR] Fix iteration counting in greedy pattern application
Previously, checking that a fix point is reached was counted as a full
iteration. As this "iteration" never changes the IR, this seems counter-
intuitive.

Differential Revision: https://reviews.llvm.org/D123641
2022-04-21 15:17:28 -04:00
River Riddle
af371f9f98 Reland [GreedPatternRewriter] Preprocess constants while building worklist when not processing top down
Reland Note: Adds a fix to properly mark a commutative operation as folded if we change the order
             of its operands. This was uncovered by the fact that we no longer re-process constants.

This avoids accidentally reversing the order of constants during successive
application, e.g. when running the canonicalizer. This helps reduce the number
of iterations, and also avoids unnecessary changes to input IR.

Fixes #51892

Differential Revision: https://reviews.llvm.org/D122692
2022-04-07 11:31:42 -07:00
River Riddle
ea64828a10 [mlir:PDL] Expand how native constraint/rewrite functions can be defined
This commit refactors the expected form of native constraint and rewrite
functions, and greatly reduces the necessary user complexity required when
defining a native function. Namely, this commit adds in automatic processing
of the necessary PDLValue glue code, and allows for users to define
constraint/rewrite functions using the C++ types that they actually want to
use.

As an example, lets see a simple example rewrite defined today:

```
static void rewriteFn(PatternRewriter &rewriter, PDLResultList &results,
                      ArrayRef<PDLValue> args) {
  ValueRange operandValues = args[0].cast<ValueRange>();
  TypeRange typeValues = args[1].cast<TypeRange>();
  ...
  // Create an operation at some point and pass it back to PDL.
  Operation *op = rewriter.create<SomeOp>(...);
  results.push_back(op);
}
```

After this commit, that same rewrite could be defined as:

```
static Operation *rewriteFn(PatternRewriter &rewriter ValueRange operandValues,
                            TypeRange typeValues) {
  ...
  // Create an operation at some point and pass it back to PDL.
  return rewriter.create<SomeOp>(...);
}
```

Differential Revision: https://reviews.llvm.org/D122086
2022-04-06 17:41:59 -07:00
Mehdi Amini
ba43d6f85c Revert "[GreedPatternRewriter] Preprocess constants while building worklist when not processing top down"
This reverts commit 59bbc7a085.

This exposes an issue breaking the contract of
`applyPatternsAndFoldGreedily` where we "converge" without applying
remaining patterns.
2022-04-01 06:16:55 +00:00
River Riddle
59bbc7a085 [GreedPatternRewriter] Preprocess constants while building worklist when not processing top down
This avoids accidentally reversing the order of constants during successive
application, e.g. when running the canonicalizer. This helps reduce the number
of iterations, and also avoids unnecessary changes to input IR.

Fixes #51892

Differential Revision: https://reviews.llvm.org/D122692
2022-03-31 12:08:55 -07:00
Mogball
8f8c89f3cd [mlir] Remove spurious debug guard 2021-12-23 11:55:37 -08:00
Mehdi Amini
be0a7e9f27 Adjust "end namespace" comment in MLIR to match new agree'd coding style
See D115115 and this mailing list discussion:
https://lists.llvm.org/pipermail/llvm-dev/2021-December/154199.html

Differential Revision: https://reviews.llvm.org/D115309
2021-12-08 06:05:26 +00:00
River Riddle
5652ecc373 [mlir:GreedyPatternRewriter] Add debug logging for pattern rewriter actions
This effectively mirrors the logging in dialect conversion, which has proven
very useful for understanding the pattern application process.

Differential Revision: https://reviews.llvm.org/D112120
2021-10-21 17:14:35 +00:00
River Riddle
b7144ab765 [NFC] Clean up a few methods within GreedyPatternRewriter
Move a few methods out of line and clean up comments.
2021-10-21 17:14:35 +00:00
Frederik Gossen
519663beba [MLIR] Add an option to disable maxIterations in greedy pattern rewrites
This option is needed for passes that are known to reach a fix point, but may
need many iterations depending on the size of the input IR.

Differential Revision: https://reviews.llvm.org/D111058
2021-10-05 11:49:01 +02:00
Uday Bondhugula
7932d21f5d [MLIR] Introduce a new rewrite driver to simplify supplied list of ops
Introduce a new rewrite driver (MultiOpPatternRewriteDriver) to rewrite
a supplied list of ops and other ops. Provide a knob to restrict
rewrites strictly to those ops or also to affected ops (but still not to
completely related ops).

This rewrite driver is commonly needed to run any simplification and
cleanup at the end of a transforms pass or transforms utility in a way
that only simplifies relevant IR. This makes it easy to write test cases
while not performing unrelated whole IR simplification that may
invalidate other state at the caller.

The introduced utility provides more freedom to developers of transforms
and transform utilities to perform focussed and local simplification. In
several cases, it provides greater efficiency as well as more
simplification when compared to repeatedly calling
`applyOpPatternsAndFold`; in other cases, it avoids the need to
undesirably call `applyPatternsAndFoldGreedily` to do unrelated
simplification in a FuncOp.

Update a few transformations that were earlier using
applyOpPatternsAndFold (SimplifyAffineStructures,
affineDataCopyGenerate, a linalg transform).

TODO:
- OpPatternRewriteDriver can be removed as it's a special case of
  MultiOpPatternRewriteDriver, i.e., both can be merged.

Differential Revision: https://reviews.llvm.org/D106232
2021-07-21 20:25:16 +05:30
Chris Lattner
64716b2c39 [GreedyPatternRewriter] Introduce a config object that allows controlling internal parameters. NFC.
This exposes the iterations and top-down processing as flags, and also
allows controlling whether region simplification is desirable for a client.
This allows deleting some duplicated entrypoints to
applyPatternsAndFoldGreedily.

This also deletes the Constant Preprocessing pass, which isn't worth it
on balance.

All defaults are all kept the same, so no one should see a behavior change.

Differential Revision: https://reviews.llvm.org/D102988
2021-05-24 12:40:40 -07:00
Chris Lattner
648f34a284 Merge with mainline.
Differential Revision: https://reviews.llvm.org/D102636
2021-05-17 11:15:10 -07:00