This is an archive of the discontinued LLVM Phabricator instance.

[MLIR][SCF] Assume uses of condition in the body of scf.while is true
ClosedPublic

Authored by wsmoses on May 3 2021, 4:44 PM.

Diff Detail

Event Timeline

wsmoses created this revision.May 3 2021, 4:44 PM
wsmoses requested review of this revision.May 3 2021, 4:44 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 3 2021, 4:44 PM
mehdi_amini requested changes to this revision.May 3 2021, 6:56 PM
mehdi_amini added inline comments.
mlir/lib/Dialect/SCF/SCF.cpp
1865

I have a representation question here: why are we passing the condition to the body in the first place??

This revision now requires changes to proceed.May 3 2021, 6:56 PM

In theory, it would be nice for this not to be generated (hence why this makes a good canonicalization). In practice, this can end up being generated by an MLIR C/C++ frontend (https://github.com/wsmoses/Polygeist) as an intermediate state or simply because the source code was written like it. This consequently hinders subsequent optimization.

This isn't the particular case that triggered this to be created, but for example:

c

bool b;
while(b = condition()) {
  // canonicalized out;
  b |= knownFalse();
  if (b) {
    ...
  }
}

In theory, it would be nice for this not to be generated (hence why this makes a good canonicalization).

To me it does not makes sense that the canonical form of the operation included a dead block argument.

In practice, this can end up being generated by an MLIR C/C++ frontend (https://github.com/wsmoses/Polygeist) as an intermediate state or simply because the source code was written like it. This consequently hinders subsequent optimization.

This isn't the particular case that triggered this to be created, but for example:

c

bool b;
while(b = condition()) {
  // canonicalized out;
  b |= knownFalse();
  if (b) {
    ...
  }
}

This example does not seems like a good justification to me: it isn't in SSA form.

Ah I misunderstood your comment. The canonicalized version of the code has an unused argument because the types of the do region must match the types of the result. I suppose in this instance we could also replace uses of the result of the while with false and remove the argument entirely. Would it be better to do that here or a dead-arg elimination canonicalization (standalone pass for is intended to be submitted after this).

mehdi_amini accepted this revision.May 3 2021, 8:34 PM

OK I think I misread the pattern the first time, forget my initial remark!

mlir/lib/Dialect/SCF/SCF.cpp
1871

Please add an accessor on WhileOp for this instead.

(in general if we have a guarantee of SingleBlock region, I rather not expose "raw" Region API and write .front() or back() everywhere, and same below).

1872

Can you move this in the rewriter.create call? That way we don't pay this when the pattern does not match.

This revision is now accepted and ready to land.May 3 2021, 8:34 PM
mehdi_amini added inline comments.May 3 2021, 8:37 PM
mlir/lib/Dialect/SCF/SCF.cpp
1886

The constantTrue could be initialized inside this condition I think.
Another way to handle these kind of lazy initializations is with a lambda:

Value constantTrue = nullptr;
auto getConstantTrue() = [&] {
  if (!constantTrue) 
    constantTrue = rewriter.create<mlir::ConstantOp>(
              op.getLoc(), ty, rewriter.getBoolAttr(true));
  return constantTrue;
};


for (...)
  if (...)
    op.replaceAllUsesWith(getConstantTrue())
wsmoses updated this revision to Diff 342629.May 3 2021, 8:59 PM

Refactor while accessors