Skip to content

Commit

Permalink
[InstCombine] Fold X sdiv (-1 << C) -> -(X u>> Y) iff X is non-negative
Browse files Browse the repository at this point in the history
This is the one i'm seeing as missed optimization,
although there are likely other possibilities, as usual.

There are 4 variants of a general sdiv->udiv fold:
https://rise4fun.com/Alive/VS6

Name: v0
Pre: C0 >= 0 && C1 >= 0
%r = sdiv i8 C0, C1
  =>
%r = udiv i8 C0, C1

Name: v1
Pre: C0 <= 0 && C1 >= 0
%r = sdiv i8 C0, C1
  =>
%t0 = udiv i8 -C0, C1
%r = sub i8 0, %t0

Name: v2
Pre: C0 >= 0 && C1 <= 0
%r = sdiv i8 C0, C1
  =>
%t0 = udiv i8 C0, -C1
%r = sub i8 0, %t0

Name: v3
Pre: C0 <= 0 && C1 <= 0
%r = sdiv i8 C0, C1
  =>
%r = udiv i8 -C0, -C1


If we really don't like sdiv (more than udiv that is),
and are okay with increasing instruction count (2 new negations),
and we ensure that we don't undo the fold,
then we could just implement these..
  • Loading branch information
LebedevRI committed Jul 17, 2020
1 parent 66b6698 commit 0fdcca0
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 1 deletion.
7 changes: 7 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
Expand Up @@ -1182,6 +1182,13 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
return BO;
}

if (match(Op1, m_NegatedPower2())) {
// X sdiv (-(1 << C)) -> -(X sdiv (1 << C)) ->
// -> -(X udiv (1 << C)) -> -(X u>> C)
return BinaryOperator::CreateNeg(Builder.Insert(foldUDivPow2Cst(
Op0, ConstantExpr::getNeg(cast<Constant>(Op1)), I, *this)));
}

if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) {
// X sdiv (1 << Y) -> X udiv (1 << Y) ( -> X u>> Y)
// Safe because the only negative value (1 << Y) can take on is
Expand Down
Expand Up @@ -13,7 +13,8 @@ define i8 @t0(i8 %x, i8 %y) {
; CHECK-LABEL: @t0(
; CHECK-NEXT: [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -1
; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]])
; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[X]], -32
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[X]], 5
; CHECK-NEXT: [[DIV:%.*]] = sub nsw i8 0, [[TMP1]]
; CHECK-NEXT: ret i8 [[DIV]]
;
%x_is_nonnegative = icmp sge i8 %x, 0
Expand Down

0 comments on commit 0fdcca0

Please sign in to comment.