Rearrange some code, fold "rem X, 0", implementing rem.ll:test6

llvm-svn: 26411
This commit is contained in:
Chris Lattner 2006-02-28 05:30:45 +00:00
parent 9fed5b6122
commit 0de4a8d7b7
1 changed files with 39 additions and 38 deletions

View File

@ -1814,6 +1814,17 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
Instruction *InstCombiner::visitRem(BinaryOperator &I) { Instruction *InstCombiner::visitRem(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// 0 % X == 0, we don't need to preserve faults!
if (Constant *LHS = dyn_cast<Constant>(Op0))
if (LHS->isNullValue())
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
if (isa<UndefValue>(Op0)) // undef % X -> 0
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
if (isa<UndefValue>(Op1))
return ReplaceInstUsesWith(I, Op1); // X % undef -> undef
if (I.getType()->isSigned()) { if (I.getType()->isSigned()) {
if (Value *RHSNeg = dyn_castNegVal(Op1)) if (Value *RHSNeg = dyn_castNegVal(Op1))
if (!isa<ConstantSInt>(RHSNeg) || if (!isa<ConstantSInt>(RHSNeg) ||
@ -1842,22 +1853,19 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
} }
} }
if (isa<UndefValue>(Op0)) // undef % X -> 0
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
if (isa<UndefValue>(Op1))
return ReplaceInstUsesWith(I, Op1); // X % undef -> undef
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) { if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// X % 0 == undef, we don't need to preserve faults!
if (RHS->equalsInt(0))
return ReplaceInstUsesWith(I, UndefValue::get(I.getType()));
if (RHS->equalsInt(1)) // X % 1 == 0 if (RHS->equalsInt(1)) // X % 1 == 0
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
// Check to see if this is an unsigned remainder with an exact power of 2, // Check to see if this is an unsigned remainder with an exact power of 2,
// if so, convert to a bitwise and. // if so, convert to a bitwise and.
if (ConstantUInt *C = dyn_cast<ConstantUInt>(RHS)) if (ConstantUInt *C = dyn_cast<ConstantUInt>(RHS))
if (uint64_t Val = C->getValue()) // Don't break X % 0 (divide by zero) if (isPowerOf2_64(C->getValue()))
if (!(Val & (Val-1))) // Power of 2 return BinaryOperator::createAnd(Op0, SubOne(C));
return BinaryOperator::createAnd(Op0,
ConstantUInt::get(I.getType(), Val-1));
if (!RHS->isNullValue()) { if (!RHS->isNullValue()) {
if (SelectInst *SI = dyn_cast<SelectInst>(Op0)) if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
@ -1869,35 +1877,6 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
} }
} }
// If this is 'urem X, (Cond ? C1, C2)' where C1&C2 are powers of two,
// transform this into: '(Cond ? (urem X, C1) : (urem X, C2))'.
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
if (ConstantUInt *STO = dyn_cast<ConstantUInt>(SI->getOperand(1)))
if (ConstantUInt *SFO = dyn_cast<ConstantUInt>(SI->getOperand(2))) {
if (STO->getValue() == 0) { // Couldn't be this argument.
I.setOperand(1, SFO);
return &I;
} else if (SFO->getValue() == 0) {
I.setOperand(1, STO);
return &I;
}
if (!(STO->getValue() & (STO->getValue()-1)) &&
!(SFO->getValue() & (SFO->getValue()-1))) {
Value *TrueAnd = InsertNewInstBefore(BinaryOperator::createAnd(Op0,
SubOne(STO), SI->getName()+".t"), I);
Value *FalseAnd = InsertNewInstBefore(BinaryOperator::createAnd(Op0,
SubOne(SFO), SI->getName()+".f"), I);
return new SelectInst(SI->getOperand(0), TrueAnd, FalseAnd);
}
}
// 0 % X == 0, we don't need to preserve faults!
if (ConstantInt *LHS = dyn_cast<ConstantInt>(Op0))
if (LHS->equalsInt(0))
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) { if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
// Turn A % (C << N), where C is 2^k, into A & ((C << N)-1) [urem only]. // Turn A % (C << N), where C is 2^k, into A & ((C << N)-1) [urem only].
if (I.getType()->isUnsigned() && if (I.getType()->isUnsigned() &&
@ -1911,6 +1890,28 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
return BinaryOperator::createAnd(Op0, Add); return BinaryOperator::createAnd(Op0, Add);
} }
} }
// If this is 'urem X, (Cond ? C1, C2)' where C1&C2 are powers of two,
// transform this into: '(Cond ? (urem X, C1) : (urem X, C2))'.
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
if (ConstantUInt *STO = dyn_cast<ConstantUInt>(SI->getOperand(1)))
if (ConstantUInt *SFO = dyn_cast<ConstantUInt>(SI->getOperand(2))) {
if (STO->getValue() == 0) { // Couldn't be this argument.
I.setOperand(1, SFO);
return &I;
} else if (SFO->getValue() == 0) {
I.setOperand(1, STO);
return &I;
}
if (isPowerOf2_64(STO->getValue()) && isPowerOf2_64(SFO->getValue())){
Value *TrueAnd = InsertNewInstBefore(BinaryOperator::createAnd(Op0,
SubOne(STO), SI->getName()+".t"), I);
Value *FalseAnd = InsertNewInstBefore(BinaryOperator::createAnd(Op0,
SubOne(SFO), SI->getName()+".f"), I);
return new SelectInst(SI->getOperand(0), TrueAnd, FalseAnd);
}
}
} }
return 0; return 0;