Skip to content

Commit 9ddff66

Browse files
committed
1 parent c94d104 commit 9ddff66

File tree

3 files changed

+179
-143
lines changed

3 files changed

+179
-143
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,6 +2669,80 @@ foldRoundUpIntegerWithPow2Alignment(SelectInst &SI,
26692669
return R;
26702670
}
26712671

2672+
/// Look for patterns like
2673+
/// %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false
2674+
/// %inner.sel = select i1 %inner.cond, i8 %inner.sel.t, i8 %inner.sel.f
2675+
/// %outer.sel = select i1 %outer.cond, i8 %outer.sel.t, i8 %inner.sel
2676+
/// and rewrite it as
2677+
/// %inner.sel = select i1 %cond.alternative, i8 %sel.outer.t, i8 %sel.inner.t
2678+
/// %sel.outer = select i1 %cond.inner, i8 %inner.sel, i8 %sel.inner.f
2679+
static Instruction *foldNestedSelects(SelectInst &OuterSel,
2680+
InstCombiner::BuilderTy &Builder) {
2681+
// We must start with a `select`.
2682+
Value *OuterCond, *InnerSel, *OuterSelFalseVal;
2683+
match(&OuterSel, m_Select(m_Value(OuterCond), m_Value(InnerSel),
2684+
m_Value(OuterSelFalseVal)));
2685+
2686+
// Canonicalize inversion of the outermost `select`'s condition.
2687+
if (match(OuterCond, m_Not(m_Value(OuterCond))))
2688+
std::swap(InnerSel, OuterSelFalseVal);
2689+
2690+
auto m_c_LogicalOp = [](auto L, auto R) {
2691+
return m_CombineOr(m_c_LogicalAnd(L, R), m_c_LogicalOr(L, R));
2692+
};
2693+
2694+
// The condition of the outermost select must be an `and`/`or`.
2695+
if (!match(OuterCond, m_c_LogicalOp(m_Value(), m_Value())))
2696+
return nullptr;
2697+
2698+
// To simplify logic, prefer the pattern variant with an `or`.
2699+
bool IsAndVariant = match(OuterCond, m_LogicalAnd());
2700+
if (match(OuterCond, m_LogicalAnd()))
2701+
std::swap(InnerSel, OuterSelFalseVal);
2702+
2703+
// Profitability check - avoid increasing instruction count.
2704+
if (none_of(ArrayRef<Value *>({OuterCond, InnerSel}),
2705+
[](Value *V) { return V->hasOneUse(); }))
2706+
return nullptr;
2707+
2708+
// The appropriate hand of the outermost `select` must be a select itself.
2709+
Value *InnerCond, *InnerSelTrueVal, *InnerSelFalseVal;
2710+
if (!match(InnerSel, m_Select(m_Value(InnerCond), m_Value(InnerSelTrueVal),
2711+
m_Value(InnerSelFalseVal))))
2712+
return nullptr;
2713+
2714+
// Canonicalize inversion of the innermost `select`'s condition.
2715+
if (match(InnerCond, m_Not(m_Value(InnerCond))))
2716+
std::swap(InnerSelTrueVal, InnerSelFalseVal);
2717+
2718+
Value *AltCond = nullptr;
2719+
auto matchOuterCond = [OuterCond, m_c_LogicalOp, &AltCond](auto m_InnerCond) {
2720+
return match(OuterCond, m_c_LogicalOp(m_InnerCond, m_Value(AltCond)));
2721+
};
2722+
2723+
// Finally, match the condition that was driving the outermost `select`,
2724+
// it should be a logical operation between the condition that was driving
2725+
// the innermost `select` (after accounting for the possible inversions
2726+
// of the condition), and some other condition.
2727+
if (matchOuterCond(m_Specific(InnerCond))) {
2728+
// Done!
2729+
} else if (Value * NotInnerCond; matchOuterCond(m_CombineAnd(
2730+
m_Not(m_Specific(InnerCond)), m_Value(NotInnerCond)))) {
2731+
// Done!
2732+
std::swap(InnerSelTrueVal, InnerSelFalseVal);
2733+
InnerCond = NotInnerCond;
2734+
} else // Not the pattern we were looking for.
2735+
return nullptr;
2736+
2737+
Value *SelInner = Builder.CreateSelect(
2738+
AltCond, IsAndVariant ? OuterSelFalseVal : InnerSelFalseVal,
2739+
IsAndVariant ? InnerSelTrueVal : OuterSelFalseVal);
2740+
SelInner->takeName(InnerSel);
2741+
return SelectInst::Create(InnerCond,
2742+
IsAndVariant ? SelInner : InnerSelTrueVal,
2743+
IsAndVariant ? InnerSelFalseVal : SelInner);
2744+
}
2745+
26722746
Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
26732747
Value *CondVal = SI.getCondition();
26742748
Value *TrueVal = SI.getTrueValue();
@@ -3292,5 +3366,8 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
32923366
}
32933367
}
32943368

3369+
if (Instruction *I = foldNestedSelects(SI, Builder))
3370+
return I;
3371+
32953372
return nullptr;
32963373
}

0 commit comments

Comments
 (0)