This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] canonicalize abs pattern
ClosedPublic

Authored by shchenz on Jun 28 2018, 10:39 PM.

Details

Summary

two more abs pattern and canonicalize abs pattern.
This patch handle two more pattern:
1:

define i32 @abs_canonical_6(i32 %a, i32 %b) {
  %tmp1 = sub i32 %a, %b
  %cmp = icmp sgt i32 %tmp1, -1
  %tmp2 = sub i32 %b, %a
  %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
  ret i32 %abs
}

this should be |a-b|.

2:

define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
  %tmp1 = sub <2 x i8> %a, %b
  %cmp = icmp sgt <2 x i8> %tmp1, <i8 -1, i8 -1>
  %tmp2 = sub <2 x i8> %b, %a
  %abs = select <2 x i1> %cmp, <2 x i8> %tmp1, <2 x i8> %tmp2
  ret <2 x i8> %abs
}

this should be |a - b| for vector type.

3:

define i32 @abs_canonical_8(i32 %a) {
; CHECK-LABEL: @abs_canonical_8(
; CHECK-NEXT:    [[TMP:%.*]] = sub i32 0, [[A:%.*]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP]], 0
; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[TMP]]
; CHECK-NEXT:    ret i32 [[ABS]]
;
  %tmp = sub i32 0, %a
  %cmp = icmp slt i32 %tmp, 0
  %abs = select i1 %cmp, i32 %a, i32 %tmp
  ret i32 %abs
}

this should be |-a| -> |a|
Also add test cases for -|a-b|(i32 and vector), -|-a|(-|a|)

Diff Detail

Repository
rL LLVM

Event Timeline

shchenz created this revision.Jun 28 2018, 10:39 PM
craig.topper edited the summary of this revision. (Show Details)
craig.topper added inline comments.Jun 28 2018, 10:55 PM
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
17528 ↗(On Diff #153437)

Just declare this local to the 2 blocks that need since it doesn't live outside of them.

17530 ↗(On Diff #153437)

You probably don't need the GE/LE checks. We should be canonicalizing those away by altering the constant.

shchenz updated this revision to Diff 153451.Jun 29 2018, 1:42 AM

fix Craig's comments

shchenz marked 2 inline comments as done.Jun 29 2018, 1:44 AM

For min/max, we made value tracking (matchSelectPattern) recognize more patterns:
https://reviews.llvm.org/rL286776

And then we canonicalized the IR to the most recognizable form (where the cmp operands match the select operands):
https://reviews.llvm.org/rL295758

I think that's a better solution than adding more pattern matching to the DAG. For example, this isn't going to help vector code?

@spatel Hi Sanjay, thanks for your comments. I will look into it.

spatel added a subscriber: RKSimon.Jul 2 2018, 6:00 AM

@spatel Hi Sanjay, thanks for your comments. I will look into it.

Thanks - here are recent patches for abs IR canonicalization:
D47076
rL334137

...so you want modify/add the pattern that has a 'sub' with something similar. We haven't made ValueTracking changes corresponding to those (but probably should). There's also an open question about creating ISD::ABS nodes directly in SelectionDAGBuilder. I think it's just an oversight that we use matchSelectPattern to create min/max there, but not abs.

There's also an open question about creating ISD::ABS nodes directly in SelectionDAGBuilder. I think it's just an oversight that we use matchSelectPattern to create min/max there, but not abs.

For reference, this was raised in PR37743

shchenz updated this revision to Diff 154047.Jul 3 2018, 9:40 PM

@spatel Hi Sanjay, thanks for your comments. After investigation, I split this task into three parts:
1: find more abs pattern in matchSelectPattern and do canonicalization for abs/nabs pattern. (cmp + select). This is what this patch doing.
2: recognize ISD::ABS in selectionDAGBuilder to leverage platform abs instruction. (https://bugs.llvm.org/show_bug.cgi?id=36036). This will be done in next patch.
3: if no platform abs instructions, recognize canonicalized abs pattern (cmp + select) to shift + add + xor in DAGCombiner. This will be done in third patch.

What do you think about above proposal? And could you please help to do another review for this patch? Thanks.

spatel added a comment.Jul 4 2018, 6:04 AM

@spatel Hi Sanjay, thanks for your comments. After investigation, I split this task into three parts:
1: find more abs pattern in matchSelectPattern and do canonicalization for abs/nabs pattern. (cmp + select). This is what this patch doing.
2: recognize ISD::ABS in selectionDAGBuilder to leverage platform abs instruction. (https://bugs.llvm.org/show_bug.cgi?id=36036). This will be done in next patch.
3: if no platform abs instructions, recognize canonicalized abs pattern (cmp + select) to shift + add + xor in DAGCombiner. This will be done in third patch.

What do you think about above proposal? And could you please help to do another review for this patch? Thanks.

Yes, this sounds like a good plan to me.

spatel added inline comments.Jul 4 2018, 6:40 AM
llvm/include/llvm/Analysis/ValueTracking.h
104–105 ↗(On Diff #154047)

Doesn't "complement" mean bitwise-not? I think this should be called "isKnownNegation" unless I'm mixing up the terminology.

Nit: add a period at end of comment.

llvm/lib/Analysis/ValueTracking.cpp
4506 ↗(On Diff #154047)

Don't repeat the comment from the header file.

4508–4509 ↗(On Diff #154047)

Make that an assert? Other functions in this file just assume that the parameters are valid. Ideally, we'd change everything to references instead of pointers...

4515 ↗(On Diff #154047)

The comments don't match the code. The parameters to this function should be named X and Y, and these local values should be named A and B?

4516 ↗(On Diff #154047)

Don't initialize these to nullptr. They should not be read if they are uninitialized, so explicitly initializing them removes a chance to produce a warning for that situation.

4521 ↗(On Diff #154047)

Remove the TODO or specify a pattern that you know should be added later.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
815–817 ↗(On Diff #154047)

We should check the negated value in the select here. If it is not m_Neg(), then we should create a new sub (neg) in the canonical form.

If you would prefer to make that a separate patch, then please add a 'TODO' comment here.

826 ↗(On Diff #154047)

Formatting: goes over 80-columns.

llvm/test/Transforms/InstCombine/abs-1.ll
119–123 ↗(On Diff #154047)

Please commit all new tests to trunk with the current output. Then rebase this patch so we see only the diffs.

shchenz updated this revision to Diff 154932.Jul 10 2018, 10:25 PM
shchenz edited the summary of this revision. (Show Details)

fix Sanjay's comments

shchenz marked 9 inline comments as done.Jul 10 2018, 10:26 PM

@spatel Hi Sanjay, I have made changes accordingly. Could you help to have another review. Thanks.

@spatel Hi Sanjay, I have made changes accordingly. Could you help to have another review. Thanks.

Thanks for the changes. This looks mostly right, but I want to make sure we're testing everything properly. This is really several independent steps in 1 patch, so I'd like to reduce the risk of bugs by breaking it up.

  1. Please separate the creation of isKnownNegation() into its own patch and use it from InstSimplify -> SimplifyAddInst(). I have added tests at rL336822, so that should be a very small patch. Improving InstSimplify helps several other passes, so that's a good patch independent of abs().
  2. The changes in matchSelectPattern can be separated and tested using patterns that are optimized by InstCombiner::foldSPFofSPF(). We'll need to add some tests for that part. Let me know if it is not clear.
  3. The canonicalization changes will be the last step and should be covered by the tests shown in this patch, but I think we're missing some cases where the code may have bugs.
llvm/lib/Analysis/ValueTracking.cpp
4640 ↗(On Diff #154932)

cmpEqNegated -> CmpUsesNegatedOp ?

4672–4673 ↗(On Diff #154932)

Would it be better to return {N}ABS(X) here rather than {N}ABS(-X)?

Why is it useful to return the negated operand as the input rather than the original operand X?

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
840 ↗(On Diff #154932)

What happens if the subtract has other uses? We should have tests for that possibility.

@spatel Hi Sanjay, I have made changes accordingly. Could you help to have another review. Thanks.

Thanks for the changes. This looks mostly right, but I want to make sure we're testing everything properly. This is really several independent steps in 1 patch, so I'd like to reduce the risk of bugs by breaking it up.

  1. Please separate the creation of isKnownNegation() into its own patch and use it from InstSimplify -> SimplifyAddInst(). I have added tests at rL336822, so that should be a very small patch. Improving InstSimplify helps several other passes, so that's a good patch independent of abs().
  2. The changes in matchSelectPattern can be separated and tested using patterns that are optimized by InstCombiner::foldSPFofSPF(). We'll need to add some tests for that part. Let me know if it is not clear.
  3. The canonicalization changes will be the last step and should be covered by the tests shown in this patch, but I think we're missing some cases where the code may have bugs.

@spatel Hi Sanjay, I have made patches for 1 & 2. But I am not very clear about 3. You mentioned the code may have bugs, could you give me some details? I saw your inline comment "What happens if the subtract has other uses", do you mean this one? In my opinion, RHS from matchSelectPattern() currently must be sub(0, X) or sub(A, B) (LHS = sub(B, A)). If I change RHS(TVal or FVal) to sub(0, LHS), I think there will be no impact for RHS(TVal or FVal) other users. yes, you are right, there should be some test cases for this scenario. Thanks.

shchenz updated this revision to Diff 155622.Jul 16 2018, 12:13 AM
shchenz retitled this revision from recognize more abs pattern to [InstCombine] canonicalize abs pattern.

part 1 & 2 are done.
part 3: canonicalize abs pattern and fix code review comments

shchenz edited the summary of this revision. (Show Details)Jul 16 2018, 5:30 AM

Please add a test like this (it will fail with the current patch):

define i32 @abs_canonical_9(i32 %a, i32 %b) {
  %tmp2 = sub i32 %b, %a
  %tmp1 = sub i32 %a, %b
  %cmp = icmp sgt i32 %tmp1, -1
  %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
  %add = add i32 %abs, %tmp2 ; increase use count for %tmp2.
  ret i32 %add
}

Actually, it will fail even without the extra use, so this is a minimal test:

define i32 @abs_canonical_9(i32 %a, i32 %b) {
  %tmp2 = sub i32 %b, %a
  %tmp1 = sub i32 %a, %b
  %cmp = icmp sgt i32 %tmp1, -1
  %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
  ret i32 %abs
}

We can not just replace operands without considering the order of the instructions. It would be better to create a new instruction with the IRBuilder, so we don't have to worry about this problem.

spatel added inline comments.Jul 16 2018, 7:30 AM
llvm/lib/Analysis/ValueTracking.cpp
4520 ↗(On Diff #155622)

There is some white space difference in this file. It should not be included in this patch now.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
836 ↗(On Diff #155622)

typo: canoical

shchenz marked an inline comment as not done.Jul 16 2018, 8:27 AM

Actually, it will fail even without the extra use, so this is a minimal test:

define i32 @abs_canonical_9(i32 %a, i32 %b) {
  %tmp2 = sub i32 %b, %a
  %tmp1 = sub i32 %a, %b
  %cmp = icmp sgt i32 %tmp1, -1
  %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
  ret i32 %abs
}

We can not just replace operands without considering the order of the instructions. It would be better to create a new instruction with the IRBuilder, so we don't have to worry about this problem.

@spatel Hi Sanjay, Sorry about this. Seems this is a big mistake. I will do some study about IRBuilder and upload a new patch later. Thanks for your help.

llvm/lib/Analysis/ValueTracking.cpp
4520 ↗(On Diff #155622)

Yes, I deleted two white spaces added in line 4629 by mistake in rL337143.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
836 ↗(On Diff #155622)

I'll fix that.

We can not just replace operands without considering the order of the instructions. It would be better to create a new instruction with the IRBuilder, so we don't have to worry about this problem.

@spatel Hi Sanjay, Sorry about this. Seems this is a big mistake. I will do some study about IRBuilder and upload a new patch later. Thanks for your help.

It's not too bad - see the code just above here in canonicalizeMinMaxWithConstant() for an example.

shchenz updated this revision to Diff 156468.Jul 20 2018, 4:37 AM

fix Sanjay's comments

shchenz updated this revision to Diff 156969.Jul 23 2018, 11:03 PM

rebase the patch

spatel added inline comments.Jul 25 2018, 4:45 PM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
797–799 ↗(On Diff #156969)

This comment is not accurate now. It should mention the possibility of a compare that uses the negated op. I'm not sure how many variants we can match now, but you can include that number if you know the answer.

819–820 ↗(On Diff #156969)

Rephrase this as:
The compare may use the negated abs()/nabs() operand, or it may use negation in non-canonical form such as: sub A, B.

821–822 ↗(On Diff #156969)

Indentation is not as expected.

838 ↗(On Diff #156969)

This assert can be more specific? The sub must be with the specific operands of LHS reversed?

840 ↗(On Diff #156969)

Use Builder.CreateNeg().

llvm/test/Transforms/InstCombine/abs-1.ll
188–192 ↗(On Diff #156969)

This is the extra-uses scenario that I was worried about. We have more instructions than we started with. We should not canonicalize if we can not have equal or less-than instructions from the transform.

344–349 ↗(On Diff #156969)

Similar to above - we should not ever have more instructions than we started with.

shchenz updated this revision to Diff 157422.Jul 25 2018, 9:32 PM

fix Sanjay's comments.

shchenz marked 4 inline comments as done.Jul 25 2018, 9:38 PM
shchenz added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
797–799 ↗(On Diff #156969)

Maybe we want to add new pattern in isKnownNegation(), to avoid change the comments every time we change isKnownNegetion(), I don't use a accurate number. Hope this is ok.

838 ↗(On Diff #156969)

The assert is added in previous patch which is directly changing operands of operator Sub. Since that is a wrong patch and we create new node for RHS, I delete this assert.

spatel accepted this revision.Jul 26 2018, 6:21 AM

Thanks for all of the IR improvements - LGTM.

Note that the 2nd step of the larger proposal for abs() improvements is implemented in D49837.

This revision is now accepted and ready to land.Jul 26 2018, 6:22 AM
This revision was automatically updated to reflect the committed changes.