Fix and/or/xor (cast A), (cast B) --> cast (and/or/xor A, B)

The cast patch introduced the possibility that the wrong cast opcode
could be used and that this transform could trigger on different kinds
of cast operations. This patch rectifies that.

llvm-svn: 32538
This commit is contained in:
Reid Spencer 2006-12-13 08:27:15 +00:00
parent 20f7a2a09b
commit 799b5bfc71
1 changed files with 40 additions and 41 deletions

View File

@ -3270,22 +3270,21 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
}
// fold (and (cast A), (cast B)) -> (cast (and A, B))
if (CastInst *Op1C = dyn_cast<CastInst>(Op1)) {
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
const Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
// Only do this if the casts both really cause code to be generated.
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
Instruction *NewOp = BinaryOperator::createAnd(Op0C->getOperand(0),
Op1C->getOperand(0),
I.getName());
InsertNewInstBefore(NewOp, I);
return CastInst::createIntegerCast(NewOp, I.getType(),
SrcTy->isSigned());
if (CastInst *Op0C = dyn_cast<CastInst>(Op0))
if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind ?
const Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
// Only do this if the casts both really cause code to be generated.
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
Instruction *NewOp = BinaryOperator::createAnd(Op0C->getOperand(0),
Op1C->getOperand(0),
I.getName());
InsertNewInstBefore(NewOp, I);
return CastInst::create(Op0C->getOpcode(), NewOp, I.getType());
}
}
}
}
// (X >> Z) & (Y >> Z) -> (X&Y) >> Z for all shifts.
if (ShiftInst *SI1 = dyn_cast<ShiftInst>(Op1)) {
@ -3675,21 +3674,21 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
}
// fold (or (cast A), (cast B)) -> (cast (or A, B))
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
const Type *SrcTy = Op0C->getOperand(0)->getType();
if (CastInst *Op0C = dyn_cast<CastInst>(Op0))
if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
// Only do this if the casts both really cause code to be generated.
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
Instruction *NewOp = BinaryOperator::createOr(Op0C->getOperand(0),
Op1C->getOperand(0),
I.getName());
InsertNewInstBefore(NewOp, I);
return CastInst::createIntegerCast(NewOp, I.getType(),
SrcTy->isSigned());
if (Op0C->getOpcode() == Op1C->getOpcode()) {// same cast kind ?
const Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
// Only do this if the casts both really cause code to be generated.
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
Instruction *NewOp = BinaryOperator::createOr(Op0C->getOperand(0),
Op1C->getOperand(0),
I.getName());
InsertNewInstBefore(NewOp, I);
return CastInst::create(Op0C->getOpcode(), NewOp, I.getType());
}
}
}
return Changed ? &I : 0;
@ -3857,21 +3856,21 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
return R;
// fold (xor (cast A), (cast B)) -> (cast (xor A, B))
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
const Type *SrcTy = Op0C->getOperand(0)->getType();
if (CastInst *Op0C = dyn_cast<CastInst>(Op0))
if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
// Only do this if the casts both really cause code to be generated.
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
Instruction *NewOp = BinaryOperator::createXor(Op0C->getOperand(0),
Op1C->getOperand(0),
I.getName());
InsertNewInstBefore(NewOp, I);
return CastInst::createIntegerCast(NewOp, I.getType(),
SrcTy->isSigned());
if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind?
const Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegral() &&
// Only do this if the casts both really cause code to be generated.
ValueRequiresCast(Op0C->getOperand(0), I.getType(), TD) &&
ValueRequiresCast(Op1C->getOperand(0), I.getType(), TD)) {
Instruction *NewOp = BinaryOperator::createXor(Op0C->getOperand(0),
Op1C->getOperand(0),
I.getName());
InsertNewInstBefore(NewOp, I);
return CastInst::create(Op0C->getOpcode(), NewOp, I.getType());
}
}
}
// (X >> Z) ^ (Y >> Z) -> (X^Y) >> Z for all shifts.
if (ShiftInst *SI1 = dyn_cast<ShiftInst>(Op1)) {