Skip to content

Commit cd6434f

Browse files
[ExpandLargeDivRem] Scalarize vector types. (#86959)
expand-large-divrem cannot handle vector types. If overly large vector element types survive into isel, they will likely be scalarized there, but since isel cannot handle scalar integer types of that size, it will assert. Handle vector types in expand-large-divrem by scalarizing them and then expanding the scalar type operation. For large vectors, this results in a *massive* code expansion, but it's better than asserting.
1 parent 209a1e8 commit cd6434f

File tree

3 files changed

+3803
-8
lines changed

3 files changed

+3803
-8
lines changed

llvm/lib/CodeGen/ExpandLargeDivRem.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,32 @@ static bool isSigned(unsigned int Opcode) {
5454
return Opcode == Instruction::SDiv || Opcode == Instruction::SRem;
5555
}
5656

57+
static void scalarize(BinaryOperator *BO,
58+
SmallVectorImpl<BinaryOperator *> &Replace) {
59+
VectorType *VTy = cast<FixedVectorType>(BO->getType());
60+
61+
IRBuilder<> Builder(BO);
62+
63+
unsigned NumElements = VTy->getElementCount().getFixedValue();
64+
Value *Result = PoisonValue::get(VTy);
65+
for (unsigned Idx = 0; Idx < NumElements; ++Idx) {
66+
Value *LHS = Builder.CreateExtractElement(BO->getOperand(0), Idx);
67+
Value *RHS = Builder.CreateExtractElement(BO->getOperand(1), Idx);
68+
Value *Op = Builder.CreateBinOp(BO->getOpcode(), LHS, RHS);
69+
Result = Builder.CreateInsertElement(Result, Op, Idx);
70+
if (auto *NewBO = dyn_cast<BinaryOperator>(Op)) {
71+
NewBO->copyIRFlags(Op, true);
72+
Replace.push_back(NewBO);
73+
}
74+
}
75+
BO->replaceAllUsesWith(Result);
76+
BO->dropAllReferences();
77+
BO->eraseFromParent();
78+
}
79+
5780
static bool runImpl(Function &F, const TargetLowering &TLI) {
5881
SmallVector<BinaryOperator *, 4> Replace;
82+
SmallVector<BinaryOperator *, 4> ReplaceVector;
5983
bool Modified = false;
6084

6185
unsigned MaxLegalDivRemBitWidth = TLI.getMaxDivRemBitWidthSupported();
@@ -71,16 +95,23 @@ static bool runImpl(Function &F, const TargetLowering &TLI) {
7195
case Instruction::SDiv:
7296
case Instruction::URem:
7397
case Instruction::SRem: {
74-
// TODO: This doesn't handle vectors.
75-
auto *IntTy = dyn_cast<IntegerType>(I.getType());
98+
// TODO: This pass doesn't handle scalable vectors.
99+
if (I.getOperand(0)->getType()->isScalableTy())
100+
continue;
101+
102+
auto *IntTy = dyn_cast<IntegerType>(I.getType()->getScalarType());
76103
if (!IntTy || IntTy->getIntegerBitWidth() <= MaxLegalDivRemBitWidth)
77104
continue;
78105

79106
// The backend has peephole optimizations for powers of two.
107+
// TODO: We don't consider vectors here.
80108
if (isConstantPowerOfTwo(I.getOperand(1), isSigned(I.getOpcode())))
81109
continue;
82110

83-
Replace.push_back(&cast<BinaryOperator>(I));
111+
if (I.getOperand(0)->getType()->isVectorTy())
112+
ReplaceVector.push_back(&cast<BinaryOperator>(I));
113+
else
114+
Replace.push_back(&cast<BinaryOperator>(I));
84115
Modified = true;
85116
break;
86117
}
@@ -89,6 +120,11 @@ static bool runImpl(Function &F, const TargetLowering &TLI) {
89120
}
90121
}
91122

123+
while (!ReplaceVector.empty()) {
124+
BinaryOperator *BO = ReplaceVector.pop_back_val();
125+
scalarize(BO, Replace);
126+
}
127+
92128
if (Replace.empty())
93129
return false;
94130

0 commit comments

Comments
 (0)