Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[IVDescriptors] Call getOpcode on demand in getReductionOpChain. nfc #118777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 30, 2025

Conversation

Mel-Chen
Copy link
Contributor

@Mel-Chen Mel-Chen commented Dec 5, 2024

Non-arithmetic reductions do not require the binary opcodes.
As a first step toward removing the dependency of non-arithmetic reductions on getOpcode function, this patch refactors the getReductionOpChain function.

In the future, once all users of getOpcode function are refactored, an assertion can be added to getOpcode function to ensure that only arithmetic reductions rely on it.

@llvmbot
Copy link
Member

llvmbot commented Dec 5, 2024

@llvm/pr-subscribers-llvm-analysis

Author: Mel Chen (Mel-Chen)

Changes

Non-arithmetic reductions do not require the use of binary opcodes.
As a first step toward removing the dependency of non-arithmetic reductions on getOpcode function, this patch refactors the getReductionOpChain function.

In the future, once all users of getOpcode function are refactored, an assertion can be added to getOpcode function to ensure that only arithmetic reductions rely on it.


Full diff: https://github.com/llvm/llvm-project/pull/118777.diff

2 Files Affected:

  • (modified) llvm/include/llvm/Analysis/IVDescriptors.h (+3)
  • (modified) llvm/lib/Analysis/IVDescriptors.cpp (+10-5)
diff --git a/llvm/include/llvm/Analysis/IVDescriptors.h b/llvm/include/llvm/Analysis/IVDescriptors.h
index 5d992faf99d27f..913cd8db894cf0 100644
--- a/llvm/include/llvm/Analysis/IVDescriptors.h
+++ b/llvm/include/llvm/Analysis/IVDescriptors.h
@@ -213,6 +213,9 @@ class RecurrenceDescriptor {
   /// Returns true if the recurrence kind is a floating point kind.
   static bool isFloatingPointRecurrenceKind(RecurKind Kind);
 
+  /// Returns true if the recurrence kind is arithmetic.
+  static bool isArithmeticRecurrenceKind(RecurKind Kind);
+
   /// Returns true if the recurrence kind is an integer min/max kind.
   static bool isIntMinMaxRecurrenceKind(RecurKind Kind) {
     return Kind == RecurKind::UMin || Kind == RecurKind::UMax ||
diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp
index e1eb219cf977e1..103f1d3149121b 100644
--- a/llvm/lib/Analysis/IVDescriptors.cpp
+++ b/llvm/lib/Analysis/IVDescriptors.cpp
@@ -60,6 +60,11 @@ bool RecurrenceDescriptor::isFloatingPointRecurrenceKind(RecurKind Kind) {
   return (Kind != RecurKind::None) && !isIntegerRecurrenceKind(Kind);
 }
 
+bool RecurrenceDescriptor::isArithmeticRecurrenceKind(RecurKind Kind) {
+  return (Kind != RecurKind::None) && !isMinMaxRecurrenceKind(Kind) &&
+         !isAnyOfRecurrenceKind(Kind);
+}
+
 /// Determines if Phi may have been type-promoted. If Phi has a single user
 /// that ANDs the Phi with a type mask, return the user. RT is updated to
 /// account for the narrower bit width represented by the mask, and the AND
@@ -1063,7 +1068,7 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) {
 SmallVector<Instruction *, 4>
 RecurrenceDescriptor::getReductionOpChain(PHINode *Phi, Loop *L) const {
   SmallVector<Instruction *, 4> ReductionOperations;
-  unsigned RedOp = getOpcode();
+  bool IsArithmetic = isArithmeticRecurrenceKind(Kind);
 
   // Search down from the Phi to the LoopExitInstr, looking for instructions
   // with a single user of the correct type for the reduction.
@@ -1081,7 +1086,7 @@ RecurrenceDescriptor::getReductionOpChain(PHINode *Phi, Loop *L) const {
   // more expensive than out-of-loop reductions, and need to be costed more
   // carefully.
   unsigned ExpectedUses = 1;
-  if (RedOp == Instruction::ICmp || RedOp == Instruction::FCmp)
+  if (!IsArithmetic)
     ExpectedUses = 2;
 
   auto getNextInstruction = [&](Instruction *Cur) -> Instruction * {
@@ -1089,7 +1094,7 @@ RecurrenceDescriptor::getReductionOpChain(PHINode *Phi, Loop *L) const {
       Instruction *UI = cast<Instruction>(User);
       if (isa<PHINode>(UI))
         continue;
-      if (RedOp == Instruction::ICmp || RedOp == Instruction::FCmp) {
+      if (!IsArithmetic) {
         // We are expecting a icmp/select pair, which we go to the next select
         // instruction if we can. We already know that Cur has 2 uses.
         if (isa<SelectInst>(UI))
@@ -1101,7 +1106,7 @@ RecurrenceDescriptor::getReductionOpChain(PHINode *Phi, Loop *L) const {
     return nullptr;
   };
   auto isCorrectOpcode = [&](Instruction *Cur) {
-    if (RedOp == Instruction::ICmp || RedOp == Instruction::FCmp) {
+    if (!IsArithmetic) {
       Value *LHS, *RHS;
       return SelectPatternResult::isMinOrMax(
           matchSelectPattern(Cur, LHS, RHS).Flavor);
@@ -1110,7 +1115,7 @@ RecurrenceDescriptor::getReductionOpChain(PHINode *Phi, Loop *L) const {
     if (isFMulAddIntrinsic(Cur))
       return true;
 
-    return Cur->getOpcode() == RedOp;
+    return Cur->getOpcode() == getOpcode();
   };
 
   // Attempt to look through Phis which are part of the reduction chain

Comment on lines -1113 to +1239
return Cur->getOpcode() == RedOp;
return Cur->getOpcode() == getOpcode();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're checking for opcode here anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only arithmetic reductions call getOpcode and check the opcode, non-arithmetic won't reach this check statement.

Copy link
Contributor

@artagnon artagnon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this.

Comment on lines 1108 to 1109
auto isCorrectOpcode = [&](Instruction *Cur) {
if (RedOp == Instruction::ICmp || RedOp == Instruction::FCmp) {
if (!IsArithmetic) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called isCorrectOpcode(), and it doesn't check opcode anymore?

Comment on lines 1084 to 1089
if (RedOp == Instruction::ICmp || RedOp == Instruction::FCmp)
if (!IsArithmetic)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like IsArithmetic needs to be inverted, since we're checking the negation everywhere, but then I wouldn't know what to call the new variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can call it as IsNonArithmetic, I think.
82a107d

@Mel-Chen Mel-Chen force-pushed the remove-call-getopcode-ivdes branch from 1282bd9 to 82a107d Compare December 6, 2024 07:17
@Mel-Chen Mel-Chen requested a review from artagnon December 6, 2024 07:19
@@ -1081,15 +1086,15 @@ RecurrenceDescriptor::getReductionOpChain(PHINode *Phi, Loop *L) const {
// more expensive than out-of-loop reductions, and need to be costed more
// carefully.
unsigned ExpectedUses = 1;
if (RedOp == Instruction::ICmp || RedOp == Instruction::FCmp)
if (IsNonArithmetic)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this patch is really NFC because in theory IsNonArithmetic could be true when Kind is RecurKind::None. Also, even if you remove references to getOpcode for AnyOf recurrence kinds in this function there are still lots of places in LoopVectorize.cpp that call RecurrenceDescriptor::getOpcode(). It's not obvious to me right now that you can avoid calling getOpcode for AnyOf types. Also, if you have to specialise the code everywhere to avoid calling getOpcode for AnyOf kinds wouldn't that make the code even more complicated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this patch is really NFC because in theory IsNonArithmetic could be true when Kind is RecurKind::None.

This is a great reminder, but I don't think Kind would normally be None in the function getReductionOpChain. I believe using an assertion here would be more appropriate.
8dd7cde

Also, even if you remove references to getOpcode for AnyOf recurrence kinds in this function there are still lots of places in LoopVectorize.cpp that call RecurrenceDescriptor::getOpcode().

Yes, also in SLP that need to be refined. #121549
This is just the first step in the cleanup.

It's not obvious to me right now that you can avoid calling getOpcode for AnyOf types. Also, if you have to specialise the code everywhere to avoid calling getOpcode for AnyOf kinds wouldn't that make the code even more complicated?

The main purpose of avoiding to call getOpcode is to unify AnyOf.
This won't make things more complicated; the design and usage will be similar to llvm::getRecurrenceIdentity.
On the contrary, passing the type into getOpcode would make it more complex #118393 : when an AnyOf recurrence needs to call getOpcode, I would first have to determine whether it is a select(icmp ixx) or select(fcmp float/double...) before calling getOpcode.

@@ -1063,7 +1068,7 @@ unsigned RecurrenceDescriptor::getOpcode(RecurKind Kind) {
SmallVector<Instruction *, 4>
RecurrenceDescriptor::getReductionOpChain(PHINode *Phi, Loop *L) const {
SmallVector<Instruction *, 4> ReductionOperations;
unsigned RedOp = getOpcode();
bool IsNonArithmetic = !isArithmeticRecurrenceKind(Kind);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd prefer this to be:

  bool IsComparison = Instruction::ICmp || RedOp == Instruction::FCmp;

or something like that. It's more precise and we don't have to worry about updating isArithmeticRecurrenceKind every time we add a new recurrence kind. It also explicitly excludes RecurKind::None.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I don't want to call getOpcode for every recurrences. How about adding isComparisonRecurrenceKind function?

@Mel-Chen Mel-Chen force-pushed the remove-call-getopcode-ivdes branch from 82a107d to 8dd7cde Compare January 3, 2025 08:21
Mel-Chen added a commit that referenced this pull request Jan 10, 2025
…:createOp (NFC) (#122239)

This patch is one part of unifying IAnyOf and FAnyOf reduction. #118393
The related patch is #118777.
BaiXilin pushed a commit to BaiXilin/llvm-fix-vnni-instr-types that referenced this pull request Jan 12, 2025
…:createOp (NFC) (llvm#122239)

This patch is one part of unifying IAnyOf and FAnyOf reduction. llvm#118393
The related patch is llvm#118777.
@Mel-Chen Mel-Chen force-pushed the remove-call-getopcode-ivdes branch from 8dd7cde to 367cfd1 Compare March 24, 2025 09:47
@Mel-Chen Mel-Chen changed the title [IVDescriptors][NFC] Refactor getReductionOpChain to remove the dependency of non-arithmetic reductions on getOpcode. [IVDescriptors] Call getOpcode on demand in getReductionOpChain. nfc Mar 24, 2025
@Mel-Chen
Copy link
Contributor Author

Mel-Chen commented Apr 7, 2025

ping

1 similar comment
@Mel-Chen
Copy link
Contributor Author

ping

@Mel-Chen
Copy link
Contributor Author

Ping

Copy link
Contributor

@fhahn fhahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks.

@Mel-Chen Mel-Chen force-pushed the remove-call-getopcode-ivdes branch from 367cfd1 to 137c6c4 Compare April 30, 2025 07:12
@Mel-Chen Mel-Chen merged commit 08f0aa4 into llvm:main Apr 30, 2025
11 checks passed
@Mel-Chen Mel-Chen deleted the remove-call-getopcode-ivdes branch April 30, 2025 09:01
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…lvm#118777)

Non-arithmetic reductions do not require the binary opcodes.
As a first step toward removing the dependency of non-arithmetic
reductions on `getOpcode` function, this patch refactors the
`getReductionOpChain` function.

In the future, once all users of `getOpcode` function are refactored, an
assertion can be added to `getOpcode` function to ensure that only
arithmetic reductions rely on it.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…lvm#118777)

Non-arithmetic reductions do not require the binary opcodes.
As a first step toward removing the dependency of non-arithmetic
reductions on `getOpcode` function, this patch refactors the
`getReductionOpChain` function.

In the future, once all users of `getOpcode` function are refactored, an
assertion can be added to `getOpcode` function to ensure that only
arithmetic reductions rely on it.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…lvm#118777)

Non-arithmetic reductions do not require the binary opcodes.
As a first step toward removing the dependency of non-arithmetic
reductions on `getOpcode` function, this patch refactors the
`getReductionOpChain` function.

In the future, once all users of `getOpcode` function are refactored, an
assertion can be added to `getOpcode` function to ensure that only
arithmetic reductions rely on it.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
…lvm#118777)

Non-arithmetic reductions do not require the binary opcodes.
As a first step toward removing the dependency of non-arithmetic
reductions on `getOpcode` function, this patch refactors the
`getReductionOpChain` function.

In the future, once all users of `getOpcode` function are refactored, an
assertion can be added to `getOpcode` function to ensure that only
arithmetic reductions rely on it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants