This is an archive of the discontinued LLVM Phabricator instance.

[LSR] Fix canonicalization formula and its checker.
ClosedPublic

Authored by skatkov on Mar 24 2022, 9:41 PM.

Details

Summary

According to definition of canonical form, it is a canonical
if scale reg does not contain addrec for loop L then none of bases
should contain addrec for this loop.

The critical word here is "contains".

Current checker of canonical form checks not "containing" property
but "is". So it does not check whether it contains but whether it is.

Fix the checker and canonicalizing utility to follow definition.

Without this fix in the test attached the base formula looking as
reg((-1 * {0,+,8}<nuw><nsw><%bb2>)<nsw>) + 1*reg((8 * (%arg /u 8))<nuw>)
is considered as conanocial while base contains an addrec.
And modified formula we want to insert
reg({0,+,8}<nuw><nsw><%bb2>) + 1*reg((-8 * (%arg /u 8)))
is considered as not canonical.

Diff Detail

Event Timeline

skatkov created this revision.Mar 24 2022, 9:41 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2022, 9:41 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
skatkov requested review of this revision.Mar 24 2022, 9:41 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2022, 9:41 PM

Could you please elaborate what kind of crash do you see? Is it simply an assertion that something must be canonical and it's not, or something more sophisticated?

mkazantsev added inline comments.Mar 27 2022, 8:36 PM
llvm/test/Transforms/LoopStrengthReduce/canonical-form.ll
2

nit: I suggest adding | FileCheck and also adding CHECK-LABEL: <test name> to the code itself.

Could you please elaborate what kind of crash do you see? Is it simply an assertion that something must be canonical and it's not, or something more sophisticated?

You'll get
bool LSRUse::InsertFormula(const Formula &F, const Loop &L) {

assert(F.isCanonical(L) && "Invalid canonical representation");

on a attached test.

llvm/test/Transforms/LoopStrengthReduce/canonical-form.ll
2

will do before landing or with next update of the patch.

Interesting note. It seems that the definition of canonical representation of the formula looks as follows:

/// The list of "base" registers for this use. When this is non-empty. The
/// canonical representation of a formula is
/// 1. BaseRegs.size > 1 implies ScaledReg != NULL and
/// 2. ScaledReg != NULL implies Scale != 1 || !BaseRegs.empty().
/// 3. The reg containing recurrent expr related with currect loop in the
/// formula should be put in the ScaledReg.
/// #1 enforces that the scaled register is always used when at least two
/// registers are needed by the formula: e.g., reg1 + reg2 is reg1 + 1 * reg2.
/// #2 enforces that 1 * reg is reg.
/// #3 ensures invariant regs with respect to current loop can be combined
/// together in LSR codegen.
/// This invariant can be temporarily broken while building a formula.
/// However, every formula inserted into the LSRInstance must be in canonical
/// form.

The important statement here is "reg containing recurrent expr" while isCanonical utility checks that reg is recurrent expr.
The utility that makes canonicalization also operates on reg as if it is recurrent expr but not contains.

Might be the bug is here.

mkazantsev added a comment.EditedMar 27 2022, 9:13 PM

Yup, I agree with that. To me the initial formula

reg((-1 * {0,+,8}<nuw><nsw><%bb2>)<nsw>) + 1*reg((8 * (%arg /u 8))<nuw>)

isn't canonical too, but because of wrong check (which simply checks that base reg isa SCEVAddRec) multiplication by minus one obfuscates this.

One more counter-argument to this fix was: could we just replace {0,+,8} by 1 * {0,+,8} and treat this as canonical formula?

Let's see how deep this bug actually lies.

skatkov updated this revision to Diff 418503.Mar 28 2022, 12:19 AM
skatkov retitled this revision from [LSR] Canonicalize formula before inserting it. to [LSR] Fix canonicalization formula and its checker..
skatkov edited the summary of this revision. (Show Details)
mkazantsev accepted this revision.Mar 28 2022, 10:08 PM

LGTM with nits.

llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
482

nit: naming convention for functions broken here, I suggest containsAddRecDependentOnLoop.

507

nit: I think we can capture [&L] only.

This revision is now accepted and ready to land.Mar 28 2022, 10:08 PM
This revision was automatically updated to reflect the committed changes.