[llvm] [DAGCombiner] Handle type-promoted constants in UDIV lowering (PR #169491)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 12 21:12:04 PST 2025


topperc wrote:

> > > We're hitting an assert after this change:
> > > ```
> > > llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:989: void (anonymous namespace)::SelectionDAGLegalize::LegalizeOp(SDNode *): Assertion `(TLI.getTypeAction(*DAG.getContext(), Op.getValueType()) == TargetLowering::TypeLegal || Op.getOpcode() == ISD::TargetConstant || Op.getOpcode() == ISD::Register) && "Unexpected illegal type!"' failed.
> > > ```
> > 
> > 
> > We ran into the same issue on LoongArch, and here's a [reduced reproducer](https://github.com/llvm/llvm-project/issues/170976) that may help with the investigation.
> > After this PR, DAGCombiner ends up expanding `UDIV` after type legalization, introducing nodes that include logical right shifts on illegal types.
> > On the LoongArch side, we addressed this by implementing custom target-specific lowering for logical shift right nodes (#171097), preventing the generic DAG-level optimizations from generating such illegal constructs.
> 
> We should just need to make the BUILD_VECTOR created by the UDIV combine use a legal type for the scalar elements when NewNodesMustHaveLegalTypes is set.

Here's a patch based on the LoongArch failures

```
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index bf26fec28763..474c504b8a16 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -6707,6 +6707,15 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
   unsigned EltBits = VT.getScalarSizeInBits();
   EVT MulVT;
 
+  if (IsAfterLegalTypes && VT.isVector()) {
+    SVT = getTypeToTransformTo(*DAG.getContext(), SVT);
+    if (SVT.bitsLT(VT.getScalarType()))
+      return SDValue();
+    ShSVT = getTypeToTransformTo(*DAG.getContext(), ShSVT);
+    if (ShSVT.bitsLT(ShVT.getScalarType()))
+      return SDValue();
+  }
+
   // Check to see if we can do this.
   // FIXME: We should be more aggressive here.
   if (!isTypeLegal(VT)) {
@@ -6758,7 +6767,8 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
           UnsignedDivisionByConstantInfo::get(
               Divisor, std::min(KnownLeadingZeros, Divisor.countl_zero()));
 
-      MagicFactor = DAG.getConstant(magics.Magic, dl, SVT);
+      MagicFactor = DAG.getConstant(
+          magics.Magic.zext(SVT.getScalarSizeInBits()), dl, SVT);
 
       assert(magics.PreShift < Divisor.getBitWidth() &&
              "We shouldn't generate an undefined shift!");
@@ -6769,8 +6779,9 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
       PreShift = DAG.getConstant(magics.PreShift, dl, ShSVT);
       PostShift = DAG.getConstant(magics.PostShift, dl, ShSVT);
       NPQFactor = DAG.getConstant(
-          magics.IsAdd ? APInt::getOneBitSet(EltBits, EltBits - 1)
-                       : APInt::getZero(EltBits),
+          magics.IsAdd
+              ? APInt::getOneBitSet(SVT.getScalarSizeInBits(), EltBits - 1)
+              : APInt::getZero(SVT.getScalarSizeInBits()),
           dl, SVT);
       UseNPQ |= magics.IsAdd;
       UsePreShift |= magics.PreShift != 0;
```

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


More information about the llvm-commits mailing list