Instcombine x-((x/y)*y) into a remainder operator.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42035 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2007-09-17 17:31:57 +00:00
parent baa2fa5823
commit 5d066ff7f0
3 changed files with 28 additions and 1 deletions

View File

@ -2257,6 +2257,17 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
Constant *CP1 = Subtract(ConstantInt::get(I.getType(), 1), C2);
return BinaryOperator::createMul(Op0, CP1);
}
// X - ((X / Y) * Y) --> X % Y
if (Op1I->getOpcode() == Instruction::Mul)
if (Instruction *I = dyn_cast<Instruction>(Op1I->getOperand(0)))
if (Op0 == I->getOperand(0) &&
Op1I->getOperand(1) == I->getOperand(1)) {
if (I->getOpcode() == Instruction::SDiv)
return BinaryOperator::createSRem(Op0, Op1I->getOperand(1));
if (I->getOpcode() == Instruction::UDiv)
return BinaryOperator::createURem(Op0, Op1I->getOperand(1));
}
}
}
@ -2902,7 +2913,7 @@ static unsigned getICmpCode(const ICmpInst *ICI) {
/// getICmpValue - This is the complement of getICmpCode, which turns an
/// opcode and two operands into either a constant true or false, or a brand
/// new /// ICmp instruction. The sign is passed in to determine which kind
/// new ICmp instruction. The sign is passed in to determine which kind
/// of predicate to use in new icmp instructions.
static Value *getICmpValue(bool sign, unsigned code, Value *LHS, Value *RHS) {
switch (code) {

View File

@ -0,0 +1,8 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep srem
define i64 @foo(i64 %x1, i64 %y2) {
%r = sdiv i64 %x1, %y2
%r7 = mul i64 %r, %y2
%r8 = sub i64 %x1, %r7
ret i64 %r8
}

View File

@ -0,0 +1,8 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep urem
define i64 @rem_unsigned(i64 %x1, i64 %y2) {
%r = udiv i64 %x1, %y2
%r7 = mul i64 %r, %y2
%r8 = sub i64 %x1, %r7
ret i64 %r8
}