Skip to content

Commit aa2d053

Browse files
committed
[GloalISel] Fold G_CTTZ if possible
This patch tries to fold `G_CTTZ` if possible.
1 parent 7564566 commit aa2d053

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

llvm/include/llvm/CodeGen/GlobalISel/Utils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,11 @@ std::optional<APFloat> ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy,
313313
std::optional<SmallVector<unsigned>>
314314
ConstantFoldCTLZ(Register Src, const MachineRegisterInfo &MRI);
315315

316+
/// Tries to constant fold a G_CTTZ operation on \p Src. If \p Src is a vector
317+
/// then it tries to do an element-wise constant fold.
318+
std::optional<SmallVector<unsigned>>
319+
ConstantFoldCTTZ(Register Src, const MachineRegisterInfo &MRI);
320+
316321
/// Test if the given value is known to have exactly one bit set. This differs
317322
/// from computeKnownBits in that it doesn't necessarily determine which bit is
318323
/// set.

llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,22 @@ MachineInstrBuilder CSEMIRBuilder::buildInstr(unsigned Opc,
272272
buildConstant(VecTy.getScalarType(), Cst).getReg(0));
273273
return buildBuildVector(DstOps[0], ConstantRegs);
274274
}
275+
case TargetOpcode::G_CTTZ: {
276+
assert(SrcOps.size() == 1 && "Expected one source");
277+
assert(DstOps.size() == 1 && "Expected one dest");
278+
auto MaybeCsts = ConstantFoldCTTZ(SrcOps[0].getReg(), *getMRI());
279+
if (!MaybeCsts)
280+
break;
281+
if (MaybeCsts->size() == 1)
282+
return buildConstant(DstOps[0], (*MaybeCsts)[0]);
283+
// This was a vector constant. Build a G_BUILD_VECTOR for them.
284+
SmallVector<Register> ConstantRegs;
285+
LLT VecTy = DstOps[0].getLLTTy(*getMRI());
286+
for (unsigned Cst : *MaybeCsts)
287+
ConstantRegs.emplace_back(
288+
buildConstant(VecTy.getScalarType(), Cst).getReg(0));
289+
return buildBuildVector(DstOps[0], ConstantRegs);
290+
}
275291
}
276292
bool CanCopy = checkCopyToDefsPossible(DstOps);
277293
if (!canPerformCSEForOpc(Opc))

llvm/lib/CodeGen/GlobalISel/Utils.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,37 @@ llvm::ConstantFoldCTLZ(Register Src, const MachineRegisterInfo &MRI) {
996996
return std::nullopt;
997997
}
998998

999+
std::optional<SmallVector<unsigned>>
1000+
llvm::ConstantFoldCTTZ(Register Src, const MachineRegisterInfo &MRI) {
1001+
LLT Ty = MRI.getType(Src);
1002+
SmallVector<unsigned> FoldedCTTZs;
1003+
auto tryFoldScalar = [&](Register R) -> std::optional<unsigned> {
1004+
auto MaybeCst = getIConstantVRegVal(R, MRI);
1005+
if (!MaybeCst)
1006+
return std::nullopt;
1007+
return MaybeCst->countTrailingZeros();
1008+
};
1009+
if (Ty.isVector()) {
1010+
// Try to constant fold each element.
1011+
auto *BV = getOpcodeDef<GBuildVector>(Src, MRI);
1012+
if (!BV)
1013+
return std::nullopt;
1014+
for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) {
1015+
if (auto MaybeFold = tryFoldScalar(BV->getSourceReg(SrcIdx))) {
1016+
FoldedCTTZs.emplace_back(*MaybeFold);
1017+
continue;
1018+
}
1019+
return std::nullopt;
1020+
}
1021+
return FoldedCTTZs;
1022+
}
1023+
if (auto MaybeCst = tryFoldScalar(Src)) {
1024+
FoldedCTTZs.emplace_back(*MaybeCst);
1025+
return FoldedCTTZs;
1026+
}
1027+
return std::nullopt;
1028+
}
1029+
9991030
bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
10001031
GISelKnownBits *KB) {
10011032
std::optional<DefinitionAndSourceRegister> DefSrcReg =

0 commit comments

Comments
 (0)