[llvm] [InstCombine] InstCombine should fold frexp of select to select of frexp (PR #121227)

via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 27 12:15:06 PST 2024


https://github.com/vortex73 created https://github.com/llvm/llvm-project/pull/121227

Fixes #92542 

>From 81bafc6b1cdf41dda64454ca856b8b667079f1f4 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Sat, 28 Dec 2024 00:31:40 +0530
Subject: [PATCH] [InstCombine] InstCombine should fold frexp of select to
 select of frexp

---
 .../InstCombine/InstCombineSelect.cpp         | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 3d251d662bd53d..a6539e119d68d5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3813,6 +3813,42 @@ static Value *foldSelectIntoAddConstant(SelectInst &SI,
   return nullptr;
 }
 
+static Instruction *foldFrexpOfSelect(ExtractValueInst *EV, CallInst *FrexpCall,
+                                      SelectInst *SelectInst) {
+  // A helper that folds frexp of select to select of frexp.
+  IRBuilder<> Builder(EV);
+
+  Value *Cond = SelectInst->getCondition();
+  Value *TrueVal = SelectInst->getTrueValue();
+  Value *FalseVal = SelectInst->getFalseValue();
+
+  ConstantFP *ConstOp = nullptr;
+  Value *VarOp = nullptr;
+  bool ConstIsTrue = false;
+
+  if ((ConstOp = dyn_cast<ConstantFP>(TrueVal))) {
+    VarOp = FalseVal;
+    ConstIsTrue = true;
+  } else {
+    ConstOp = dyn_cast<ConstantFP>(FalseVal);
+    VarOp = TrueVal;
+    ConstIsTrue = false;
+  }
+
+  CallInst *NewFrexp =
+      Builder.CreateCall(FrexpCall->getCalledFunction(), {VarOp}, "frexp");
+  Value  *NewEV = Builder.CreateExtractValue(NewFrexp, 0);
+
+  APFloat ConstVal = ConstOp->getValueAPF();
+  int Exp;
+  APFloat Mantissa = frexp(ConstVal, Exp, APFloat::rmNearestTiesToEven);
+  Constant *ConstantMantissa = ConstantFP::get(ConstOp->getType(), Mantissa);
+  Value *NewSel =
+      Builder.CreateSelect(Cond, ConstIsTrue ? ConstantMantissa : NewEV,
+                           ConstIsTrue ? NewEV : ConstantMantissa);
+  return cast<Instruction>(NewSel);
+}
+
 Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
   Value *CondVal = SI.getCondition();
   Value *TrueVal = SI.getTrueValue();
@@ -3829,6 +3865,27 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
   if (Instruction *I = canonicalizeScalarSelectOfVecs(SI, *this))
     return I;
 
+  for (User *U : SI.users()) {
+    if (auto *EV = dyn_cast<ExtractValueInst>(U)) {
+      if (!EV->hasOneUse())
+        continue;
+      if (auto *FrexpCall = dyn_cast<CallInst>(EV->getAggregateOperand())) {
+        if (Function *F = FrexpCall->getCalledFunction()) {
+          if (F->getIntrinsicID() == Intrinsic::frexp &&
+              EV->getNumIndices() == 1 && EV->getIndices()[0] == 0) {
+            Value *SelectOp = FrexpCall->getArgOperand(0);
+            if (auto *SelInst = dyn_cast<SelectInst>(SelectOp)) {
+                                if (isa<ConstantFP>(SelInst->getTrueValue()) ||
+						isa<ConstantFP>(SelInst->getFalseValue())) {
+                return foldFrexpOfSelect(EV, FrexpCall, SelInst);
+				}
+            }
+          }
+        }
+      }
+    }
+  }
+
   // If the type of select is not an integer type or if the condition and
   // the selection type are not both scalar nor both vector types, there is no
   // point in attempting to match these patterns.



More information about the llvm-commits mailing list