Skip to content

Commit b23f59a

Browse files
dtcxzywXChy
andauthored
[InstCombine] Fold select (A &/| B), T, F if select B, T, F is foldable (#76621)
This patch does the following folds: ``` (select A && B, T, F) -> (select A, (select B, T, F), F) (select A || B, T, F) -> (select A, T, (select B, T, F)) ``` if `(select B, T, F)` can be folded into a value or a canonicalized SPF. Alive2: https://alive2.llvm.org/ce/z/4Bdrbu The original motivation of this patch is to simplify the following pattern: ``` %.sroa.speculated.i = tail call i64 @llvm.umax.i64(i64 %sub.ptr.div.i.i, i64 1) %add.i = add i64 %.sroa.speculated.i, %sub.ptr.div.i.i %cmp7.i = icmp ult i64 %add.i, %sub.ptr.div.i.i %cmp9.i = icmp ugt i64 %add.i, 1152921504606846975 %or.cond.i = or i1 %cmp7.i, %cmp9.i %cond.i = select i1 %or.cond.i, i64 1152921504606846975, i64 %add.i -> %.sroa.speculated.i = tail call i64 @llvm.umax.i64(i64 %sub.ptr.div.i.i, i64 1) %add.i = add i64 %.sroa.speculated.i, %sub.ptr.div.i.i %cmp7.i = icmp ult i64 %add.i, %sub.ptr.div.i.i %max = call i64 @llvm.umax.i64(i64 %add.i, 1152921504606846975) %cond.i = select i1 %cmp7.i, i64 1152921504606846975, i64 %max ``` The later form has a better codegen for some backends. It is also more analysis-friendly than the original one. Godbolt: https://godbolt.org/z/eK6eb5jf1 Alive2: https://alive2.llvm.org/ce/z/VHlxL2 Compile-time impact: http://llvm-compile-time-tracker.com/compare.php?from=7c71d3996a72b9b024622f23bf556539b961c88c&to=638ce8666fadaca1ab2639a3c2bc52a4a8508f40&stat=instructions:u |stage1-O3|stage1-ReleaseThinLTO|stage1-ReleaseLTO-g|stage1-O0-g|stage2-O3|stage2-O0-g|stage2-clang| |--|--|--|--|--|--|--| |+0.02%|-0.00%|+0.02%|-0.03%|-0.00%|-0.05%|-0.00%| It is an alternative to #76203 and #76363 because we can simplify `select (icmp eq/ne a, b), a, b` into `b` or `a`. Fixes #75784. Fixes #76043. Thank @XChy for providing additional tests. Co-authored-by: XChy <[email protected]>
1 parent 61999b1 commit b23f59a

File tree

5 files changed

+427
-37
lines changed

5 files changed

+427
-37
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3794,5 +3794,51 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
37943794
if (Instruction *I = foldBitCeil(SI, Builder))
37953795
return I;
37963796

3797+
// Fold:
3798+
// (select A && B, T, F) -> (select A, (select B, T, F), F)
3799+
// (select A || B, T, F) -> (select A, T, (select B, T, F))
3800+
// if (select B, T, F) is foldable.
3801+
// TODO: preserve FMF flags
3802+
auto FoldSelectWithAndOrCond = [&](bool IsAnd, Value *A,
3803+
Value *B) -> Instruction * {
3804+
if (Value *V = simplifySelectInst(B, TrueVal, FalseVal,
3805+
SQ.getWithInstruction(&SI)))
3806+
return SelectInst::Create(A, IsAnd ? V : TrueVal, IsAnd ? FalseVal : V);
3807+
3808+
// Is (select B, T, F) a SPF?
3809+
if (CondVal->hasOneUse() && SelType->isIntOrIntVectorTy()) {
3810+
Value *LHS, *RHS;
3811+
if (ICmpInst *Cmp = dyn_cast<ICmpInst>(B))
3812+
if (Value *V = canonicalizeSPF(*Cmp, TrueVal, FalseVal, *this))
3813+
return SelectInst::Create(A, IsAnd ? V : TrueVal,
3814+
IsAnd ? FalseVal : V);
3815+
}
3816+
3817+
return nullptr;
3818+
};
3819+
3820+
Value *LHS, *RHS;
3821+
if (match(CondVal, m_And(m_Value(LHS), m_Value(RHS)))) {
3822+
if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ true, LHS, RHS))
3823+
return I;
3824+
if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ true, RHS, LHS))
3825+
return I;
3826+
} else if (match(CondVal, m_Or(m_Value(LHS), m_Value(RHS)))) {
3827+
if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ false, LHS, RHS))
3828+
return I;
3829+
if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ false, RHS, LHS))
3830+
return I;
3831+
} else {
3832+
// We cannot swap the operands of logical and/or.
3833+
// TODO: Can we swap the operands by inserting a freeze?
3834+
if (match(CondVal, m_LogicalAnd(m_Value(LHS), m_Value(RHS)))) {
3835+
if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ true, LHS, RHS))
3836+
return I;
3837+
} else if (match(CondVal, m_LogicalOr(m_Value(LHS), m_Value(RHS)))) {
3838+
if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ false, LHS, RHS))
3839+
return I;
3840+
}
3841+
}
3842+
37973843
return nullptr;
37983844
}

0 commit comments

Comments
 (0)