[llvm] [AArch64] Sanitise pow inputs using a target DAG combine (PR #192958)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 22 08:36:49 PDT 2026


================
@@ -27763,6 +27714,65 @@ static SDValue trySwapVSelectOperands(SDNode *N, SelectionDAG &DAG) {
                      {InverseSetCC, SelectB, SelectA});
 }
 
+static SDValue performVselectPowCombine(SDNode *N,
+                                        TargetLowering::DAGCombinerInfo &DCI) {
+  SDValue Cond = N->getOperand(0);
+  SDValue TrueVal = N->getOperand(1);
+  SDValue FalseVal = N->getOperand(2);
+  bool TrueValIsPow = TrueVal.getOpcode() == ISD::FPOW;
+  bool FalseValIsPow = FalseVal.getOpcode() == ISD::FPOW;
+
+  // If both inputs are pow we could equally remove the select and simply
+  // select between pow inputs instead.
+  if (TrueValIsPow && FalseValIsPow)
+    return SDValue();
+
+  if ((TrueValIsPow && !TrueVal.hasOneUse()) ||
+      (FalseValIsPow && !FalseVal.hasOneUse()))
+    return SDValue();
+
+  EVT VT = N->getValueType(0);
+  RTLIB::Libcall LC = RTLIB::getPOW(VT);
+  SelectionDAG &DAG = DCI.DAG;
+  auto &TLI = DAG.getTargetLoweringInfo();
+  bool HasLibCall =
+      TLI.getLibcallLoweringInfo().getLibcallImpl(LC) != RTLIB::Unsupported;
+  if (!HasLibCall)
+    return SDValue();
+
+  // TODO: For scalable vectors we should really just be able to pass in the
+  // mask when lowering FPOW to a call instruction.
+
+  // For a given call pow(x, y) when x=1.0 it is guaranteed to return 1.0 for
+  // any value of y.
+  SDLoc DL(N);
+  SDValue One = DAG.getConstantFP(1.0, DL, VT.getVectorElementType());
+  SDValue SplatOne = DAG.getSplatVector(VT, DL, One);
+
+  SDValue OldPow = TrueValIsPow ? TrueVal : FalseVal;
+  SDValue OldPowArg0 = OldPow->getOperand(0);
+
+  // Bail out if argument 0 is already a select.
+  if (OldPowArg0.getOpcode() == ISD::VSELECT)
+    return SDValue();
+
+  SDValue NewPowArg0;
+  if (TrueValIsPow)
+    NewPowArg0 = DAG.getNode(ISD::VSELECT, DL, VT, Cond, OldPowArg0, SplatOne);
+  else
+    NewPowArg0 = DAG.getNode(ISD::VSELECT, DL, VT, Cond, SplatOne, OldPowArg0);
+  SDValue NewPow =
+      DAG.getNode(ISD::FPOW, DL, VT, NewPowArg0, OldPow->getOperand(1));
+  NewPow->setFlags(OldPow->getFlags());
----------------
paulwalker-arm wrote:

```suggestion
      DAG.getNode(ISD::FPOW, DL, VT, NewPowArg0, OldPow->getOperand(1), OldPow->getFlags());
```

https://github.com/llvm/llvm-project/pull/192958


More information about the llvm-commits mailing list