[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