mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-26 07:24:25 +00:00
Implement shift-simplify.ll:test3, turning:
(X << 31) <s 0 --> (X&1) != 0 This happens dozens of times in the CFE. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@39879 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -2271,24 +2271,19 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isSignBitCheck - Given an exploded icmp instruction, return true if it
|
/// isSignBitCheck - Given an exploded icmp instruction, return true if the
|
||||||
/// really just returns true if the most significant (sign) bit is set.
|
/// comparison only checks the sign bit. If it only checks the sign bit, set
|
||||||
static bool isSignBitCheck(ICmpInst::Predicate pred, ConstantInt *RHS) {
|
/// TrueIfSigned if the result of the comparison is true when the input value is
|
||||||
|
/// signed.
|
||||||
|
static bool isSignBitCheck(ICmpInst::Predicate pred, ConstantInt *RHS,
|
||||||
|
bool &TrueIfSigned) {
|
||||||
switch (pred) {
|
switch (pred) {
|
||||||
case ICmpInst::ICMP_SLT:
|
case ICmpInst::ICMP_SLT: // True if LHS s< 0
|
||||||
// True if LHS s< RHS and RHS == 0
|
TrueIfSigned = true;
|
||||||
return RHS->isZero();
|
return RHS->isZero();
|
||||||
case ICmpInst::ICMP_SLE:
|
case ICmpInst::ICMP_SGT: // True if LHS s> -1
|
||||||
// True if LHS s<= RHS and RHS == -1
|
TrueIfSigned = false;
|
||||||
return RHS->isAllOnesValue();
|
return RHS->isAllOnesValue();
|
||||||
case ICmpInst::ICMP_UGE:
|
|
||||||
// True if LHS u>= RHS and RHS == high-bit-mask (2^7, 2^15, 2^31, etc)
|
|
||||||
return RHS->getValue() ==
|
|
||||||
APInt::getSignBit(RHS->getType()->getPrimitiveSizeInBits());
|
|
||||||
case ICmpInst::ICMP_UGT:
|
|
||||||
// True if LHS u> RHS and RHS == high-bit-mask - 1
|
|
||||||
return RHS->getValue() ==
|
|
||||||
APInt::getSignedMaxValue(RHS->getType()->getPrimitiveSizeInBits());
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2377,11 +2372,13 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
|||||||
if (ICmpInst *SCI = dyn_cast<ICmpInst>(BoolCast->getOperand(0))) {
|
if (ICmpInst *SCI = dyn_cast<ICmpInst>(BoolCast->getOperand(0))) {
|
||||||
Value *SCIOp0 = SCI->getOperand(0), *SCIOp1 = SCI->getOperand(1);
|
Value *SCIOp0 = SCI->getOperand(0), *SCIOp1 = SCI->getOperand(1);
|
||||||
const Type *SCOpTy = SCIOp0->getType();
|
const Type *SCOpTy = SCIOp0->getType();
|
||||||
|
bool TIS = false;
|
||||||
|
|
||||||
// If the icmp is true iff the sign bit of X is set, then convert this
|
// If the icmp is true iff the sign bit of X is set, then convert this
|
||||||
// multiply into a shift/and combination.
|
// multiply into a shift/and combination.
|
||||||
if (isa<ConstantInt>(SCIOp1) &&
|
if (isa<ConstantInt>(SCIOp1) &&
|
||||||
isSignBitCheck(SCI->getPredicate(), cast<ConstantInt>(SCIOp1))) {
|
isSignBitCheck(SCI->getPredicate(), cast<ConstantInt>(SCIOp1), TIS) &&
|
||||||
|
TIS) {
|
||||||
// Shift the X value right to turn it into "all signbits".
|
// Shift the X value right to turn it into "all signbits".
|
||||||
Constant *Amt = ConstantInt::get(SCIOp0->getType(),
|
Constant *Amt = ConstantInt::get(SCIOp0->getType(),
|
||||||
SCOpTy->getPrimitiveSizeInBits()-1);
|
SCOpTy->getPrimitiveSizeInBits()-1);
|
||||||
@ -2805,23 +2802,19 @@ Instruction *InstCombiner::visitFRem(BinaryOperator &I) {
|
|||||||
// isMaxValueMinusOne - return true if this is Max-1
|
// isMaxValueMinusOne - return true if this is Max-1
|
||||||
static bool isMaxValueMinusOne(const ConstantInt *C, bool isSigned) {
|
static bool isMaxValueMinusOne(const ConstantInt *C, bool isSigned) {
|
||||||
uint32_t TypeBits = C->getType()->getPrimitiveSizeInBits();
|
uint32_t TypeBits = C->getType()->getPrimitiveSizeInBits();
|
||||||
if (isSigned) {
|
if (!isSigned)
|
||||||
// Calculate 0111111111..11111
|
|
||||||
APInt Val(APInt::getSignedMaxValue(TypeBits));
|
|
||||||
return C->getValue() == Val-1;
|
|
||||||
}
|
|
||||||
return C->getValue() == APInt::getAllOnesValue(TypeBits) - 1;
|
return C->getValue() == APInt::getAllOnesValue(TypeBits) - 1;
|
||||||
|
return C->getValue() == APInt::getSignedMaxValue(TypeBits)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// isMinValuePlusOne - return true if this is Min+1
|
// isMinValuePlusOne - return true if this is Min+1
|
||||||
static bool isMinValuePlusOne(const ConstantInt *C, bool isSigned) {
|
static bool isMinValuePlusOne(const ConstantInt *C, bool isSigned) {
|
||||||
if (isSigned) {
|
if (!isSigned)
|
||||||
|
return C->getValue() == 1; // unsigned
|
||||||
|
|
||||||
// Calculate 1111111111000000000000
|
// Calculate 1111111111000000000000
|
||||||
uint32_t TypeBits = C->getType()->getPrimitiveSizeInBits();
|
uint32_t TypeBits = C->getType()->getPrimitiveSizeInBits();
|
||||||
APInt Val(APInt::getSignedMinValue(TypeBits));
|
return C->getValue() == APInt::getSignedMinValue(TypeBits)+1;
|
||||||
return C->getValue() == Val+1;
|
|
||||||
}
|
|
||||||
return C->getValue() == 1; // unsigned
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isOneBitSet - Return true if there is exactly one bit set in the specified
|
// isOneBitSet - Return true if there is exactly one bit set in the specified
|
||||||
@ -5415,9 +5408,10 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction::Shl: // (icmp pred (shl X, ShAmt), CI)
|
case Instruction::Shl: { // (icmp pred (shl X, ShAmt), CI)
|
||||||
if (ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
|
ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1));
|
||||||
if (ICI.isEquality()) {
|
if (!ShAmt) break;
|
||||||
|
|
||||||
uint32_t TypeBits = RHSV.getBitWidth();
|
uint32_t TypeBits = RHSV.getBitWidth();
|
||||||
|
|
||||||
// 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
|
||||||
@ -5426,6 +5420,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
|
|||||||
if (ShAmt->uge(TypeBits))
|
if (ShAmt->uge(TypeBits))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (ICI.isEquality()) {
|
||||||
// If we are comparing against bits always shifted out, the
|
// If we are comparing against bits always shifted out, the
|
||||||
// comparison cannot succeed.
|
// comparison cannot succeed.
|
||||||
Constant *Comp =
|
Constant *Comp =
|
||||||
@ -5450,12 +5445,30 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
|
|||||||
ConstantInt::get(RHSV.lshr(ShAmtVal)));
|
ConstantInt::get(RHSV.lshr(ShAmtVal)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, if this is a comparison of the sign bit, simplify to and/test.
|
||||||
|
bool TrueIfSigned = false;
|
||||||
|
if (LHSI->hasOneUse() &&
|
||||||
|
isSignBitCheck(ICI.getPredicate(), RHS, TrueIfSigned)) {
|
||||||
|
// (X << 31) <s 0 --> (X&1) != 0
|
||||||
|
Constant *Mask = ConstantInt::get(APInt(TypeBits, 1) <<
|
||||||
|
(TypeBits-ShAmt->getZExtValue()-1));
|
||||||
|
Instruction *AndI =
|
||||||
|
BinaryOperator::createAnd(LHSI->getOperand(0),
|
||||||
|
Mask, LHSI->getName()+".mask");
|
||||||
|
Value *And = InsertNewInstBefore(AndI, ICI);
|
||||||
|
|
||||||
|
return new ICmpInst(TrueIfSigned ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ,
|
||||||
|
And, Constant::getNullValue(And->getType()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Instruction::LShr: // (icmp pred (shr X, ShAmt), CI)
|
case Instruction::LShr: // (icmp pred (shr X, ShAmt), CI)
|
||||||
case Instruction::AShr:
|
case Instruction::AShr: {
|
||||||
if (ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
|
ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1));
|
||||||
|
if (!ShAmt) break;
|
||||||
|
|
||||||
if (ICI.isEquality()) {
|
if (ICI.isEquality()) {
|
||||||
// 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
|
||||||
@ -5492,8 +5505,8 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
|
|||||||
ConstantExpr::getShl(RHS, ShAmt));
|
ConstantExpr::getShl(RHS, ShAmt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Instruction::SDiv:
|
case Instruction::SDiv:
|
||||||
case Instruction::UDiv:
|
case Instruction::UDiv:
|
||||||
|
@ -21,3 +21,10 @@ define i32 @test2(i32 %A, i32 %B, i32 %C) {
|
|||||||
%Z = xor i32 %X, %Y
|
%Z = xor i32 %X, %Y
|
||||||
ret i32 %Z
|
ret i32 %Z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i1 @test3(i32 %X) {
|
||||||
|
%tmp1 = shl i32 %X, 7
|
||||||
|
%tmp2 = icmp slt i32 %tmp1, 0
|
||||||
|
ret i1 %tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user