Skip to content

Commit ce5b88b

Browse files
[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: #66417.
1 parent 5163319 commit ce5b88b

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

+22-9
Original file line numberDiff line numberDiff line change
@@ -2616,20 +2616,33 @@ static Instruction *foldSelectWithSRem(SelectInst &SI, InstCombinerImpl &IC,
26162616
if (!TrueIfSigned)
26172617
std::swap(TrueVal, FalseVal);
26182618

2619-
// We are matching a quite specific pattern here:
2619+
auto FoldToBitwiseAnd = [&](Value *Remainder) -> Instruction * {
2620+
Value *Add = Builder.CreateAdd(
2621+
Remainder, Constant::getAllOnesValue(RemRes->getType()));
2622+
return BinaryOperator::CreateAnd(Op, Add);
2623+
};
2624+
2625+
// Match the general case:
26202626
// %rem = srem i32 %x, %n
26212627
// %cnd = icmp slt i32 %rem, 0
26222628
// %add = add i32 %rem, %n
26232629
// %sel = select i1 %cnd, i32 %add, i32 %rem
2624-
if (!(match(TrueVal, m_Add(m_Value(RemRes), m_Value(Remainder))) &&
2625-
match(RemRes, m_SRem(m_Value(Op), m_Specific(Remainder))) &&
2626-
IC.isKnownToBeAPowerOfTwo(Remainder, /*OrZero*/ true) &&
2627-
FalseVal == RemRes))
2628-
return nullptr;
2630+
if (match(TrueVal, m_Add(m_Value(RemRes), m_Value(Remainder))) &&
2631+
match(RemRes, m_SRem(m_Value(Op), m_Specific(Remainder))) &&
2632+
IC.isKnownToBeAPowerOfTwo(Remainder, /*OrZero*/ true) &&
2633+
FalseVal == RemRes)
2634+
return FoldToBitwiseAnd(Remainder);
2635+
2636+
// Match the case where the one arm has been replaced by constant 1:
2637+
// %rem = srem i32 %n, 2
2638+
// %cnd = icmp slt i32 %rem, 0
2639+
// %sel = select i1 %cnd, i32 1, i32 %rem
2640+
if (match(TrueVal, m_One()) &&
2641+
match(RemRes, m_SRem(m_Value(Op), m_SpecificInt(2))) &&
2642+
FalseVal == RemRes)
2643+
return FoldToBitwiseAnd(ConstantInt::get(RemRes->getType(), 2));
26292644

2630-
Value *Add = Builder.CreateAdd(Remainder,
2631-
Constant::getAllOnesValue(RemRes->getType()));
2632-
return BinaryOperator::CreateAnd(Op, Add);
2645+
return nullptr;
26332646
}
26342647

26352648
static Value *foldSelectWithFrozenICmp(SelectInst &Sel, InstCombiner::BuilderTy &Builder) {

llvm/test/Transforms/InstCombine/select-divrem.ll

+22
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,25 @@ define i8 @rem_euclid_non_const_pow2(i8 %0, i8 %1) {
321321
%sel = select i1 %cond, i8 %add, i8 %rem
322322
ret i8 %sel
323323
}
324+
325+
define i32 @rem_euclid_pow2_true_arm_folded(i32 %n) {
326+
; CHECK-LABEL: @rem_euclid_pow2_true_arm_folded(
327+
; CHECK-NEXT: [[RES:%.*]] = and i32 [[N:%.*]], 1
328+
; CHECK-NEXT: ret i32 [[RES]]
329+
;
330+
%rem = srem i32 %n, 2
331+
%neg = icmp slt i32 %rem, 0
332+
%res = select i1 %neg, i32 1, i32 %rem
333+
ret i32 %res
334+
}
335+
336+
define i32 @rem_euclid_pow2_false_arm_folded(i32 %n) {
337+
; CHECK-LABEL: @rem_euclid_pow2_false_arm_folded(
338+
; CHECK-NEXT: [[RES:%.*]] = and i32 [[N:%.*]], 1
339+
; CHECK-NEXT: ret i32 [[RES]]
340+
;
341+
%rem = srem i32 %n, 2
342+
%nonneg = icmp sge i32 %rem, 0
343+
%res = select i1 %nonneg, i32 %rem, i32 1
344+
ret i32 %res
345+
}

0 commit comments

Comments
 (0)