[llvm] [SelectionDAG] Scalarize legal operands of scalarized vector binops (PR #226616)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 18:06:07 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-selectiondag

Author: Demetrios Chiuratto Agourakis (agourakis82)

<details>
<summary>Changes</summary>

Fixes #<!-- -->219695.

`ScalarizeVecRes_BinOp` assumed both operands of a scalarized `<1 x ty>` result also needed scalarizing, and looked each up in the scalarized-vector map. Under AVX-512 `<1 x i1>` is a legal type, so the exponent of `llvm.ldexp.v1f32.v1i1` was never scalarized. The lookup then asserted in `DAGTypeLegalizer::getSDValue` with `TableId should be non-zero` during X86 instruction selection.

Extract a legal operand element instead of requiring it to have been scalarized, matching the per-operand handling already used by `ScalarizeVecRes_StrictFPOp`.

The exponent is then promoted by the existing `PromoteIntOp_ExpOp` path. Because the promoted `i1` is narrower than `sizeof(int)`, it is lowered to the `ldexp`/`ldexpf` libcall rather than `vscalef`; the `i32` exponent case is unchanged and still selects `vscalefss`.

```llvm
define <1 x float> @<!-- -->test(<1 x float> %x, <1 x i1> %e) {
  %r = call <1 x float> @<!-- -->llvm.ldexp.v1f32.v1i1(<1 x float> %x, <1 x i1> %e)
  ret <1 x float> %r
}
```

`llc -mtriple=x86_64 -mattr=+avx512f` aborts before this change and compiles after it.

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


2 Files Affected:

- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (+17-4) 
- (added) llvm/test/CodeGen/X86/ldexp-v1i1.ll (+36) 


``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 913aa4536bc81..b3404bcb25170 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -281,10 +281,23 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
 }
 
 SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
-  SDValue LHS = GetScalarizedVector(N->getOperand(0));
-  SDValue RHS = GetScalarizedVector(N->getOperand(1));
-  return DAG.getNode(N->getOpcode(), SDLoc(N),
-                     LHS.getValueType(), LHS, RHS, N->getFlags());
+  SDLoc DL(N);
+  SDValue LHS = N->getOperand(0);
+  SDValue RHS = N->getOperand(1);
+  // The result needs scalarizing, but it is not a given that both operands
+  // do. For instance, AVX-512 has a legal <1 x i1> exponent for FLDEXP.
+  if (getTypeAction(LHS.getValueType()) == TargetLowering::TypeScalarizeVector)
+    LHS = GetScalarizedVector(LHS);
+  else
+    LHS = DAG.getExtractVectorElt(DL, LHS.getValueType().getVectorElementType(),
+                                  LHS, 0);
+  if (getTypeAction(RHS.getValueType()) == TargetLowering::TypeScalarizeVector)
+    RHS = GetScalarizedVector(RHS);
+  else
+    RHS = DAG.getExtractVectorElt(DL, RHS.getValueType().getVectorElementType(),
+                                  RHS, 0);
+  return DAG.getNode(N->getOpcode(), DL, LHS.getValueType(), LHS, RHS,
+                     N->getFlags());
 }
 
 SDValue DAGTypeLegalizer::ScalarizeVecRes_MaskedBinOp(SDNode *N) {
diff --git a/llvm/test/CodeGen/X86/ldexp-v1i1.ll b/llvm/test/CodeGen/X86/ldexp-v1i1.ll
new file mode 100644
index 0000000000000..b6cb4c27a8305
--- /dev/null
+++ b/llvm/test/CodeGen/X86/ldexp-v1i1.ll
@@ -0,0 +1,36 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f | FileCheck %s
+
+; <1 x i1> is a legal type under AVX-512, while <1 x float> and <1 x double>
+; are scalarized. The exponent operand must be extracted rather than looked up
+; as a scalarized vector, which previously crashed type legalization with
+; "TableId should be non-zero".
+
+define <1 x float> @test_v1f32(<1 x float> %x, <1 x i1> %e) nounwind {
+; CHECK-LABEL: test_v1f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    andl $1, %edi
+; CHECK-NEXT:    negl %edi
+; CHECK-NEXT:    callq ldexpf at PLT
+; CHECK-NEXT:    popq %rax
+; CHECK-NEXT:    retq
+  %r = call <1 x float> @llvm.ldexp.v1f32.v1i1(<1 x float> %x, <1 x i1> %e)
+  ret <1 x float> %r
+}
+
+define <1 x double> @test_v1f64(<1 x double> %x, <1 x i1> %e) nounwind {
+; CHECK-LABEL: test_v1f64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    andl $1, %edi
+; CHECK-NEXT:    negl %edi
+; CHECK-NEXT:    callq ldexp at PLT
+; CHECK-NEXT:    popq %rax
+; CHECK-NEXT:    retq
+  %r = call <1 x double> @llvm.ldexp.v1f64.v1i1(<1 x double> %x, <1 x i1> %e)
+  ret <1 x double> %r
+}
+
+declare <1 x float> @llvm.ldexp.v1f32.v1i1(<1 x float>, <1 x i1>) memory(none)
+declare <1 x double> @llvm.ldexp.v1f64.v1i1(<1 x double>, <1 x i1>) memory(none)

``````````

</details>


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


More information about the llvm-commits mailing list