Skip to content

[InstCombine] Remove redundant fptrunc of select fold (NFCI) #117182

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

Closed
wants to merge 1 commit into from

Conversation

nikic
Copy link
Contributor

@nikic nikic commented Nov 21, 2024

This was subsumed by FoldOpIntoSelect() in #116073, and has incorrect FMF propagation on top.

This was subsumed by FoldOpIntoSelect() in llvm#116073, and has
incorrect FMF propagation on top.
@nikic nikic requested review from dtcxzyw and goldsteinn November 21, 2024 16:25
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms labels Nov 21, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2024

@llvm/pr-subscribers-llvm-transforms

Author: Nikita Popov (nikic)

Changes

This was subsumed by FoldOpIntoSelect() in #116073, and has incorrect FMF propagation on top.


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

1 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp (-18)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 6c2554ea73b7f8..c97be6ffc75675 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -1866,24 +1866,6 @@ Instruction *InstCombinerImpl::visitFPTrunc(FPTruncInst &FPT) {
 
       return UnaryOperator::CreateFNegFMF(InnerTrunc, Op);
     }
-
-    // If we are truncating a select that has an extended operand, we can
-    // narrow the other operand and do the select as a narrow op.
-    Value *Cond, *X, *Y;
-    if (match(Op, m_Select(m_Value(Cond), m_FPExt(m_Value(X)), m_Value(Y))) &&
-        X->getType() == Ty) {
-      // fptrunc (select Cond, (fpext X), Y --> select Cond, X, (fptrunc Y)
-      Value *NarrowY = Builder.CreateFPTrunc(Y, Ty);
-      Value *Sel = Builder.CreateSelect(Cond, X, NarrowY, "narrow.sel", Op);
-      return replaceInstUsesWith(FPT, Sel);
-    }
-    if (match(Op, m_Select(m_Value(Cond), m_Value(Y), m_FPExt(m_Value(X)))) &&
-        X->getType() == Ty) {
-      // fptrunc (select Cond, Y, (fpext X) --> select Cond, (fptrunc Y), X
-      Value *NarrowY = Builder.CreateFPTrunc(Y, Ty);
-      Value *Sel = Builder.CreateSelect(Cond, NarrowY, X, "narrow.sel", Op);
-      return replaceInstUsesWith(FPT, Sel);
-    }
   }
 
   if (auto *II = dyn_cast<IntrinsicInst>(FPT.getOperand(0))) {

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.

I think this LGTM, except maybe change NFCI to NFC in the title? I also looked at the subsuming commit, and I think we can be confident that this is an NFC.

@dtcxzyw
Copy link
Member

dtcxzyw commented Nov 23, 2024

Can you pre-commit this test: https://alive2.llvm.org/ce/z/XNQvu5

define half @src(half %394) {
entry:
  %395 = fpext half %394 to double
   %396 = fcmp olt double %395, 0.000000e+00
   %397 = select i1 %396, double 0.000000e+00, double %395
   %398 = fptrunc double %397 to half
  ret half %398
}

define half @tgt(half %394) {
entry:
   %396 = fcmp olt half %394, 0.000000e+00
   %397 = select i1 %396, half 0.000000e+00, half %394
  ret half %397
}

nikic added a commit that referenced this pull request Nov 25, 2024
To guard against regression from #117182.
@nikic
Copy link
Contributor Author

nikic commented Nov 25, 2024

@dtcxzyw Done in f81f47e.

This case is doubly-blocked, first by

// We are casting a select. Try to fold the cast into the select if the
// select does not have a compare instruction with matching operand types
// or the select is likely better done in a narrow type.
// Creating a select with operands that are different sizes than its
// condition may inhibit other folds and lead to worse codegen.
auto *Cmp = dyn_cast<CmpInst>(Sel->getCondition());
if (!Cmp || Cmp->getOperand(0)->getType() != Sel->getType() ||
(CI.getOpcode() == Instruction::Trunc &&
shouldChangeType(CI.getSrcTy(), CI.getType()))) {
which checks for a comparison with same types and then
// Test if a FCmpInst instruction is used exclusively by a select as
// part of a minimum or maximum operation. If so, refrain from doing
// any other folding. This helps out other analyses which understand
// non-obfuscated minimum and maximum idioms. And in this case, at
// least one of the comparison operands has at least one user besides
// the compare (the select), which would often largely negate the
// benefit of folding anyway.
if (auto *CI = dyn_cast<FCmpInst>(SI->getCondition())) {
if (CI->hasOneUse()) {
Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
if ((TV == Op0 && FV == Op1) || (FV == Op0 && TV == Op1))
return nullptr;
}
}
blocks specifically the min/max pattern.

@nikic
Copy link
Contributor Author

nikic commented Nov 25, 2024

A complicating factor is that we perform this canonicalization:

define float @t4(double %a) {
; CHECK-LABEL: @t4(
; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp oge double [[A:%.*]], 5.000000e+00
; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[DOTINV]], double 5.000000e+00, double [[A]]
; CHECK-NEXT:    [[TMP2:%.*]] = fptrunc double [[TMP1]] to float
; CHECK-NEXT:    ret float [[TMP2]]
;
  %1 = fcmp ult double %a, 5.0
  %2 = fptrunc double %a to float
  %3 = select i1 %1, float %2, float 5.0
  ret float %3
}

So just special casing fptrunc also doesn't work, because we'd infinite loop with this transform. So I'm inclined to just leave this alone...

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

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

LGTM. Remember to update the test f81f47e :)

@nikic
Copy link
Contributor Author

nikic commented Nov 25, 2024

@dtcxzyw But do we really want to merge this despite the regression?

@dtcxzyw
Copy link
Member

dtcxzyw commented Nov 26, 2024

@dtcxzyw But do we really want to merge this despite the regression?

This pattern looks weird and should be caused by an unexpected upcasting. I believe it is easy to be fixed in the source code with the help of linters.

BTW, before fixing the regression, we should fold fptrunc max/min(fpext(X), fpext(Y)) first: https://alive2.llvm.org/ce/z/WtxWAM. It is enough for some applications pursuing the floating point performance.

So I agree that we just leave it alone.

@nikic nikic closed this Jan 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants