1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 20:12:56 +02:00

Allow pulling logical operations through shifts.

This implements InstCombine/shift.ll:test14*

llvm-svn: 7793
This commit is contained in:
Chris Lattner 2003-08-12 21:53:41 +00:00
parent 7105c4aad0
commit 3e52e8ce5a

View File

@ -15,8 +15,8 @@
// This pass guarantees that the following cannonicalizations are performed on
// the program:
// 1. If a binary operator has a constant operand, it is moved to the RHS
// 2. Logical operators with constant operands are always grouped so that
// 'or's are performed first, then 'and's, then 'xor's.
// 2. Bitwise operators with constant operands are always grouped so that
// shifts are performed first, then or's, then and's, then xor's.
// 3. SetCC instructions are converted from <,>,<=,>= to ==,!= if possible
// 4. All SetCC instructions on boolean values are replaced with logical ops
// N. This list is incomplete
@ -879,6 +879,7 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
assert(I.getOperand(1)->getType() == Type::UByteTy);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
bool isLeftShift = I.getOpcode() == Instruction::Shl;
// shl X, 0 == X and shr X, 0 == X
// shl 0, X == 0 and shr 0, X == 0
@ -886,17 +887,68 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
Op0 == Constant::getNullValue(Op0->getType()))
return ReplaceInstUsesWith(I, Op0);
// shr int -1, X = -1 (for any arithmetic shift rights of ~0)
if (!isLeftShift)
if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op0))
if (CSI->isAllOnesValue())
return ReplaceInstUsesWith(I, CSI);
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1)) {
// shl uint X, 32 = 0 and shr ubyte Y, 9 = 0, ... just don't eliminate shr
// of a signed value.
//
unsigned TypeBits = Op0->getType()->getPrimitiveSize()*8;
if (CUI->getValue() >= TypeBits &&
(!Op0->getType()->isSigned() || I.getOpcode() == Instruction::Shl))
(!Op0->getType()->isSigned() || isLeftShift))
return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType()));
// If the operand is an bitwise operator with a constant RHS, and the
// shift is the only use, we can pull it out of the shift.
if (Op0->use_size() == 1)
if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0))
if (ConstantInt *Op0C = dyn_cast<ConstantInt>(Op0BO->getOperand(1))) {
bool isValid = true; // Valid only for And, Or, Xor
bool highBitSet = false; // Transform if high bit of constant set?
switch (Op0BO->getOpcode()) {
default: isValid = false; break; // Do not perform transform!
case Instruction::Or:
case Instruction::Xor:
highBitSet = false;
break;
case Instruction::And:
highBitSet = true;
break;
}
// If this is a signed shift right, and the high bit is modified
// by the logical operation, do not perform the transformation.
// The highBitSet boolean indicates the value of the high bit of
// the constant which would cause it to be modified for this
// operation.
//
if (isValid && !isLeftShift && !I.getType()->isUnsigned()) {
uint64_t Val = Op0C->getRawValue();
isValid = ((Val & (1 << (TypeBits-1))) != 0) == highBitSet;
}
if (isValid) {
Constant *NewRHS =
ConstantFoldShiftInstruction(I.getOpcode(), Op0C, CUI);
Instruction *NewShift =
new ShiftInst(I.getOpcode(), Op0BO->getOperand(0), CUI,
Op0BO->getName());
Op0BO->setName("");
InsertNewInstBefore(NewShift, I);
return BinaryOperator::create(Op0BO->getOpcode(), NewShift,
NewRHS);
}
}
// If this is a shift of a shift, see if we can fold the two together...
if (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0)) {
if (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0))
if (ConstantUInt *ShiftAmt1C =
dyn_cast<ConstantUInt>(Op0SI->getOperand(1))) {
unsigned ShiftAmt1 = ShiftAmt1C->getValue();
@ -912,13 +964,13 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
// Check for (A << c1) >> c2 or visaversa. If we are dealing with
// signed types, we can only support the (A >> c1) << c2 configuration,
// because it can not turn an arbitrary bit of A into a sign bit.
if (I.getType()->isUnsigned() || I.getOpcode() == Instruction::Shl) {
if (I.getType()->isUnsigned() || isLeftShift) {
// Calculate bitmask for what gets shifted off the edge...
Constant *C = ConstantIntegral::getAllOnesValue(I.getType());
if (I.getOpcode() == Instruction::Shr)
C = ConstantExpr::getShift(Instruction::Shr, C, ShiftAmt1C);
else
if (isLeftShift)
C = ConstantExpr::getShift(Instruction::Shl, C, ShiftAmt1C);
else
C = ConstantExpr::getShift(Instruction::Shr, C, ShiftAmt1C);
Instruction *Mask =
BinaryOperator::create(Instruction::And, Op0SI->getOperand(0),
@ -937,21 +989,14 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
}
}
}
}
// Check to see if we are shifting left by 1. If so, turn it into an add
// instruction.
if (I.getOpcode() == Instruction::Shl && CUI->equalsInt(1))
if (isLeftShift && CUI->equalsInt(1))
// Convert 'shl int %X, 1' to 'add int %X, %X'
return BinaryOperator::create(Instruction::Add, Op0, Op0, I.getName());
}
// shr int -1, X = -1 (for any arithmetic shift rights of ~0)
if (I.getOpcode() == Instruction::Shr)
if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op0))
if (CSI->isAllOnesValue())
return ReplaceInstUsesWith(I, CSI);
return 0;
}