This is an archive of the discontinued LLVM Phabricator instance.

[InstSimplify] with logical ops: (X | Y) ? 0 : X --> 0
ClosedPublic

Authored by Allen on Apr 22 2023, 2:40 AM.

Details

Summary

Use simplifySelectWithICmpEq to handle the implied equalities from the icmp-or,
then both of ICMP_NE and ICMP_EQ will be addressed

(X | Y) == 0 ?  X : 0 --> 0 (commuted 2 ways)
(X | Y) != 0 ?  0 : X --> 0 (commuted 2 ways) --> will transform to above in instcombine

Fixes https://github.com/llvm/llvm-project/issues/62263

Diff Detail

Event Timeline

Allen created this revision.Apr 22 2023, 2:40 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 22 2023, 2:40 AM
Allen requested review of this revision.Apr 22 2023, 2:40 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 22 2023, 2:40 AM
RKSimon added inline comments.Apr 22 2023, 2:55 AM
llvm/test/Transforms/InstSimplify/select.ll
1408 ↗(On Diff #516048)

is noundef necessary?

1416 ↗(On Diff #516048)

commutation test?

RKSimon added inline comments.Apr 22 2023, 3:02 AM
llvm/lib/Analysis/InstructionSimplify.cpp
4733

Also - is this safe when matching zero vectors with undef elements?

nikic requested changes to this revision.Apr 22 2023, 3:25 AM

As this is the second special case for this pattern, we should generalize it.

  1. Extract https://github.com/llvm/llvm-project/blob/9ea3fcfa380c6097fddd0d9a9b2c13f0f20bc41a/llvm/lib/Analysis/InstructionSimplify.cpp#L4569-L4582 in one direction into a helper, and call it in both directions there.
  2. Add a special case for or equals zero and and equals minus one where we try the replacement with the operands of the or/and.
  3. Remove https://github.com/llvm/llvm-project/blob/9ea3fcfa380c6097fddd0d9a9b2c13f0f20bc41a/llvm/lib/Analysis/InstructionSimplify.cpp#L4585-L4598, which is subsumed.
This revision now requires changes to proceed.Apr 22 2023, 3:25 AM
floatshadow added a comment.EditedApr 22 2023, 3:38 AM

As this is the second special case for this pattern, we should generalize it.

  1. Extract https://github.com/llvm/llvm-project/blob/9ea3fcfa380c6097fddd0d9a9b2c13f0f20bc41a/llvm/lib/Analysis/InstructionSimplify.cpp#L4569-L4582 in one direction into a helper, and call it in both directions there.
  2. Add a special case for or equals zero and and equals minus one where we try the replacement with the operands of the or/and.
  3. Remove https://github.com/llvm/llvm-project/blob/9ea3fcfa380c6097fddd0d9a9b2c13f0f20bc41a/llvm/lib/Analysis/InstructionSimplify.cpp#L4585-L4598, which is subsumed.

My concern mentioned in this issue is the case the condition of ternary operator contains multiple ORs/ANDs. There seems a need to do a recursive check (?)
Current simplifyWithOpReplaced will dispatch OR simplification into a some fold check and fail to do further inductions.

nikic added a comment.Apr 22 2023, 3:46 AM

As this is the second special case for this pattern, we should generalize it.

  1. Extract https://github.com/llvm/llvm-project/blob/9ea3fcfa380c6097fddd0d9a9b2c13f0f20bc41a/llvm/lib/Analysis/InstructionSimplify.cpp#L4569-L4582 in one direction into a helper, and call it in both directions there.
  2. Add a special case for or equals zero and and equals minus one where we try the replacement with the operands of the or/and.
  3. Remove https://github.com/llvm/llvm-project/blob/9ea3fcfa380c6097fddd0d9a9b2c13f0f20bc41a/llvm/lib/Analysis/InstructionSimplify.cpp#L4585-L4598, which is subsumed.

My concern mentioned in this issue is the case the condition of ternary operator contains multiple ORs/ANDs. There seems a need to do a recursive check (?)

Unless there is reason to believe that such patterns occur in practice, there is no need for premature over-generalization. There are lots of places where we could be doing recursive checks, but in most places that just unnecessarily complicates things without providing tangible benefit.

Allen added a comment.Apr 22 2023, 8:03 PM

hi @nikic, Why do we need delete the following modifications? I find some regression with some case, such as select_or_1

Remove https://github.com/llvm/llvm-project/blob/9ea3fcfa380c6097fddd0d9a9b2c13f0f20bc41a/llvm/lib/Analysis/InstructionSimplify.cpp#L4585-L4598
+++ b/llvm/test/Transforms/InstSimplify/select_or_and.ll
@@ -5,7 +5,9 @@
 define i32 @select_or_1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @select_or_1(
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    ret i32 [[OR]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[RET]]

@Allen My bad -- we need an additional change in order to remove that code. For now you can just leave it.

Allen updated this revision to Diff 516147.Apr 23 2023, 3:37 AM
Allen edited the summary of this revision. (Show Details)

Address comment

  1. with some refactor to extract InstructionSimplify.cpp#L4569-L4582 in one direction into a helper, and call it in both directions there
  2. Add extra case select_icmp_and_eq for equals minus one with TODO
  3. Delete noundef for tests
  4. Add commutation test select_icmp_or_eq_commuted
  5. Add vector test select_icmp_or_eq_vec
  6. change the match pattern from ICMP_NE to ICMP_EQ, as the instcombine will normalize the ICMP_NE to ICMP_EQ
nikic added inline comments.Apr 23 2023, 9:50 AM
llvm/lib/Analysis/InstructionSimplify.cpp
4597

Not quite the code structure I had in mind. Rather than handling or in simplifySelectWithICmpEq, I'd expect something like this in here:

if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y))) && match(CmpRHS, m_Zero())) {
  // X | Y == 0 implies X == 0 and Y == 0.
  if (Value *V = simplifySelectWithICmpEq(X, CmpRHS, TrueVal, FalseVal, Q,
                                          MaxRecurse))
      return V;
  if (Value *V = simplifySelectWithICmpEq(Y, CmpRHS, TrueVal, FalseVal, Q,
                                          MaxRecurse))
      return V;
}

That is, we handle the straightforward equality, and then we try to handle the implied equalities from the icmp or.

llvm/test/Transforms/InstSimplify/select-cmp-or.ll
2 ↗(On Diff #516147)

Why does this also run instcombine?

Allen updated this revision to Diff 516219.Apr 23 2023, 6:47 PM
Allen edited the summary of this revision. (Show Details)

Address comment
1、Use simplifySelectWithICmpEq to handle the implied equalities from the icmp-or according the suggestion
2、Delete the instcombine for test select-cmp-or.ll as it is not need with above refactoring

Allen marked 5 inline comments as done.Apr 23 2023, 6:55 PM
Allen added inline comments.
llvm/lib/Analysis/InstructionSimplify.cpp
4597

Thanks for detail suggestion, apply your comment.

4733

Thanks, added with select_icmp_or_eq_vec

llvm/test/Transforms/InstSimplify/select-cmp-or.ll
2 ↗(On Diff #516147)

Delete it now,thanks.
I added this because the scenario of the case select_icmp_or_ne cannot be directly addressed, while I hope this scenario can also be monitored and verified.

llvm/test/Transforms/InstSimplify/select.ll
1408 ↗(On Diff #516048)

I deleted the noundef, thanks

1416 ↗(On Diff #516048)

Added with case select_icmp_or_eq_commuted

nikic added a comment.Apr 24 2023, 5:51 AM

@Allen My bad -- we need an additional change in order to remove that code. For now you can just leave it.

Actually, I think I confused myself here. We should be able to remove this code now. From a local test, this works. (Well, if you also handle the and / -1 case.)

llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll
144 ↗(On Diff #516219)

Unrelated change?

Allen updated this revision to Diff 516376.Apr 24 2023, 6:08 AM
Allen marked 5 inline comments as done.

Delete the or part according comment

Allen added a comment.Apr 24 2023, 6:10 AM

@Allen My bad -- we need an additional change in order to remove that code. For now you can just leave it.

Actually, I think I confused myself here. We should be able to remove this code now. From a local test, this works. (Well, if you also handle the and / -1 case.)

Yes, the or/ 0 part can be deleted now. And the and / -1 case should be deleted with a following MR

llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll
144 ↗(On Diff #516219)

Yes, I add the TODO as it is a potential optimization points

nikic added a comment.Apr 24 2023, 6:43 AM

Implementation looks good, can you please precommit the tests?

llvm/test/Transforms/InstSimplify/select-cmp-or.ll
33 ↗(On Diff #516376)

Not needed for instsimplify tests.

60 ↗(On Diff #516376)

Could you please add a negative test where the icmp constant is not zero?

Allen updated this revision to Diff 516602.Apr 24 2023, 7:46 PM

rebase after precommit tests

Allen marked 2 inline comments as done.Apr 24 2023, 7:52 PM

Implementation looks good, can you please precommit the tests?

Thanks, apply your comment. Precommit the tests on D149115, and also add negative case with icmp constant is not zero as suggestion.

llvm/test/Transforms/InstSimplify/select-cmp-or.ll
33 ↗(On Diff #516376)

Delete the thwart complexity-based canonicalization

Allen edited the summary of this revision. (Show Details)Apr 25 2023, 5:35 AM
nikic accepted this revision.Apr 25 2023, 5:53 AM

LGTM

llvm/test/Transforms/InstSimplify/select-cmp-or.ll
50 ↗(On Diff #516602)

This doesn't require InstCombine, this code internally canonicalizes to EQ predicate.

This revision is now accepted and ready to land.Apr 25 2023, 5:53 AM
DianQK added a subscriber: DianQK.Apr 25 2023, 5:57 AM
Allen updated this revision to Diff 516788.Apr 25 2023, 6:44 AM
Allen marked an inline comment as done.

rebase as the test merged into select_or_and.ll

This revision was landed with ongoing or failed builds.Apr 25 2023, 6:52 AM
This revision was automatically updated to reflect the committed changes.