mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-10 02:36:06 +00:00
Rewrite shift/and/compare sequences to promote better licm of the RHS.
Use isLogicalShift/isArithmeticShift to simplify code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30448 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20fdab6fbf
commit
65b72baa59
@ -3856,7 +3856,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
// happens a LOT in code produced by the C front-end, for bitfield
|
// happens a LOT in code produced by the C front-end, for bitfield
|
||||||
// access.
|
// access.
|
||||||
ShiftInst *Shift = dyn_cast<ShiftInst>(LHSI->getOperand(0));
|
ShiftInst *Shift = dyn_cast<ShiftInst>(LHSI->getOperand(0));
|
||||||
ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
|
Constant *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
|
||||||
|
|
||||||
// Check to see if there is a noop-cast between the shift and the and.
|
// Check to see if there is a noop-cast between the shift and the and.
|
||||||
if (!Shift) {
|
if (!Shift) {
|
||||||
@ -3866,7 +3866,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
CI->getType()->getPrimitiveSizeInBits())
|
CI->getType()->getPrimitiveSizeInBits())
|
||||||
Shift = dyn_cast<ShiftInst>(CI->getOperand(0));
|
Shift = dyn_cast<ShiftInst>(CI->getOperand(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantUInt *ShAmt;
|
ConstantUInt *ShAmt;
|
||||||
ShAmt = Shift ? dyn_cast<ConstantUInt>(Shift->getOperand(1)) : 0;
|
ShAmt = Shift ? dyn_cast<ConstantUInt>(Shift->getOperand(1)) : 0;
|
||||||
const Type *Ty = Shift ? Shift->getType() : 0; // Type of the shift.
|
const Type *Ty = Shift ? Shift->getType() : 0; // Type of the shift.
|
||||||
@ -3876,8 +3876,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
// into the mask. This can only happen with signed shift
|
// into the mask. This can only happen with signed shift
|
||||||
// rights, as they sign-extend.
|
// rights, as they sign-extend.
|
||||||
if (ShAmt) {
|
if (ShAmt) {
|
||||||
bool CanFold = Shift->getOpcode() != Instruction::Shr ||
|
bool CanFold = Shift->isLogicalShift();
|
||||||
Ty->isUnsigned();
|
|
||||||
if (!CanFold) {
|
if (!CanFold) {
|
||||||
// To test for the bad case of the signed shr, see if any
|
// To test for the bad case of the signed shr, see if any
|
||||||
// of the bits shifted in could be tested after the mask.
|
// of the bits shifted in could be tested after the mask.
|
||||||
@ -3930,15 +3929,49 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn ((X >> Y) & C) == 0 into (X & (C << Y)) == 0. The later is
|
||||||
|
// preferable because it allows the C<<Y expression to be hoisted out
|
||||||
|
// of a loop if Y is invariant and X is not.
|
||||||
|
if (Shift && Shift->hasOneUse() && CI->isNullValue() &&
|
||||||
|
I.isEquality() && !Shift->isArithmeticShift()) {
|
||||||
|
// Compute C << Y.
|
||||||
|
Value *NS;
|
||||||
|
if (Shift->getOpcode() == Instruction::Shr) {
|
||||||
|
NS = new ShiftInst(Instruction::Shl, AndCST, Shift->getOperand(1),
|
||||||
|
"tmp");
|
||||||
|
} else {
|
||||||
|
// Make sure we insert a logical shift.
|
||||||
|
if (AndCST->getType()->isSigned())
|
||||||
|
AndCST = ConstantExpr::getCast(AndCST,
|
||||||
|
AndCST->getType()->getUnsignedVersion());
|
||||||
|
NS = new ShiftInst(Instruction::Shr, AndCST, Shift->getOperand(1),
|
||||||
|
"tmp");
|
||||||
|
}
|
||||||
|
InsertNewInstBefore(cast<Instruction>(NS), I);
|
||||||
|
|
||||||
|
// If C's sign doesn't agree with the and, insert a cast now.
|
||||||
|
if (NS->getType() != LHSI->getType())
|
||||||
|
NS = InsertCastBefore(NS, LHSI->getType(), I);
|
||||||
|
|
||||||
|
Value *ShiftOp = Shift->getOperand(0);
|
||||||
|
if (ShiftOp->getType() != LHSI->getType())
|
||||||
|
ShiftOp = InsertCastBefore(ShiftOp, LHSI->getType(), I);
|
||||||
|
|
||||||
|
// Compute X & (C << Y).
|
||||||
|
Instruction *NewAnd =
|
||||||
|
BinaryOperator::createAnd(ShiftOp, NS, LHSI->getName());
|
||||||
|
InsertNewInstBefore(NewAnd, I);
|
||||||
|
|
||||||
|
I.setOperand(0, NewAnd);
|
||||||
|
return &I;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction::Shl: // (setcc (shl X, ShAmt), CI)
|
case Instruction::Shl: // (setcc (shl X, ShAmt), CI)
|
||||||
if (ConstantUInt *ShAmt = dyn_cast<ConstantUInt>(LHSI->getOperand(1))) {
|
if (ConstantUInt *ShAmt = dyn_cast<ConstantUInt>(LHSI->getOperand(1))) {
|
||||||
switch (I.getOpcode()) {
|
if (I.isEquality()) {
|
||||||
default: break;
|
|
||||||
case Instruction::SetEQ:
|
|
||||||
case Instruction::SetNE: {
|
|
||||||
unsigned TypeBits = CI->getType()->getPrimitiveSizeInBits();
|
unsigned TypeBits = CI->getType()->getPrimitiveSizeInBits();
|
||||||
|
|
||||||
// Check that the shift amount is in range. If not, don't perform
|
// Check that the shift amount is in range. If not, don't perform
|
||||||
@ -3979,17 +4012,12 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
ConstantExpr::getUShr(CI, ShAmt));
|
ConstantExpr::getUShr(CI, ShAmt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction::Shr: // (setcc (shr X, ShAmt), CI)
|
case Instruction::Shr: // (setcc (shr X, ShAmt), CI)
|
||||||
if (ConstantUInt *ShAmt = dyn_cast<ConstantUInt>(LHSI->getOperand(1))) {
|
if (ConstantUInt *ShAmt = dyn_cast<ConstantUInt>(LHSI->getOperand(1))) {
|
||||||
switch (I.getOpcode()) {
|
if (I.isEquality()) {
|
||||||
default: break;
|
|
||||||
case Instruction::SetEQ:
|
|
||||||
case Instruction::SetNE: {
|
|
||||||
|
|
||||||
// Check that the shift amount is in range. If not, don't perform
|
// Check that the shift amount is in range. If not, don't perform
|
||||||
// undefined shifts. When the shift is visited it will be
|
// undefined shifts. When the shift is visited it will be
|
||||||
// simplified.
|
// simplified.
|
||||||
@ -4030,8 +4058,6 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
return new SetCondInst(I.getOpcode(), And,
|
return new SetCondInst(I.getOpcode(), And,
|
||||||
ConstantExpr::getShl(CI, ShAmt));
|
ConstantExpr::getShl(CI, ShAmt));
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -4130,8 +4156,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Simplify seteq and setne instructions...
|
// Simplify seteq and setne instructions...
|
||||||
if (I.getOpcode() == Instruction::SetEQ ||
|
if (I.isEquality()) {
|
||||||
I.getOpcode() == Instruction::SetNE) {
|
|
||||||
bool isSetNE = I.getOpcode() == Instruction::SetNE;
|
bool isSetNE = I.getOpcode() == Instruction::SetNE;
|
||||||
|
|
||||||
// If the first operand is (and|or|xor) with a constant, and the second
|
// If the first operand is (and|or|xor) with a constant, and the second
|
||||||
@ -4361,9 +4386,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
|
if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
|
||||||
Value *CastOp0 = CI->getOperand(0);
|
Value *CastOp0 = CI->getOperand(0);
|
||||||
if (CastOp0->getType()->isLosslesslyConvertibleTo(CI->getType()) &&
|
if (CastOp0->getType()->isLosslesslyConvertibleTo(CI->getType()) &&
|
||||||
(isa<Constant>(Op1) || isa<CastInst>(Op1)) &&
|
(isa<Constant>(Op1) || isa<CastInst>(Op1)) && I.isEquality()) {
|
||||||
(I.getOpcode() == Instruction::SetEQ ||
|
|
||||||
I.getOpcode() == Instruction::SetNE)) {
|
|
||||||
// We keep moving the cast from the left operand over to the right
|
// We keep moving the cast from the left operand over to the right
|
||||||
// operand, where it can often be eliminated completely.
|
// operand, where it can often be eliminated completely.
|
||||||
Op0 = CastOp0;
|
Op0 = CastOp0;
|
||||||
@ -4398,8 +4421,7 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
|
|||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (I.getOpcode() == Instruction::SetNE ||
|
if (I.isEquality()) {
|
||||||
I.getOpcode() == Instruction::SetEQ) {
|
|
||||||
Value *A, *B;
|
Value *A, *B;
|
||||||
if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
|
if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
|
||||||
(A == Op1 || B == Op1)) {
|
(A == Op1 || B == Op1)) {
|
||||||
@ -4552,7 +4574,7 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
|
|||||||
return R;
|
return R;
|
||||||
|
|
||||||
// See if we can turn a signed shr into an unsigned shr.
|
// See if we can turn a signed shr into an unsigned shr.
|
||||||
if (!isLeftShift && I.getType()->isSigned()) {
|
if (I.isArithmeticShift()) {
|
||||||
if (MaskedValueIsZero(Op0,
|
if (MaskedValueIsZero(Op0,
|
||||||
1ULL << (I.getType()->getPrimitiveSizeInBits()-1))) {
|
1ULL << (I.getType()->getPrimitiveSizeInBits()-1))) {
|
||||||
Value *V = InsertCastBefore(Op0, I.getType()->getUnsignedVersion(), I);
|
Value *V = InsertCastBefore(Op0, I.getType()->getUnsignedVersion(), I);
|
||||||
@ -5617,10 +5639,8 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
|||||||
// non-constant value, eliminate this whole mess. This corresponds to
|
// non-constant value, eliminate this whole mess. This corresponds to
|
||||||
// cases like this: ((X & 27) ? 27 : 0)
|
// cases like this: ((X & 27) ? 27 : 0)
|
||||||
if (TrueValC->isNullValue() || FalseValC->isNullValue())
|
if (TrueValC->isNullValue() || FalseValC->isNullValue())
|
||||||
if (Instruction *IC = dyn_cast<Instruction>(SI.getCondition()))
|
if (SetCondInst *IC = dyn_cast<SetCondInst>(SI.getCondition()))
|
||||||
if ((IC->getOpcode() == Instruction::SetEQ ||
|
if (IC->isEquality() && isa<ConstantInt>(IC->getOperand(1)) &&
|
||||||
IC->getOpcode() == Instruction::SetNE) &&
|
|
||||||
isa<ConstantInt>(IC->getOperand(1)) &&
|
|
||||||
cast<Constant>(IC->getOperand(1))->isNullValue())
|
cast<Constant>(IC->getOperand(1))->isNullValue())
|
||||||
if (Instruction *ICA = dyn_cast<Instruction>(IC->getOperand(0)))
|
if (Instruction *ICA = dyn_cast<Instruction>(IC->getOperand(0)))
|
||||||
if (ICA->getOpcode() == Instruction::And &&
|
if (ICA->getOpcode() == Instruction::And &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user