[InstCombine] Handle constant arms in select of srem fold
Extend folding for `2^n` euclidean division remainder operations on signed integers by handling the specific instance in which one `select` arm has already been replaced by 1. Reported-By: HypheX Fixes: https://github.com/llvm/llvm-project/issues/66417.
This commit is contained in:
parent
5163319ee2
commit
ce5b88bf10
@ -2616,20 +2616,33 @@ static Instruction *foldSelectWithSRem(SelectInst &SI, InstCombinerImpl &IC,
|
||||
if (!TrueIfSigned)
|
||||
std::swap(TrueVal, FalseVal);
|
||||
|
||||
// We are matching a quite specific pattern here:
|
||||
auto FoldToBitwiseAnd = [&](Value *Remainder) -> Instruction * {
|
||||
Value *Add = Builder.CreateAdd(
|
||||
Remainder, Constant::getAllOnesValue(RemRes->getType()));
|
||||
return BinaryOperator::CreateAnd(Op, Add);
|
||||
};
|
||||
|
||||
// Match the general case:
|
||||
// %rem = srem i32 %x, %n
|
||||
// %cnd = icmp slt i32 %rem, 0
|
||||
// %add = add i32 %rem, %n
|
||||
// %sel = select i1 %cnd, i32 %add, i32 %rem
|
||||
if (!(match(TrueVal, m_Add(m_Value(RemRes), m_Value(Remainder))) &&
|
||||
match(RemRes, m_SRem(m_Value(Op), m_Specific(Remainder))) &&
|
||||
IC.isKnownToBeAPowerOfTwo(Remainder, /*OrZero*/ true) &&
|
||||
FalseVal == RemRes))
|
||||
return nullptr;
|
||||
if (match(TrueVal, m_Add(m_Value(RemRes), m_Value(Remainder))) &&
|
||||
match(RemRes, m_SRem(m_Value(Op), m_Specific(Remainder))) &&
|
||||
IC.isKnownToBeAPowerOfTwo(Remainder, /*OrZero*/ true) &&
|
||||
FalseVal == RemRes)
|
||||
return FoldToBitwiseAnd(Remainder);
|
||||
|
||||
Value *Add = Builder.CreateAdd(Remainder,
|
||||
Constant::getAllOnesValue(RemRes->getType()));
|
||||
return BinaryOperator::CreateAnd(Op, Add);
|
||||
// Match the case where the one arm has been replaced by constant 1:
|
||||
// %rem = srem i32 %n, 2
|
||||
// %cnd = icmp slt i32 %rem, 0
|
||||
// %sel = select i1 %cnd, i32 1, i32 %rem
|
||||
if (match(TrueVal, m_One()) &&
|
||||
match(RemRes, m_SRem(m_Value(Op), m_SpecificInt(2))) &&
|
||||
FalseVal == RemRes)
|
||||
return FoldToBitwiseAnd(ConstantInt::get(RemRes->getType(), 2));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Value *foldSelectWithFrozenICmp(SelectInst &Sel, InstCombiner::BuilderTy &Builder) {
|
||||
|
||||
@ -321,3 +321,25 @@ define i8 @rem_euclid_non_const_pow2(i8 %0, i8 %1) {
|
||||
%sel = select i1 %cond, i8 %add, i8 %rem
|
||||
ret i8 %sel
|
||||
}
|
||||
|
||||
define i32 @rem_euclid_pow2_true_arm_folded(i32 %n) {
|
||||
; CHECK-LABEL: @rem_euclid_pow2_true_arm_folded(
|
||||
; CHECK-NEXT: [[RES:%.*]] = and i32 [[N:%.*]], 1
|
||||
; CHECK-NEXT: ret i32 [[RES]]
|
||||
;
|
||||
%rem = srem i32 %n, 2
|
||||
%neg = icmp slt i32 %rem, 0
|
||||
%res = select i1 %neg, i32 1, i32 %rem
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
define i32 @rem_euclid_pow2_false_arm_folded(i32 %n) {
|
||||
; CHECK-LABEL: @rem_euclid_pow2_false_arm_folded(
|
||||
; CHECK-NEXT: [[RES:%.*]] = and i32 [[N:%.*]], 1
|
||||
; CHECK-NEXT: ret i32 [[RES]]
|
||||
;
|
||||
%rem = srem i32 %n, 2
|
||||
%nonneg = icmp sge i32 %rem, 0
|
||||
%res = select i1 %nonneg, i32 %rem, i32 1
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user