[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Jan 1 08:22:42 PST 2005
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.295 -> 1.296
---
Log message:
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
---
Diffs of the changes: (+268 -78)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.295 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.296
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.295 Tue Dec 14 14:08:06 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sat Jan 1 10:22:27 2005
@@ -486,31 +486,60 @@
}
};
-static Value *FoldOperationIntoSelectOperand(Instruction &BI, Value *SO,
+static Value *FoldOperationIntoSelectOperand(Instruction &I, Value *SO,
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.
- bool ConstIsRHS = isa<Constant>(BI.getOperand(1));
- Constant *ConstOperand = cast<Constant>(BI.getOperand(ConstIsRHS));
+ bool ConstIsRHS = isa<Constant>(I.getOperand(1));
+ Constant *ConstOperand = cast<Constant>(I.getOperand(ConstIsRHS));
if (Constant *SOC = dyn_cast<Constant>(SO)) {
if (ConstIsRHS)
- return ConstantExpr::get(BI.getOpcode(), SOC, ConstOperand);
- return ConstantExpr::get(BI.getOpcode(), ConstOperand, SOC);
+ return ConstantExpr::get(I.getOpcode(), SOC, ConstOperand);
+ return ConstantExpr::get(I.getOpcode(), ConstOperand, SOC);
}
Value *Op0 = SO, *Op1 = ConstOperand;
if (!ConstIsRHS)
std::swap(Op0, Op1);
Instruction *New;
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&BI))
- New = BinaryOperator::create(BO->getOpcode(), Op0, Op1);
- else if (ShiftInst *SI = dyn_cast<ShiftInst>(&BI))
- New = new ShiftInst(SI->getOpcode(), Op0, Op1);
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&I))
+ New = BinaryOperator::create(BO->getOpcode(), Op0, Op1,SO->getName()+".op");
+ else if (ShiftInst *SI = dyn_cast<ShiftInst>(&I))
+ New = new ShiftInst(SI->getOpcode(), Op0, Op1, SO->getName()+".sh");
else {
assert(0 && "Unknown binary instruction type!");
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 @@
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) {
bool Changed = SimplifyCommutative(I);
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
@@ -667,10 +676,9 @@
}
}
-
// Try to fold constant add into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(LHS))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
}
@@ -761,7 +769,7 @@
// Try to fold constant sub into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
@@ -889,7 +897,7 @@
// Try to fold constant mul into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
@@ -990,7 +998,7 @@
if (!RHS->isNullValue()) {
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
@@ -1066,7 +1074,7 @@
if (!RHS->isNullValue()) {
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
@@ -1251,6 +1259,70 @@
};
+/// 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
// 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.
@@ -1265,10 +1337,7 @@
switch (Op->getOpcode()) {
case Instruction::Xor:
- if (Together->isNullValue()) {
- // (X ^ C1) & C2 --> (X & C2) iff (C1&C2) == 0
- return BinaryOperator::createAnd(X, AndRHS);
- } else if (Op->hasOneUse()) {
+ if (Op->hasOneUse()) {
// (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
std::string OpName = Op->getName(); Op->setName("");
Instruction *And = BinaryOperator::createAnd(X, AndRHS, OpName);
@@ -1277,20 +1346,15 @@
}
break;
case Instruction::Or:
- // (X | C1) & C2 --> X & C2 iff C1 & C1 == 0
- if (Together->isNullValue())
- return BinaryOperator::createAnd(X, AndRHS);
- else {
- if (Together == AndRHS) // (X | C) & C --> C
- return ReplaceInstUsesWith(TheAnd, AndRHS);
+ if (Together == AndRHS) // (X | C) & C --> C
+ return ReplaceInstUsesWith(TheAnd, AndRHS);
- if (Op->hasOneUse() && Together != OpRHS) {
- // (X | C1) & C2 --> (X | (C1&C2)) & C2
- std::string Op0Name = Op->getName(); Op->setName("");
- Instruction *Or = BinaryOperator::createOr(X, Together, Op0Name);
- InsertNewInstBefore(Or, TheAnd);
- return BinaryOperator::createAnd(Or, AndRHS);
- }
+ if (Op->hasOneUse() && Together != OpRHS) {
+ // (X | C1) & C2 --> (X | (C1&C2)) & C2
+ std::string Op0Name = Op->getName(); Op->setName("");
+ Instruction *Or = BinaryOperator::createOr(X, Together, Op0Name);
+ InsertNewInstBefore(Or, TheAnd);
+ return BinaryOperator::createAnd(Or, AndRHS);
}
break;
case Instruction::Add:
@@ -1445,27 +1509,103 @@
if (isa<UndefValue>(Op1)) // X & undef -> 0
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
- // and X, X = X and X, 0 == 0
- if (Op0 == Op1 || Op1 == Constant::getNullValue(I.getType()))
+ // and X, X = X
+ if (Op0 == Op1)
return ReplaceInstUsesWith(I, Op1);
// and X, -1 == X
- if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
- if (RHS->isAllOnesValue())
+ if (ConstantIntegral *AndRHS = dyn_cast<ConstantIntegral>(Op1)) {
+ if (AndRHS->isAllOnesValue()) // and X, -1 == X
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...
if (isa<BinaryOperator>(Op0) || isa<ShiftInst>(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 (Instruction *Res = OptAndOp(Op0I, Op0CI, RHS, I))
+ if (Instruction *Res = OptAndOp(Op0I, Op0CI, AndRHS, I))
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.
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
@@ -1599,8 +1739,11 @@
// or X, -1 == -1
if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
- if (RHS->isAllOnesValue())
- return ReplaceInstUsesWith(I, Op1);
+ // If X is known to only contain bits that already exist in RHS, just
+ // replace this instruction with RHS directly.
+ if (MaskedValueIsZero(Op0,
+ cast<ConstantIntegral>(ConstantExpr::getNot(RHS))))
+ return ReplaceInstUsesWith(I, RHS);
ConstantInt *C1; Value *X;
// (X & C1) | C2 --> (X | C2) & (C1|C2)
@@ -1622,7 +1765,7 @@
// Try to fold constant and into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
@@ -1840,7 +1983,7 @@
// Try to fold constant and into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
@@ -2671,7 +2814,7 @@
// Try to fold constant and into select arguments.
if (isa<Constant>(Op0))
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1)) {
@@ -2697,15 +2840,48 @@
// Try to fold constant and into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
- if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
- // 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->hasOneUse())
+ if (Op0->hasOneUse()) {
+ // If this is a SHL of a sign-extending cast, see if we can turn the input
+ // 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 (ConstantInt *Op0C = dyn_cast<ConstantInt>(Op0BO->getOperand(1))) {
bool isValid = true; // Valid only for And, Or, Xor
@@ -2749,6 +2925,7 @@
NewRHS);
}
}
+ }
// If this is a shift of a shift, see if we can fold the two together...
if (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0))
@@ -2926,9 +3103,10 @@
// If casting the result of another cast instruction, try to eliminate this
// one!
//
- if (CastInst *CSrc = dyn_cast<CastInst>(Src)) {
- if (isEliminableCastOfCast(CSrc->getOperand(0)->getType(),
- CSrc->getType(), CI.getType(), TD)) {
+ if (CastInst *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast
+ Value *A = CSrc->getOperand(0);
+ if (isEliminableCastOfCast(A->getType(), CSrc->getType(),
+ CI.getType(), TD)) {
// This instruction now refers directly to the cast's src operand. This
// has a good chance of making CSrc dead.
CI.setOperand(0, CSrc->getOperand(0));
@@ -2938,18 +3116,27 @@
// If this is an A->B->A cast, and we are dealing with integral types, try
// 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()->isUnsigned() && CSrc->getType()->isUnsigned() &&
- CSrc->getType()->getPrimitiveSize() < CI.getType()->getPrimitiveSize()){
+ CSrc->getType()->isUnsigned() && // B->A cast must zero extend
+ CSrc->getType()->getPrimitiveSize() < CI.getType()->getPrimitiveSize()&&
+ A->getType()->getPrimitiveSize() == CI.getType()->getPrimitiveSize()) {
assert(CSrc->getType() != Type::ULongTy &&
"Cannot have type bigger than ulong!");
uint64_t AndValue = (1ULL << CSrc->getType()->getPrimitiveSize()*8)-1;
- Constant *AndOp = ConstantUInt::get(CI.getType(), AndValue);
- return BinaryOperator::createAnd(CSrc->getOperand(0), AndOp);
+ Constant *AndOp = ConstantUInt::get(A->getType()->getUnsignedVersion(),
+ 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 (CI.getType() == Type::BoolTy)
return BinaryOperator::createSetNE(CI.getOperand(0),
@@ -3001,6 +3188,9 @@
}
}
+ if (SelectInst *SI = dyn_cast<SelectInst>(Src))
+ if (Instruction *NV = FoldOpIntoSelect(CI, SI, this))
+ return NV;
if (isa<PHINode>(Src))
if (Instruction *NV = FoldOpIntoPhi(CI))
return NV;
More information about the llvm-commits
mailing list