forked from OSchip/llvm-project
This is a bulk commit that implements the following primary improvements:
* We can now fold cast instructions into select instructions that have at least one constant operand. * We now optimize expressions more aggressively based on bits that are known to be zero. These optimizations occur a lot in code that uses bitfields even in simple ways. * We now turn more cast-cast sequences into AND instructions. Before we would only do this if it if all types were unsigned. Now only the middle type needs to be unsigned (guaranteeing a zero extend). * We transform sign extensions into zero extensions in several cases. This corresponds to these test/Regression/Transforms/InstCombine testcases: 2004-11-22-Missed-and-fold.ll and.ll: test28-29 cast.ll: test21-24 and-or-and.ll cast-cast-to-and.ll zeroext-and-reduce.ll llvm-svn: 19220
This commit is contained in:
parent
da15d4ba49
commit
86102b8ad5
|
@ -486,31 +486,60 @@ struct AddMaskingAnd {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static Value *FoldOperationIntoSelectOperand(Instruction &BI, Value *SO,
|
static Value *FoldOperationIntoSelectOperand(Instruction &I, Value *SO,
|
||||||
InstCombiner *IC) {
|
InstCombiner *IC) {
|
||||||
|
if (isa<CastInst>(I)) {
|
||||||
|
if (Constant *SOC = dyn_cast<Constant>(SO))
|
||||||
|
return ConstantExpr::getCast(SOC, I.getType());
|
||||||
|
|
||||||
|
return IC->InsertNewInstBefore(new CastInst(SO, I.getType(),
|
||||||
|
SO->getName() + ".cast"), I);
|
||||||
|
}
|
||||||
|
|
||||||
// Figure out if the constant is the left or the right argument.
|
// Figure out if the constant is the left or the right argument.
|
||||||
bool ConstIsRHS = isa<Constant>(BI.getOperand(1));
|
bool ConstIsRHS = isa<Constant>(I.getOperand(1));
|
||||||
Constant *ConstOperand = cast<Constant>(BI.getOperand(ConstIsRHS));
|
Constant *ConstOperand = cast<Constant>(I.getOperand(ConstIsRHS));
|
||||||
|
|
||||||
if (Constant *SOC = dyn_cast<Constant>(SO)) {
|
if (Constant *SOC = dyn_cast<Constant>(SO)) {
|
||||||
if (ConstIsRHS)
|
if (ConstIsRHS)
|
||||||
return ConstantExpr::get(BI.getOpcode(), SOC, ConstOperand);
|
return ConstantExpr::get(I.getOpcode(), SOC, ConstOperand);
|
||||||
return ConstantExpr::get(BI.getOpcode(), ConstOperand, SOC);
|
return ConstantExpr::get(I.getOpcode(), ConstOperand, SOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *Op0 = SO, *Op1 = ConstOperand;
|
Value *Op0 = SO, *Op1 = ConstOperand;
|
||||||
if (!ConstIsRHS)
|
if (!ConstIsRHS)
|
||||||
std::swap(Op0, Op1);
|
std::swap(Op0, Op1);
|
||||||
Instruction *New;
|
Instruction *New;
|
||||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&BI))
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&I))
|
||||||
New = BinaryOperator::create(BO->getOpcode(), Op0, Op1);
|
New = BinaryOperator::create(BO->getOpcode(), Op0, Op1,SO->getName()+".op");
|
||||||
else if (ShiftInst *SI = dyn_cast<ShiftInst>(&BI))
|
else if (ShiftInst *SI = dyn_cast<ShiftInst>(&I))
|
||||||
New = new ShiftInst(SI->getOpcode(), Op0, Op1);
|
New = new ShiftInst(SI->getOpcode(), Op0, Op1, SO->getName()+".sh");
|
||||||
else {
|
else {
|
||||||
assert(0 && "Unknown binary instruction type!");
|
assert(0 && "Unknown binary instruction type!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return IC->InsertNewInstBefore(New, BI);
|
return IC->InsertNewInstBefore(New, I);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FoldOpIntoSelect - Given an instruction with a select as one operand and a
|
||||||
|
// constant as the other operand, try to fold the binary operator into the
|
||||||
|
// select arguments. This also works for Cast instructions, which obviously do
|
||||||
|
// not have a second operand.
|
||||||
|
static Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
|
||||||
|
InstCombiner *IC) {
|
||||||
|
// Don't modify shared select instructions
|
||||||
|
if (!SI->hasOneUse()) return 0;
|
||||||
|
Value *TV = SI->getOperand(1);
|
||||||
|
Value *FV = SI->getOperand(2);
|
||||||
|
|
||||||
|
if (isa<Constant>(TV) || isa<Constant>(FV)) {
|
||||||
|
Value *SelectTrueVal = FoldOperationIntoSelectOperand(Op, TV, IC);
|
||||||
|
Value *SelectFalseVal = FoldOperationIntoSelectOperand(Op, FV, IC);
|
||||||
|
|
||||||
|
return new SelectInst(SI->getCondition(), SelectTrueVal,
|
||||||
|
SelectFalseVal);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -555,26 +584,6 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
|
||||||
return ReplaceInstUsesWith(I, NewPN);
|
return ReplaceInstUsesWith(I, NewPN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FoldBinOpIntoSelect - Given an instruction with a select as one operand and a
|
|
||||||
// constant as the other operand, try to fold the binary operator into the
|
|
||||||
// select arguments.
|
|
||||||
static Instruction *FoldBinOpIntoSelect(Instruction &BI, SelectInst *SI,
|
|
||||||
InstCombiner *IC) {
|
|
||||||
// Don't modify shared select instructions
|
|
||||||
if (!SI->hasOneUse()) return 0;
|
|
||||||
Value *TV = SI->getOperand(1);
|
|
||||||
Value *FV = SI->getOperand(2);
|
|
||||||
|
|
||||||
if (isa<Constant>(TV) || isa<Constant>(FV)) {
|
|
||||||
Value *SelectTrueVal = FoldOperationIntoSelectOperand(BI, TV, IC);
|
|
||||||
Value *SelectFalseVal = FoldOperationIntoSelectOperand(BI, FV, IC);
|
|
||||||
|
|
||||||
return new SelectInst(SI->getCondition(), SelectTrueVal,
|
|
||||||
SelectFalseVal);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
||||||
bool Changed = SimplifyCommutative(I);
|
bool Changed = SimplifyCommutative(I);
|
||||||
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
|
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
|
||||||
|
@ -667,10 +676,9 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Try to fold constant add into select arguments.
|
// Try to fold constant add into select arguments.
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(LHS))
|
if (SelectInst *SI = dyn_cast<SelectInst>(LHS))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,7 +769,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||||
|
|
||||||
// Try to fold constant sub into select arguments.
|
// Try to fold constant sub into select arguments.
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
|
|
||||||
if (isa<PHINode>(Op0))
|
if (isa<PHINode>(Op0))
|
||||||
|
@ -889,7 +897,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||||
|
|
||||||
// Try to fold constant mul into select arguments.
|
// Try to fold constant mul into select arguments.
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
|
|
||||||
if (isa<PHINode>(Op0))
|
if (isa<PHINode>(Op0))
|
||||||
|
@ -990,7 +998,7 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
|
||||||
|
|
||||||
if (!RHS->isNullValue()) {
|
if (!RHS->isNullValue()) {
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
if (isa<PHINode>(Op0))
|
if (isa<PHINode>(Op0))
|
||||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||||
|
@ -1066,7 +1074,7 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) {
|
||||||
|
|
||||||
if (!RHS->isNullValue()) {
|
if (!RHS->isNullValue()) {
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
if (isa<PHINode>(Op0))
|
if (isa<PHINode>(Op0))
|
||||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||||
|
@ -1251,6 +1259,70 @@ struct FoldSetCCLogical {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
|
||||||
|
/// this predicate to simplify operations downstream. V and Mask are known to
|
||||||
|
/// be the same type.
|
||||||
|
static bool MaskedValueIsZero(Value *V, ConstantIntegral *Mask) {
|
||||||
|
if (isa<UndefValue>(V) || Mask->isNullValue())
|
||||||
|
return true;
|
||||||
|
if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(V))
|
||||||
|
return ConstantExpr::getAnd(CI, Mask)->isNullValue();
|
||||||
|
|
||||||
|
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
||||||
|
switch (I->getOpcode()) {
|
||||||
|
case Instruction::And:
|
||||||
|
// (X & C1) & C2 == 0 iff C1 & C2 == 0.
|
||||||
|
if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(I->getOperand(1)))
|
||||||
|
if (ConstantExpr::getAnd(CI, Mask)->isNullValue())
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case Instruction::Cast: {
|
||||||
|
const Type *SrcTy = I->getOperand(0)->getType();
|
||||||
|
if (SrcTy->isIntegral()) {
|
||||||
|
// (cast <ty> X to int) & C2 == 0 iff <ty> could not have contained C2.
|
||||||
|
if (SrcTy->isUnsigned() && // Only handle zero ext.
|
||||||
|
ConstantExpr::getCast(Mask, SrcTy)->isNullValue())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// If this is a noop cast, recurse.
|
||||||
|
if (SrcTy != Type::BoolTy)
|
||||||
|
if ((SrcTy->isSigned() && SrcTy->getUnsignedVersion() ==I->getType()) ||
|
||||||
|
SrcTy->getSignedVersion() == I->getType()) {
|
||||||
|
Constant *NewMask =
|
||||||
|
ConstantExpr::getCast(Mask, I->getOperand(0)->getType());
|
||||||
|
return MaskedValueIsZero(I->getOperand(0),
|
||||||
|
cast<ConstantIntegral>(NewMask));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::Shl:
|
||||||
|
// (shl X, C1) & C2 == 0 iff (-1 << C1) & C2 == 0
|
||||||
|
if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1))) {
|
||||||
|
Constant *C1 = ConstantIntegral::getAllOnesValue(I->getType());
|
||||||
|
C1 = ConstantExpr::getShl(C1, SA);
|
||||||
|
C1 = ConstantExpr::getAnd(C1, Mask);
|
||||||
|
if (C1->isNullValue())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Instruction::Shr:
|
||||||
|
// (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0
|
||||||
|
if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1)))
|
||||||
|
if (I->getType()->isUnsigned()) {
|
||||||
|
Constant *C1 = ConstantIntegral::getAllOnesValue(I->getType());
|
||||||
|
C1 = ConstantExpr::getShr(C1, SA);
|
||||||
|
C1 = ConstantExpr::getAnd(C1, Mask);
|
||||||
|
if (C1->isNullValue())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// OptAndOp - This handles expressions of the form ((val OP C1) & C2). Where
|
// OptAndOp - This handles expressions of the form ((val OP C1) & C2). Where
|
||||||
// the Op parameter is 'OP', OpRHS is 'C1', and AndRHS is 'C2'. Op is
|
// the Op parameter is 'OP', OpRHS is 'C1', and AndRHS is 'C2'. Op is
|
||||||
// guaranteed to be either a shift instruction or a binary operator.
|
// guaranteed to be either a shift instruction or a binary operator.
|
||||||
|
@ -1265,10 +1337,7 @@ Instruction *InstCombiner::OptAndOp(Instruction *Op,
|
||||||
|
|
||||||
switch (Op->getOpcode()) {
|
switch (Op->getOpcode()) {
|
||||||
case Instruction::Xor:
|
case Instruction::Xor:
|
||||||
if (Together->isNullValue()) {
|
if (Op->hasOneUse()) {
|
||||||
// (X ^ C1) & C2 --> (X & C2) iff (C1&C2) == 0
|
|
||||||
return BinaryOperator::createAnd(X, AndRHS);
|
|
||||||
} else if (Op->hasOneUse()) {
|
|
||||||
// (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
|
// (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
|
||||||
std::string OpName = Op->getName(); Op->setName("");
|
std::string OpName = Op->getName(); Op->setName("");
|
||||||
Instruction *And = BinaryOperator::createAnd(X, AndRHS, OpName);
|
Instruction *And = BinaryOperator::createAnd(X, AndRHS, OpName);
|
||||||
|
@ -1277,20 +1346,15 @@ Instruction *InstCombiner::OptAndOp(Instruction *Op,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Instruction::Or:
|
case Instruction::Or:
|
||||||
// (X | C1) & C2 --> X & C2 iff C1 & C1 == 0
|
if (Together == AndRHS) // (X | C) & C --> C
|
||||||
if (Together->isNullValue())
|
return ReplaceInstUsesWith(TheAnd, AndRHS);
|
||||||
return BinaryOperator::createAnd(X, AndRHS);
|
|
||||||
else {
|
|
||||||
if (Together == AndRHS) // (X | C) & C --> C
|
|
||||||
return ReplaceInstUsesWith(TheAnd, AndRHS);
|
|
||||||
|
|
||||||
if (Op->hasOneUse() && Together != OpRHS) {
|
if (Op->hasOneUse() && Together != OpRHS) {
|
||||||
// (X | C1) & C2 --> (X | (C1&C2)) & C2
|
// (X | C1) & C2 --> (X | (C1&C2)) & C2
|
||||||
std::string Op0Name = Op->getName(); Op->setName("");
|
std::string Op0Name = Op->getName(); Op->setName("");
|
||||||
Instruction *Or = BinaryOperator::createOr(X, Together, Op0Name);
|
Instruction *Or = BinaryOperator::createOr(X, Together, Op0Name);
|
||||||
InsertNewInstBefore(Or, TheAnd);
|
InsertNewInstBefore(Or, TheAnd);
|
||||||
return BinaryOperator::createAnd(Or, AndRHS);
|
return BinaryOperator::createAnd(Or, AndRHS);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Instruction::Add:
|
case Instruction::Add:
|
||||||
|
@ -1445,27 +1509,103 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
||||||
if (isa<UndefValue>(Op1)) // X & undef -> 0
|
if (isa<UndefValue>(Op1)) // X & undef -> 0
|
||||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||||
|
|
||||||
// and X, X = X and X, 0 == 0
|
// and X, X = X
|
||||||
if (Op0 == Op1 || Op1 == Constant::getNullValue(I.getType()))
|
if (Op0 == Op1)
|
||||||
return ReplaceInstUsesWith(I, Op1);
|
return ReplaceInstUsesWith(I, Op1);
|
||||||
|
|
||||||
// and X, -1 == X
|
// and X, -1 == X
|
||||||
if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
|
if (ConstantIntegral *AndRHS = dyn_cast<ConstantIntegral>(Op1)) {
|
||||||
if (RHS->isAllOnesValue())
|
if (AndRHS->isAllOnesValue()) // and X, -1 == X
|
||||||
return ReplaceInstUsesWith(I, Op0);
|
return ReplaceInstUsesWith(I, Op0);
|
||||||
|
|
||||||
|
if (MaskedValueIsZero(Op0, AndRHS)) // LHS & RHS == 0
|
||||||
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||||
|
|
||||||
|
// If the mask is not masking out any bits, there is no reason to do the
|
||||||
|
// and in the first place.
|
||||||
|
if (MaskedValueIsZero(Op0,
|
||||||
|
cast<ConstantIntegral>(ConstantExpr::getNot(AndRHS))))
|
||||||
|
return ReplaceInstUsesWith(I, Op0);
|
||||||
|
|
||||||
// Optimize a variety of ((val OP C1) & C2) combinations...
|
// Optimize a variety of ((val OP C1) & C2) combinations...
|
||||||
if (isa<BinaryOperator>(Op0) || isa<ShiftInst>(Op0)) {
|
if (isa<BinaryOperator>(Op0) || isa<ShiftInst>(Op0)) {
|
||||||
Instruction *Op0I = cast<Instruction>(Op0);
|
Instruction *Op0I = cast<Instruction>(Op0);
|
||||||
Value *X = Op0I->getOperand(0);
|
Value *Op0LHS = Op0I->getOperand(0);
|
||||||
|
Value *Op0RHS = Op0I->getOperand(1);
|
||||||
|
switch (Op0I->getOpcode()) {
|
||||||
|
case Instruction::Xor:
|
||||||
|
case Instruction::Or:
|
||||||
|
// (X ^ V) & C2 --> (X & C2) iff (V & C2) == 0
|
||||||
|
// (X | V) & C2 --> (X & C2) iff (V & C2) == 0
|
||||||
|
if (MaskedValueIsZero(Op0LHS, AndRHS))
|
||||||
|
return BinaryOperator::createAnd(Op0RHS, AndRHS);
|
||||||
|
if (MaskedValueIsZero(Op0RHS, AndRHS))
|
||||||
|
return BinaryOperator::createAnd(Op0LHS, AndRHS);
|
||||||
|
break;
|
||||||
|
case Instruction::And:
|
||||||
|
// (X & V) & C2 --> 0 iff (V & C2) == 0
|
||||||
|
if (MaskedValueIsZero(Op0LHS, AndRHS) ||
|
||||||
|
MaskedValueIsZero(Op0RHS, AndRHS))
|
||||||
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
|
if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
|
||||||
if (Instruction *Res = OptAndOp(Op0I, Op0CI, RHS, I))
|
if (Instruction *Res = OptAndOp(Op0I, Op0CI, AndRHS, I))
|
||||||
return Res;
|
return Res;
|
||||||
|
} else if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
|
||||||
|
const Type *SrcTy = CI->getOperand(0)->getType();
|
||||||
|
|
||||||
|
// If this is an integer sign or zero extension instruction.
|
||||||
|
if (SrcTy->isIntegral() &&
|
||||||
|
SrcTy->getPrimitiveSize() < CI->getType()->getPrimitiveSize()) {
|
||||||
|
|
||||||
|
if (SrcTy->isUnsigned()) {
|
||||||
|
// See if this and is clearing out bits that are known to be zero
|
||||||
|
// anyway (due to the zero extension).
|
||||||
|
Constant *Mask = ConstantIntegral::getAllOnesValue(SrcTy);
|
||||||
|
Mask = ConstantExpr::getZeroExtend(Mask, CI->getType());
|
||||||
|
Constant *Result = ConstantExpr::getAnd(Mask, AndRHS);
|
||||||
|
if (Result == Mask) // The "and" isn't doing anything, remove it.
|
||||||
|
return ReplaceInstUsesWith(I, CI);
|
||||||
|
if (Result != AndRHS) { // Reduce the and RHS constant.
|
||||||
|
I.setOperand(1, Result);
|
||||||
|
return &I;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (CI->hasOneUse() && SrcTy->isInteger()) {
|
||||||
|
// We can only do this if all of the sign bits brought in are masked
|
||||||
|
// out. Compute this by first getting 0000011111, then inverting
|
||||||
|
// it.
|
||||||
|
Constant *Mask = ConstantIntegral::getAllOnesValue(SrcTy);
|
||||||
|
Mask = ConstantExpr::getZeroExtend(Mask, CI->getType());
|
||||||
|
Mask = ConstantExpr::getNot(Mask); // 1's in the new bits.
|
||||||
|
if (ConstantExpr::getAnd(Mask, AndRHS)->isNullValue()) {
|
||||||
|
// If the and is clearing all of the sign bits, change this to a
|
||||||
|
// zero extension cast. To do this, cast the cast input to
|
||||||
|
// unsigned, then to the requested size.
|
||||||
|
Value *CastOp = CI->getOperand(0);
|
||||||
|
Instruction *NC =
|
||||||
|
new CastInst(CastOp, CastOp->getType()->getUnsignedVersion(),
|
||||||
|
CI->getName()+".uns");
|
||||||
|
NC = InsertNewInstBefore(NC, I);
|
||||||
|
// Finally, insert a replacement for CI.
|
||||||
|
NC = new CastInst(NC, CI->getType(), CI->getName());
|
||||||
|
CI->setName("");
|
||||||
|
NC = InsertNewInstBefore(NC, I);
|
||||||
|
WorkList.push_back(CI); // Delete CI later.
|
||||||
|
I.setOperand(0, NC);
|
||||||
|
return &I; // The AND operand was modified.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to fold constant and into select arguments.
|
// Try to fold constant and into select arguments.
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
if (isa<PHINode>(Op0))
|
if (isa<PHINode>(Op0))
|
||||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||||
|
@ -1599,8 +1739,11 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
||||||
|
|
||||||
// or X, -1 == -1
|
// or X, -1 == -1
|
||||||
if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
|
if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
|
||||||
if (RHS->isAllOnesValue())
|
// If X is known to only contain bits that already exist in RHS, just
|
||||||
return ReplaceInstUsesWith(I, Op1);
|
// replace this instruction with RHS directly.
|
||||||
|
if (MaskedValueIsZero(Op0,
|
||||||
|
cast<ConstantIntegral>(ConstantExpr::getNot(RHS))))
|
||||||
|
return ReplaceInstUsesWith(I, RHS);
|
||||||
|
|
||||||
ConstantInt *C1; Value *X;
|
ConstantInt *C1; Value *X;
|
||||||
// (X & C1) | C2 --> (X | C2) & (C1|C2)
|
// (X & C1) | C2 --> (X | C2) & (C1|C2)
|
||||||
|
@ -1622,7 +1765,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
||||||
|
|
||||||
// Try to fold constant and into select arguments.
|
// Try to fold constant and into select arguments.
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
if (isa<PHINode>(Op0))
|
if (isa<PHINode>(Op0))
|
||||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||||
|
@ -1840,7 +1983,7 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||||
|
|
||||||
// Try to fold constant and into select arguments.
|
// Try to fold constant and into select arguments.
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
if (isa<PHINode>(Op0))
|
if (isa<PHINode>(Op0))
|
||||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||||
|
@ -2671,7 +2814,7 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
|
||||||
// Try to fold constant and into select arguments.
|
// Try to fold constant and into select arguments.
|
||||||
if (isa<Constant>(Op0))
|
if (isa<Constant>(Op0))
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
|
|
||||||
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1)) {
|
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1)) {
|
||||||
|
@ -2697,15 +2840,48 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
|
||||||
|
|
||||||
// Try to fold constant and into select arguments.
|
// Try to fold constant and into select arguments.
|
||||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||||
if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
|
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||||
return R;
|
return R;
|
||||||
if (isa<PHINode>(Op0))
|
if (isa<PHINode>(Op0))
|
||||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||||
return NV;
|
return NV;
|
||||||
|
|
||||||
// If the operand is an bitwise operator with a constant RHS, and the
|
if (Op0->hasOneUse()) {
|
||||||
// shift is the only use, we can pull it out of the shift.
|
// If this is a SHL of a sign-extending cast, see if we can turn the input
|
||||||
if (Op0->hasOneUse())
|
// into a zero extending cast (a simple strength reduction).
|
||||||
|
if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
|
||||||
|
const Type *SrcTy = CI->getOperand(0)->getType();
|
||||||
|
if (isLeftShift && SrcTy->isInteger() && SrcTy->isSigned() &&
|
||||||
|
SrcTy->getPrimitiveSize() < CI->getType()->getPrimitiveSize()) {
|
||||||
|
// We can change it to a zero extension if we are shifting out all of
|
||||||
|
// the sign extended bits. To check this, form a mask of all of the
|
||||||
|
// sign extend bits, then shift them left and see if we have anything
|
||||||
|
// left.
|
||||||
|
Constant *Mask = ConstantIntegral::getAllOnesValue(SrcTy); // 1111
|
||||||
|
Mask = ConstantExpr::getZeroExtend(Mask, CI->getType()); // 00001111
|
||||||
|
Mask = ConstantExpr::getNot(Mask); // 1's in the sign bits: 11110000
|
||||||
|
if (ConstantExpr::getShl(Mask, CUI)->isNullValue()) {
|
||||||
|
// If the shift is nuking all of the sign bits, change this to a
|
||||||
|
// zero extension cast. To do this, cast the cast input to
|
||||||
|
// unsigned, then to the requested size.
|
||||||
|
Value *CastOp = CI->getOperand(0);
|
||||||
|
Instruction *NC =
|
||||||
|
new CastInst(CastOp, CastOp->getType()->getUnsignedVersion(),
|
||||||
|
CI->getName()+".uns");
|
||||||
|
NC = InsertNewInstBefore(NC, I);
|
||||||
|
// Finally, insert a replacement for CI.
|
||||||
|
NC = new CastInst(NC, CI->getType(), CI->getName());
|
||||||
|
CI->setName("");
|
||||||
|
NC = InsertNewInstBefore(NC, I);
|
||||||
|
WorkList.push_back(CI); // Delete CI later.
|
||||||
|
I.setOperand(0, NC);
|
||||||
|
return &I; // The SHL operand was modified.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0))
|
if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0))
|
||||||
if (ConstantInt *Op0C = dyn_cast<ConstantInt>(Op0BO->getOperand(1))) {
|
if (ConstantInt *Op0C = dyn_cast<ConstantInt>(Op0BO->getOperand(1))) {
|
||||||
bool isValid = true; // Valid only for And, Or, Xor
|
bool isValid = true; // Valid only for And, Or, Xor
|
||||||
|
@ -2749,6 +2925,7 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
|
||||||
NewRHS);
|
NewRHS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a shift of a shift, see if we can fold the two together...
|
// 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))
|
||||||
|
@ -2926,9 +3103,10 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
|
||||||
// If casting the result of another cast instruction, try to eliminate this
|
// If casting the result of another cast instruction, try to eliminate this
|
||||||
// one!
|
// one!
|
||||||
//
|
//
|
||||||
if (CastInst *CSrc = dyn_cast<CastInst>(Src)) {
|
if (CastInst *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast
|
||||||
if (isEliminableCastOfCast(CSrc->getOperand(0)->getType(),
|
Value *A = CSrc->getOperand(0);
|
||||||
CSrc->getType(), CI.getType(), TD)) {
|
if (isEliminableCastOfCast(A->getType(), CSrc->getType(),
|
||||||
|
CI.getType(), TD)) {
|
||||||
// This instruction now refers directly to the cast's src operand. This
|
// This instruction now refers directly to the cast's src operand. This
|
||||||
// has a good chance of making CSrc dead.
|
// has a good chance of making CSrc dead.
|
||||||
CI.setOperand(0, CSrc->getOperand(0));
|
CI.setOperand(0, CSrc->getOperand(0));
|
||||||
|
@ -2938,18 +3116,27 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
|
||||||
// If this is an A->B->A cast, and we are dealing with integral types, try
|
// If this is an A->B->A cast, and we are dealing with integral types, try
|
||||||
// to convert this into a logical 'and' instruction.
|
// to convert this into a logical 'and' instruction.
|
||||||
//
|
//
|
||||||
if (CSrc->getOperand(0)->getType() == CI.getType() &&
|
if (A->getType()->isInteger() &&
|
||||||
CI.getType()->isInteger() && CSrc->getType()->isInteger() &&
|
CI.getType()->isInteger() && CSrc->getType()->isInteger() &&
|
||||||
CI.getType()->isUnsigned() && CSrc->getType()->isUnsigned() &&
|
CSrc->getType()->isUnsigned() && // B->A cast must zero extend
|
||||||
CSrc->getType()->getPrimitiveSize() < CI.getType()->getPrimitiveSize()){
|
CSrc->getType()->getPrimitiveSize() < CI.getType()->getPrimitiveSize()&&
|
||||||
|
A->getType()->getPrimitiveSize() == CI.getType()->getPrimitiveSize()) {
|
||||||
assert(CSrc->getType() != Type::ULongTy &&
|
assert(CSrc->getType() != Type::ULongTy &&
|
||||||
"Cannot have type bigger than ulong!");
|
"Cannot have type bigger than ulong!");
|
||||||
uint64_t AndValue = (1ULL << CSrc->getType()->getPrimitiveSize()*8)-1;
|
uint64_t AndValue = (1ULL << CSrc->getType()->getPrimitiveSize()*8)-1;
|
||||||
Constant *AndOp = ConstantUInt::get(CI.getType(), AndValue);
|
Constant *AndOp = ConstantUInt::get(A->getType()->getUnsignedVersion(),
|
||||||
return BinaryOperator::createAnd(CSrc->getOperand(0), AndOp);
|
AndValue);
|
||||||
|
AndOp = ConstantExpr::getCast(AndOp, A->getType());
|
||||||
|
Instruction *And = BinaryOperator::createAnd(CSrc->getOperand(0), AndOp);
|
||||||
|
if (And->getType() != CI.getType()) {
|
||||||
|
And->setName(CSrc->getName()+".mask");
|
||||||
|
InsertNewInstBefore(And, CI);
|
||||||
|
And = new CastInst(And, CI.getType());
|
||||||
|
}
|
||||||
|
return And;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a cast to bool, turn it into the appropriate setne instruction.
|
// If this is a cast to bool, turn it into the appropriate setne instruction.
|
||||||
if (CI.getType() == Type::BoolTy)
|
if (CI.getType() == Type::BoolTy)
|
||||||
return BinaryOperator::createSetNE(CI.getOperand(0),
|
return BinaryOperator::createSetNE(CI.getOperand(0),
|
||||||
|
@ -3001,6 +3188,9 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SelectInst *SI = dyn_cast<SelectInst>(Src))
|
||||||
|
if (Instruction *NV = FoldOpIntoSelect(CI, SI, this))
|
||||||
|
return NV;
|
||||||
if (isa<PHINode>(Src))
|
if (isa<PHINode>(Src))
|
||||||
if (Instruction *NV = FoldOpIntoPhi(CI))
|
if (Instruction *NV = FoldOpIntoPhi(CI))
|
||||||
return NV;
|
return NV;
|
||||||
|
|
Loading…
Reference in New Issue