[PATCH] D61160: [SimplifyCFG] Implement the suggested ctlz transform
James Molloy via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed May 1 01:58:46 PDT 2019
jmolloy requested changes to this revision.
jmolloy added inline comments.
This revision now requires changes to proceed.
================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:5520
+ bool Cttz = false;
+ while (true) {
+ bool GotCollision = false;
----------------
This loop is scary and hard to read. It's really asking for a helper function. I would do something like this:
// Given a set of equivalence classes, return true if, for every pair A, B in
// Values:
// Fn(A) == Fn(B) if and only if EC(A) == EC(B).
template <typename Function>
bool IsBijectiveOverEquivalenceClasses(const EquivalenceClasses<APInt> &Values,
const Function &Fn) {
DenseMap<unsigned, APInt> Leaders;
for (auto &V : Values) {
auto TransformedValue = Fn(V.getData());
auto LeaderIt = Leaders.find(TransformedValue);
if (LeadersIt == Leaders.end()) {
Leaders[TransformedValue] = V.getLeader()->getData();
continue;
}
if (LeaderIt->getData() != V.getData())
// This transformed value has already been seen and did not belong to the
// same equivalence class. This is not a bijective relation.
return false;
}
return true;
}
static bool CanReduceSwitchRangeWithCtlzOrCttz(SwitchInst &SI, bool &UseCtlz,
bool &UseCttz, bool &UseInvert) {
// Preconstruct equivalence classes of values based on successor block.
DenseMap<BasicBlock *, APInt> Last;
EquivalenceClasses<APInt> ECs;
for (auto CI : SI.cases()) {
auto I = Last.try_emplace(CI.getCaseSuccessor(), CI.getCaseValue()).first;
ECs.unionSets(I.second, V);
}
UseInvert = false;
UseCtlz = true;
if (IsBijectiveOverEquivalenceClasses(
ECs, [&](const APInt &V) { return V.countLeadingZeros(); }))
return true;
UseCtlz = false;
if (IsBijectiveOverEquivalenceClasses(
ECs, [&](const APInt &V) { return V.countTrailingZeros(); }))
return true;
UseInvert = true;
UseCtlz = true;
if (IsBijectiveOverEquivalenceClasses(
ECs, [&](const APInt &V) { return (~V).countLeadingZeros(); }))
return true;
UseCtlz = false;
if (IsBijectiveOverEquivalenceClasses(
ECs, [&](const APInt &V) { return (~V).countTrailingZeros(); }))
return true;
return false;
}
static bool ReduceSwitchRangeWithCtlzOrCttz(SwitchInst &SI,
SmallVectorImpl<uint64_t> &Values,
bool &UseCtlz, bool &UseCttz,
bool &UseInvert) {
// Note we don't pass Values into this function. This predicate uses the
// switch's current case values *and* their associated successor block, so a
// rearranged Values array cannot be analyzed (because we wouldn't know which
// successsor belonged to which value).
if (!CanReduceSwitchRangeWithCtlzOrCttz(SI, UseCtlz, UseCttz, UseInvert))
return false;
for (auto CI : SI.cases()) {
APInt I = CI.getCaseValue();
if (UseCtlz)
Values.push_back((Invert ? ~V : V).countTrailingZeros());
else
Values.push_back((Invert ? ~V : V).countLeadingZeros());
}
llvm::sort(Values);
return true;
}
================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:5532
+ if (Got & (1ULL << Ctz)) {
+ if (&*SI.findCaseValue(ConstantInt::get(
+ SI.getContext(), Invert ? ~Int : Int)) == Prev[Ctz])
----------------
This is a fallacy (will always be false) because:
# SwitchInst::CaseHandle is unique based on switched value. There is one CaseHandle for every value in Values.
# Prev is zero-initialized just above this line, in the loop.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D61160/new/
https://reviews.llvm.org/D61160
More information about the llvm-commits
mailing list