This is an archive of the discontinued LLVM Phabricator instance.

[BypassSlowDivision] Use ValueTracking to simplify run-time checks
AbandonedPublic

Authored by n.bozhenov on Dec 31 2016, 7:02 AM.

Details

Summary

ValueTracking is used for more thorough analysis of operands. Based on
the analysis, either run-time checks can be simplified (e.g. check only
one operand instead of two) or the transformation can be avoided. For
example, it is quite often the case that a divisor is promoted from a
shorter type and run-time checks for it are redundant.

With additional compile-time analysis of values, two special
cases naturally arise and are addressed by the patch:

  1. Both operands are known to be short enough. Then, the long division can be simply replaced with a short one without CFG modification.
  1. If a division is unsigned and the dividend is known to be short enough then the long division is not needed any more. Because if the divisor is too big for short division then the quotient is obviously zero (and the remainder is equal to the dividend). Actually, the division is not needed when (divisor > dividend).

Diff Detail

Event Timeline

n.bozhenov updated this revision to Diff 82766.Dec 31 2016, 7:02 AM
n.bozhenov retitled this revision from to [BypassSlowDivision] Use ValueTracking to simplify run-time checks.
n.bozhenov updated this object.
jlebar edited edge metadata.Dec 31 2016, 10:08 AM

I'm excited to see what this does for our GPU kernels.

lib/Transforms/Utils/BypassSlowDivision.cpp
48

Please define what these mean. (The notion of "long" and "short" are important to this patch, but we don't define them anywhere.)

48

Suggest renaming the enum to ValueRange -- you can still abbreviate it "VALRNG" in the enumerators.

78

Check if an integer value fits into a smaller type.

82

This paragraph doesn't add any additional information IMO -- maybe we should just get rid of it.

87

LLVM convention is to start all variable names with upper-case letters -- please fix here and elsewhere.

98

LLVM convention is not to use braces on single-line if statements. Please fix here and elsewhere.

121

Nit, this looks like "dividend random number generator" to me. Spelling out "Range" would only be an extra two chars -- maybe we should do that for both ValRng and Dividend/DivisorRange.

139

Suggest s/tr/Trunc/. In any case please use uppercase.

149

I think it would be clearer if we didn't have this variable and just wrote out ConstantInt::get(I->getType(), 0) in the two places where we need it. As-is, a reader is going to have to use Vim's # to figure out what this variable is, since the function is so long and the uses are so far from the declaration.

151

Long prepositional phrases at the beginning of a sentence should be followed by a comma.

152

comma before "and" (separating independent clauses)

154

In this case, no division is needed at all: The quotient is 0 and the remainder is equal to Dividend.

156

This comment is missing the (really cool) punch line:

So instead of checking at runtime whether Divisor fits into BypassType, we emit a runtime check to differentiate between these two cases. This lets us entirely avoid a long div.

157

"Shortcut" is one word, but also, this control flow is very complicated.

For example, it's confusing that the first if (ShortCut) branch, which is in the "basic block for slow divide operation", actually does something very fast. One could add comments, but they're going to be pretty complicated. ("New BB for long divide, which we bypass if possible, see definition of ShortCut...")

It seems to me we really want to say

if (DividendShort && !UseSignedOp) {
  // Do one thing.
} else {
  // Do something different.
}

Could we refactor the code so we can write it this way?

232

Suggest commenting on what the whole "else" branch is doing:

Check at runtime whether Dividend and Divisor fit in BypassType.

Mentioning the "OR" is more confusing than helpful, I think, because we don't always emit the OR.

test/CodeGen/X86/bypass-slow-division-64.ll
67

The first comment added here is good, but then the ones below are all fragments, which is confusing. Can we make them complete sentences?

n.bozhenov added inline comments.Feb 13 2017, 10:01 AM
lib/Transforms/Utils/BypassSlowDivision.cpp
157

It seems to me we really want to say

if (DividendShort && !UseSignedOp) {
  // Do one thing.
} else {
  // Do something different.
}

Could we refactor the code so we can write it this way?

I fully agree that the control flow gets overly complex here. But I did it this way because all the paths re-use some parts of the code, so to get a simpler control flow one have either to perform significant refactoring of the code or to introduce a lot of code duplication. And I was kind of reluctant to refactor the code.

I played with refactoring approach and uploaded a couple of patches D29896 and D29897. The first patch does refactoring and extracts a number of auxilliary methods from insertFastDiv function, so that in the second patch these methods can be reused along different code paths as necessary. By the way, I had to convert a number of variables into object attributes, because the same values are used across all these auxilliary methods.

Justin, do you think such refactoring approach should be preferred?

Justin, do you think such refactoring approach should be preferred?

I'm happy to review these additional patches, but I would prefer to have a relatively fast feedback cycle between my reviewing the code and your addressing the comments. By the time a week has passed, I've already forgotten details about the patch; by the time six weeks pass, I am reviewing totally from scratch.

Do you have time now to push these patches through to completion? If not, maybe you can let me know when you do, and at that point I'll start reviewing?

Do you have time now to push these patches through to completion? If not, maybe you can let me know when you do, and at that point I'll start reviewing?

Yep. Let's do it now.

n.bozhenov abandoned this revision.Mar 2 2017, 3:13 PM

Superseded by D29897.