Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 56f90d7

Browse files
committed
[InstCombine] Teach the udiv folding logic how to handle constant expressions.
This patch fixes PR30366. Function foldUDivShl() worked under the assumption that one of the values in input to the function was always an instance of llvm::Instruction. However, function visitUDivOperand() (the only user of foldUDivShl) was clearly violating that precondition; internally, visitUDivOperand() uses pattern matches to check the operands of a udiv. Pattern matchers for binary operators know how to handle both Instruction and ConstantExpr values. This patch fixes the problem in foldUDivShl(). Now we use pattern matchers instead of explicit casts to Instruction. The reduced test case from PR30366 has been added to test file InstCombine/udiv-simplify.ll. Differential Revision: https://reviews.llvm.org/D24565 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282398 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 679be7e commit 56f90d7

File tree

2 files changed

+29
-11
lines changed

2 files changed

+29
-11
lines changed

lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -991,19 +991,22 @@ static Instruction *foldUDivNegCst(Value *Op0, Value *Op1,
991991
}
992992

993993
// X udiv (C1 << N), where C1 is "1<<C2" --> X >> (N+C2)
994+
// X udiv (zext (C1 << N)), where C1 is "1<<C2" --> X >> (N+C2)
994995
static Instruction *foldUDivShl(Value *Op0, Value *Op1, const BinaryOperator &I,
995996
InstCombiner &IC) {
996-
Instruction *ShiftLeft = cast<Instruction>(Op1);
997-
if (isa<ZExtInst>(ShiftLeft))
998-
ShiftLeft = cast<Instruction>(ShiftLeft->getOperand(0));
999-
1000-
const APInt &CI =
1001-
cast<Constant>(ShiftLeft->getOperand(0))->getUniqueInteger();
1002-
Value *N = ShiftLeft->getOperand(1);
1003-
if (CI != 1)
1004-
N = IC.Builder->CreateAdd(N, ConstantInt::get(N->getType(), CI.logBase2()));
1005-
if (ZExtInst *Z = dyn_cast<ZExtInst>(Op1))
1006-
N = IC.Builder->CreateZExt(N, Z->getDestTy());
997+
Value *ShiftLeft;
998+
if (!match(Op1, m_ZExt(m_Value(ShiftLeft))))
999+
ShiftLeft = Op1;
1000+
1001+
const APInt *CI;
1002+
Value *N;
1003+
if (!match(ShiftLeft, m_Shl(m_APInt(CI), m_Value(N))))
1004+
llvm_unreachable("match should never fail here!");
1005+
if (*CI != 1)
1006+
N = IC.Builder->CreateAdd(N,
1007+
ConstantInt::get(N->getType(), CI->logBase2()));
1008+
if (Op1 != ShiftLeft)
1009+
N = IC.Builder->CreateZExt(N, Op1->getType());
10071010
BinaryOperator *LShr = BinaryOperator::CreateLShr(Op0, N);
10081011
if (I.isExact())
10091012
LShr->setIsExact();

test/Transforms/InstCombine/udiv-simplify.ll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,18 @@ define i64 @test2_PR2274(i32 %x, i32 %v) nounwind {
4747
%z = sext i32 %r to i64
4848
ret i64 %z
4949
}
50+
51+
; The udiv should be simplified according to the rule:
52+
; X udiv (C1 << N), where C1 is `1<<C2` --> X >> (N+C2)
53+
@b = external global [1 x i16]
54+
55+
define i32 @PR30366(i1 %a) {
56+
; CHECK-LABEL: @PR30366(
57+
; CHECK-NEXT: [[Z:%.*]] = zext i1 %a to i32
58+
; CHECK-NEXT: [[D:%.*]] = lshr i32 [[Z]], zext (i16 ptrtoint ([1 x i16]* @b to i16) to i32)
59+
; CHECK-NEXT: ret i32 [[D]]
60+
;
61+
%z = zext i1 %a to i32
62+
%d = udiv i32 %z, zext (i16 shl (i16 1, i16 ptrtoint ([1 x i16]* @b to i16)) to i32)
63+
ret i32 %d
64+
}

0 commit comments

Comments
 (0)