forked from OSchip/llvm-project
Enhance a bunch of transformations in instcombine to start generating
exact/nsw/nuw shifts and have instcombine infer them when it can prove that the relevant properties are true for a given shift without them. Also, a variety of refactoring to use the new patternmatch logic thrown in for good luck. I believe that this takes care of a bunch of related code quality issues attached to PR8862. llvm-svn: 125267
This commit is contained in:
parent
98457101fc
commit
6b657aed33
|
@ -19,11 +19,6 @@
|
|||
using namespace llvm;
|
||||
using namespace PatternMatch;
|
||||
|
||||
/// SubOne - Subtract one from a ConstantInt.
|
||||
static Constant *SubOne(ConstantInt *C) {
|
||||
return ConstantInt::get(C->getContext(), C->getValue()-1);
|
||||
}
|
||||
|
||||
/// MultiplyOverflows - True if the multiply can not be expressed in an int
|
||||
/// this size.
|
||||
static bool MultiplyOverflows(ConstantInt *C1, ConstantInt *C2, bool sign) {
|
||||
|
@ -57,52 +52,39 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
|||
if (Value *V = SimplifyUsingDistributiveLaws(I))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
|
||||
// Simplify mul instructions with a constant RHS.
|
||||
if (Constant *Op1C = dyn_cast<Constant>(Op1)) {
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1C)) {
|
||||
|
||||
// ((X << C1)*C2) == (X * (C2 << C1))
|
||||
if (BinaryOperator *SI = dyn_cast<BinaryOperator>(Op0))
|
||||
if (SI->getOpcode() == Instruction::Shl)
|
||||
if (Constant *ShOp = dyn_cast<Constant>(SI->getOperand(1)))
|
||||
return BinaryOperator::CreateMul(SI->getOperand(0),
|
||||
ConstantExpr::getShl(CI, ShOp));
|
||||
|
||||
if (CI->isAllOnesValue()) // X * -1 == 0 - X
|
||||
return BinaryOperator::CreateNeg(Op0, I.getName());
|
||||
|
||||
const APInt& Val = cast<ConstantInt>(CI)->getValue();
|
||||
if (Val.isPowerOf2()) { // Replace X*(2^C) with X << C
|
||||
return BinaryOperator::CreateShl(Op0,
|
||||
ConstantInt::get(Op0->getType(), Val.logBase2()));
|
||||
}
|
||||
} else if (Op1C->getType()->isVectorTy()) {
|
||||
if (Op1C->isNullValue())
|
||||
return ReplaceInstUsesWith(I, Op1C);
|
||||
|
||||
if (ConstantVector *Op1V = dyn_cast<ConstantVector>(Op1C)) {
|
||||
if (Op1V->isAllOnesValue()) // X * -1 == 0 - X
|
||||
return BinaryOperator::CreateNeg(Op0, I.getName());
|
||||
|
||||
// As above, vector X*splat(1.0) -> X in all defined cases.
|
||||
if (Constant *Splat = Op1V->getSplatValue()) {
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Splat))
|
||||
if (CI->equalsInt(1))
|
||||
return ReplaceInstUsesWith(I, Op0);
|
||||
}
|
||||
}
|
||||
if (match(Op1, m_AllOnes())) // X * -1 == 0 - X
|
||||
return BinaryOperator::CreateNeg(Op0, I.getName());
|
||||
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
||||
|
||||
// ((X << C1)*C2) == (X * (C2 << C1))
|
||||
if (BinaryOperator *SI = dyn_cast<BinaryOperator>(Op0))
|
||||
if (SI->getOpcode() == Instruction::Shl)
|
||||
if (Constant *ShOp = dyn_cast<Constant>(SI->getOperand(1)))
|
||||
return BinaryOperator::CreateMul(SI->getOperand(0),
|
||||
ConstantExpr::getShl(CI, ShOp));
|
||||
|
||||
const APInt &Val = CI->getValue();
|
||||
if (Val.isPowerOf2()) { // Replace X*(2^C) with X << C
|
||||
Constant *NewCst = ConstantInt::get(Op0->getType(), Val.logBase2());
|
||||
BinaryOperator *Shl = BinaryOperator::CreateShl(Op0, NewCst);
|
||||
if (I.hasNoSignedWrap()) Shl->setHasNoSignedWrap();
|
||||
if (I.hasNoUnsignedWrap()) Shl->setHasNoUnsignedWrap();
|
||||
return Shl;
|
||||
}
|
||||
|
||||
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0))
|
||||
if (Op0I->getOpcode() == Instruction::Add && Op0I->hasOneUse() &&
|
||||
isa<ConstantInt>(Op0I->getOperand(1)) && isa<ConstantInt>(Op1C)) {
|
||||
// Canonicalize (X+C1)*C2 -> X*C2+C1*C2.
|
||||
Value *Add = Builder->CreateMul(Op0I->getOperand(0), Op1C, "tmp");
|
||||
Value *C1C2 = Builder->CreateMul(Op1C, Op0I->getOperand(1));
|
||||
return BinaryOperator::CreateAdd(Add, C1C2);
|
||||
|
||||
// Canonicalize (X+C1)*CI -> X*CI+C1*CI.
|
||||
{ Value *X; ConstantInt *C1;
|
||||
if (Op0->hasOneUse() &&
|
||||
match(Op0, m_Add(m_Value(X), m_ConstantInt(C1)))) {
|
||||
Value *Add = Builder->CreateMul(X, CI, "tmp");
|
||||
return BinaryOperator::CreateAdd(Add, Builder->CreateMul(C1, CI));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Simplify mul instructions with a constant RHS.
|
||||
if (isa<Constant>(Op1)) {
|
||||
// Try to fold constant mul into select arguments.
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
||||
|
@ -324,9 +306,8 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) {
|
|||
if (MultiplyOverflows(RHS, LHSRHS,
|
||||
I.getOpcode()==Instruction::SDiv))
|
||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||
else
|
||||
return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
|
||||
ConstantExpr::getMul(RHS, LHSRHS));
|
||||
return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
|
||||
ConstantExpr::getMul(RHS, LHSRHS));
|
||||
}
|
||||
|
||||
if (!RHS->isZero()) { // avoid X udiv 0
|
||||
|
@ -365,54 +346,50 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
|
|||
// X udiv 2^C -> X >> C
|
||||
// Check to see if this is an unsigned division with an exact power of 2,
|
||||
// if so, convert to a right shift.
|
||||
if (C->getValue().isPowerOf2()) // 0 not included in isPowerOf2
|
||||
return BinaryOperator::CreateLShr(Op0,
|
||||
if (C->getValue().isPowerOf2()) { // 0 not included in isPowerOf2
|
||||
BinaryOperator *LShr =
|
||||
BinaryOperator::CreateLShr(Op0,
|
||||
ConstantInt::get(Op0->getType(), C->getValue().logBase2()));
|
||||
if (I.isExact()) LShr->setIsExact();
|
||||
return LShr;
|
||||
}
|
||||
|
||||
// X udiv C, where C >= signbit
|
||||
if (C->getValue().isNegative()) {
|
||||
Value *IC = Builder->CreateICmpULT( Op0, C);
|
||||
Value *IC = Builder->CreateICmpULT(Op0, C);
|
||||
return SelectInst::Create(IC, Constant::getNullValue(I.getType()),
|
||||
ConstantInt::get(I.getType(), 1));
|
||||
}
|
||||
}
|
||||
|
||||
// X udiv (C1 << N), where C1 is "1<<C2" --> X >> (N+C2)
|
||||
if (BinaryOperator *RHSI = dyn_cast<BinaryOperator>(I.getOperand(1))) {
|
||||
if (RHSI->getOpcode() == Instruction::Shl &&
|
||||
isa<ConstantInt>(RHSI->getOperand(0))) {
|
||||
const APInt& C1 = cast<ConstantInt>(RHSI->getOperand(0))->getValue();
|
||||
if (C1.isPowerOf2()) {
|
||||
Value *N = RHSI->getOperand(1);
|
||||
const Type *NTy = N->getType();
|
||||
if (uint32_t C2 = C1.logBase2())
|
||||
N = Builder->CreateAdd(N, ConstantInt::get(NTy, C2), "tmp");
|
||||
return BinaryOperator::CreateLShr(Op0, N);
|
||||
}
|
||||
{ const APInt *CI; Value *N;
|
||||
if (match(Op1, m_Shl(m_Power2(CI), m_Value(N)))) {
|
||||
if (*CI != 1)
|
||||
N = Builder->CreateAdd(N, ConstantInt::get(I.getType(), CI->logBase2()),
|
||||
"tmp");
|
||||
if (I.isExact())
|
||||
return BinaryOperator::CreateExactLShr(Op0, N);
|
||||
return BinaryOperator::CreateLShr(Op0, N);
|
||||
}
|
||||
}
|
||||
|
||||
// udiv X, (Select Cond, C1, C2) --> Select Cond, (shr X, C1), (shr X, C2)
|
||||
// where C1&C2 are powers of two.
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
||||
if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
|
||||
if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2))) {
|
||||
const APInt &TVA = STO->getValue(), &FVA = SFO->getValue();
|
||||
if (TVA.isPowerOf2() && FVA.isPowerOf2()) {
|
||||
// Compute the shift amounts
|
||||
uint32_t TSA = TVA.logBase2(), FSA = FVA.logBase2();
|
||||
// Construct the "on true" case of the select
|
||||
Constant *TC = ConstantInt::get(Op0->getType(), TSA);
|
||||
Value *TSI = Builder->CreateLShr(Op0, TC, SI->getName()+".t");
|
||||
{ Value *Cond; const APInt *C1, *C2;
|
||||
if (match(Op1, m_Select(m_Value(Cond), m_Power2(C1), m_Power2(C2)))) {
|
||||
// Construct the "on true" case of the select
|
||||
Value *TSI = Builder->CreateLShr(Op0, C1->logBase2(), Op1->getName()+".t",
|
||||
I.isExact());
|
||||
|
||||
// Construct the "on false" case of the select
|
||||
Constant *FC = ConstantInt::get(Op0->getType(), FSA);
|
||||
Value *FSI = Builder->CreateLShr(Op0, FC, SI->getName()+".f");
|
||||
|
||||
// construct the select instruction and return it.
|
||||
return SelectInst::Create(SI->getOperand(0), TSI, FSI, SI->getName());
|
||||
}
|
||||
}
|
||||
// Construct the "on false" case of the select
|
||||
Value *FSI = Builder->CreateLShr(Op0, C2->logBase2(), Op1->getName()+".f",
|
||||
I.isExact());
|
||||
|
||||
// construct the select instruction and return it.
|
||||
return SelectInst::Create(Cond, TSI, FSI);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -431,20 +408,17 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
|
|||
if (RHS->isAllOnesValue())
|
||||
return BinaryOperator::CreateNeg(Op0);
|
||||
|
||||
// sdiv X, C --> ashr X, log2(C)
|
||||
if (cast<SDivOperator>(&I)->isExact() &&
|
||||
RHS->getValue().isNonNegative() &&
|
||||
// sdiv X, C --> ashr exact X, log2(C)
|
||||
if (I.isExact() && RHS->getValue().isNonNegative() &&
|
||||
RHS->getValue().isPowerOf2()) {
|
||||
Value *ShAmt = llvm::ConstantInt::get(RHS->getType(),
|
||||
RHS->getValue().exactLogBase2());
|
||||
return BinaryOperator::CreateAShr(Op0, ShAmt, I.getName());
|
||||
return BinaryOperator::CreateExactAShr(Op0, ShAmt, I.getName());
|
||||
}
|
||||
|
||||
// -X/C --> X/-C provided the negation doesn't overflow.
|
||||
if (SubOperator *Sub = dyn_cast<SubOperator>(Op0))
|
||||
if (isa<Constant>(Sub->getOperand(0)) &&
|
||||
cast<Constant>(Sub->getOperand(0))->isNullValue() &&
|
||||
Sub->hasNoSignedWrap())
|
||||
if (match(Sub->getOperand(0), m_Zero()) && Sub->hasNoSignedWrap())
|
||||
return BinaryOperator::CreateSDiv(Sub->getOperand(1),
|
||||
ConstantExpr::getNeg(RHS));
|
||||
}
|
||||
|
@ -458,9 +432,8 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
|
|||
// X sdiv Y -> X udiv Y, iff X and Y don't have sign bit set
|
||||
return BinaryOperator::CreateUDiv(Op0, Op1, I.getName());
|
||||
}
|
||||
ConstantInt *ShiftedInt;
|
||||
if (match(Op1, m_Shl(m_ConstantInt(ShiftedInt), m_Value())) &&
|
||||
ShiftedInt->getValue().isPowerOf2()) {
|
||||
|
||||
if (match(Op1, m_Shl(m_Power2(), m_Value()))) {
|
||||
// X sdiv (1 << Y) -> X udiv (1 << Y) ( -> X u>> Y)
|
||||
// Safe because the only negative value (1 << Y) can take on is
|
||||
// INT_MIN, and X sdiv INT_MIN == X udiv INT_MIN == 0 if X doesn't have
|
||||
|
@ -555,43 +528,30 @@ Instruction *InstCombiner::visitURem(BinaryOperator &I) {
|
|||
if (Instruction *common = commonIRemTransforms(I))
|
||||
return common;
|
||||
|
||||
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
|
||||
// X urem C^2 -> X and C
|
||||
// Check to see if this is an unsigned remainder with an exact power of 2,
|
||||
// if so, convert to a bitwise and.
|
||||
if (ConstantInt *C = dyn_cast<ConstantInt>(RHS))
|
||||
if (C->getValue().isPowerOf2())
|
||||
return BinaryOperator::CreateAnd(Op0, SubOne(C));
|
||||
// X urem C^2 -> X and C-1
|
||||
{ const APInt *C;
|
||||
if (match(Op1, m_Power2(C)))
|
||||
return BinaryOperator::CreateAnd(Op0,
|
||||
ConstantInt::get(I.getType(), *C-1));
|
||||
}
|
||||
|
||||
if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
|
||||
// Turn A % (C << N), where C is 2^k, into A & ((C << N)-1)
|
||||
if (RHSI->getOpcode() == Instruction::Shl &&
|
||||
isa<ConstantInt>(RHSI->getOperand(0))) {
|
||||
if (cast<ConstantInt>(RHSI->getOperand(0))->getValue().isPowerOf2()) {
|
||||
Constant *N1 = Constant::getAllOnesValue(I.getType());
|
||||
Value *Add = Builder->CreateAdd(RHSI, N1, "tmp");
|
||||
return BinaryOperator::CreateAnd(Op0, Add);
|
||||
}
|
||||
// Turn A % (C << N), where C is 2^k, into A & ((C << N)-1)
|
||||
if (match(Op1, m_Shl(m_Power2(), m_Value()))) {
|
||||
Constant *N1 = Constant::getAllOnesValue(I.getType());
|
||||
Value *Add = Builder->CreateAdd(Op1, N1, "tmp");
|
||||
return BinaryOperator::CreateAnd(Op0, Add);
|
||||
}
|
||||
|
||||
// urem X, (select Cond, 2^C1, 2^C2) -->
|
||||
// select Cond, (and X, C1-1), (and X, C2-1)
|
||||
// when C1&C2 are powers of two.
|
||||
{ Value *Cond; const APInt *C1, *C2;
|
||||
if (match(Op1, m_Select(m_Value(Cond), m_Power2(C1), m_Power2(C2)))) {
|
||||
Value *TrueAnd = Builder->CreateAnd(Op0, *C1-1, Op1->getName()+".t");
|
||||
Value *FalseAnd = Builder->CreateAnd(Op0, *C2-1, Op1->getName()+".f");
|
||||
return SelectInst::Create(Cond, TrueAnd, FalseAnd);
|
||||
}
|
||||
}
|
||||
|
||||
// urem X, (select Cond, 2^C1, 2^C2) --> select Cond, (and X, C1), (and X, C2)
|
||||
// where C1&C2 are powers of two.
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
|
||||
if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
|
||||
if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2))) {
|
||||
// STO == 0 and SFO == 0 handled above.
|
||||
if ((STO->getValue().isPowerOf2()) &&
|
||||
(SFO->getValue().isPowerOf2())) {
|
||||
Value *TrueAnd = Builder->CreateAnd(Op0, SubOne(STO),
|
||||
SI->getName()+".t");
|
||||
Value *FalseAnd = Builder->CreateAnd(Op0, SubOne(SFO),
|
||||
SI->getName()+".f");
|
||||
return SelectInst::Create(SI->getOperand(0), TrueAnd, FalseAnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -37,17 +37,18 @@ Instruction *InstCombiner::commonShiftTransforms(BinaryOperator &I) {
|
|||
return Res;
|
||||
|
||||
// X shift (A srem B) -> X shift (A and B-1) iff B is a power of 2.
|
||||
// Because shifts by negative values are undefined.
|
||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op1))
|
||||
if (BO->hasOneUse() && BO->getOpcode() == Instruction::SRem)
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(BO->getOperand(1)))
|
||||
if (CI->getValue().isPowerOf2()) {
|
||||
Constant *C = ConstantInt::get(BO->getType(), CI->getValue()-1);
|
||||
Value *Rem = Builder->CreateAnd(BO->getOperand(0), C, BO->getName());
|
||||
I.setOperand(1, Rem);
|
||||
return &I;
|
||||
}
|
||||
|
||||
// Because shifts by negative values (which could occur if A were negative)
|
||||
// are undefined.
|
||||
Value *A; const APInt *B;
|
||||
if (Op1->hasOneUse() && match(Op1, m_SRem(m_Value(A), m_Power2(B)))) {
|
||||
// FIXME: Should this get moved into SimplifyDemandedBits by saying we don't
|
||||
// demand the sign bit (and many others) here??
|
||||
Value *Rem = Builder->CreateAnd(A, ConstantInt::get(I.getType(), *B-1),
|
||||
Op1->getName());
|
||||
I.setOperand(1, Rem);
|
||||
return &I;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -621,7 +622,30 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) {
|
|||
I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
|
||||
TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
return commonShiftTransforms(I);
|
||||
|
||||
if (Instruction *V = commonShiftTransforms(I))
|
||||
return V;
|
||||
|
||||
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(I.getOperand(1))) {
|
||||
unsigned ShAmt = Op1C->getZExtValue();
|
||||
|
||||
// If the shifted-out value is known-zero, then this is a NUW shift.
|
||||
if (!I.hasNoUnsignedWrap() &&
|
||||
MaskedValueIsZero(I.getOperand(0),
|
||||
APInt::getHighBitsSet(Op1C->getBitWidth(), ShAmt))) {
|
||||
I.setHasNoUnsignedWrap();
|
||||
return &I;
|
||||
}
|
||||
|
||||
// If the shifted out value is all signbits, this is a NSW shift.
|
||||
if (!I.hasNoSignedWrap() &&
|
||||
ComputeNumSignBits(I.getOperand(0)) > ShAmt) {
|
||||
I.setHasNoSignedWrap();
|
||||
return &I;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
||||
|
@ -634,7 +658,9 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
|||
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1))
|
||||
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
|
||||
unsigned ShAmt = Op1C->getZExtValue();
|
||||
|
||||
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op0)) {
|
||||
unsigned BitWidth = Op0->getType()->getScalarSizeInBits();
|
||||
// ctlz.i32(x)>>5 --> zext(x == 0)
|
||||
|
@ -643,7 +669,7 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
|||
if ((II->getIntrinsicID() == Intrinsic::ctlz ||
|
||||
II->getIntrinsicID() == Intrinsic::cttz ||
|
||||
II->getIntrinsicID() == Intrinsic::ctpop) &&
|
||||
isPowerOf2_32(BitWidth) && Log2_32(BitWidth) == Op1C->getZExtValue()){
|
||||
isPowerOf2_32(BitWidth) && Log2_32(BitWidth) == ShAmt) {
|
||||
bool isCtPop = II->getIntrinsicID() == Intrinsic::ctpop;
|
||||
Constant *RHS = ConstantInt::getSigned(Op0->getType(), isCtPop ? -1:0);
|
||||
Value *Cmp = Builder->CreateICmpEQ(II->getArgOperand(0), RHS);
|
||||
|
@ -651,6 +677,14 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
|||
}
|
||||
}
|
||||
|
||||
// If the shifted-out value is known-zero, then this is an exact shift.
|
||||
if (!I.isExact() &&
|
||||
MaskedValueIsZero(Op0,APInt::getLowBitsSet(Op1C->getBitWidth(),ShAmt))){
|
||||
I.setIsExact();
|
||||
return &I;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -665,13 +699,15 @@ Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
|
|||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
|
||||
unsigned ShAmt = Op1C->getZExtValue();
|
||||
|
||||
// If the input is a SHL by the same constant (ashr (shl X, C), C), then we
|
||||
// have a sign-extend idiom.
|
||||
Value *X;
|
||||
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1)))) {
|
||||
// If the input value is known to already be sign extended enough, delete
|
||||
// the extension.
|
||||
if (ComputeNumSignBits(X) > Op1C->getZExtValue())
|
||||
// If the left shift is just shifting out partial signbits, delete the
|
||||
// extension.
|
||||
if (cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap())
|
||||
return ReplaceInstUsesWith(I, X);
|
||||
|
||||
// If the input is an extension from the shifted amount value, e.g.
|
||||
|
@ -686,6 +722,13 @@ Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
|
|||
return new SExtInst(ZI->getOperand(0), ZI->getType());
|
||||
}
|
||||
}
|
||||
|
||||
// If the shifted-out value is known-zero, then this is an exact shift.
|
||||
if (!I.isExact() &&
|
||||
MaskedValueIsZero(Op0,APInt::getLowBitsSet(Op1C->getBitWidth(),ShAmt))){
|
||||
I.setIsExact();
|
||||
return &I;
|
||||
}
|
||||
}
|
||||
|
||||
// See if we can turn a signed shr into an unsigned shr.
|
||||
|
|
|
@ -6,7 +6,7 @@ define i64 @test(i64 %X) {
|
|||
%Y = shl i64 %X, 16 ; <i64> [#uses=1]
|
||||
; CHECK: %Y = shl i64 %X, 16
|
||||
%Z = ashr i64 %Y, 16 ; <i64> [#uses=1]
|
||||
; CHECK: %Z = ashr i64 %Y, 16
|
||||
; CHECK: %Z = ashr exact i64 %Y, 16
|
||||
ret i64 %Z
|
||||
; CHECK: ret i64 %Z
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
; PR1271
|
||||
; RUN: opt < %s -instcombine -S | \
|
||||
; RUN: grep {ashr i32 %.mp137, 2}
|
||||
; END.
|
||||
; RUN: grep {ashr exact i32 %.mp137, 2}
|
||||
|
||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
|
||||
target triple = "i686-pc-linux-gnu"
|
||||
|
|
|
@ -452,7 +452,7 @@ define i64 @test48(i8 %A, i8 %a) {
|
|||
; CHECK: @test48
|
||||
; CHECK-NEXT: %b = zext i8 %a to i64
|
||||
; CHECK-NEXT: %B = zext i8 %A to i64
|
||||
; CHECK-NEXT: %C = shl i64 %B, 8
|
||||
; CHECK-NEXT: %C = shl nuw nsw i64 %B, 8
|
||||
; CHECK-NEXT: %D = or i64 %C, %b
|
||||
; CHECK-NEXT: ret i64 %D
|
||||
}
|
||||
|
@ -464,7 +464,7 @@ define i64 @test49(i64 %A) {
|
|||
ret i64 %D
|
||||
; CHECK: @test49
|
||||
; CHECK-NEXT: %C = shl i64 %A, 32
|
||||
; CHECK-NEXT: ashr i64 %C, 32
|
||||
; CHECK-NEXT: ashr exact i64 %C, 32
|
||||
; CHECK-NEXT: %D = or i64 {{.*}}, 1
|
||||
; CHECK-NEXT: ret i64 %D
|
||||
}
|
||||
|
@ -478,8 +478,8 @@ define i64 @test50(i64 %A) {
|
|||
; CHECK: @test50
|
||||
; CHECK-NEXT: shl i64 %A, 30
|
||||
; CHECK-NEXT: add i64 {{.*}}, -4294967296
|
||||
; CHECK-NEXT: %E = ashr i64 {{.*}}, 32
|
||||
; CHECK-NEXT: ret i64 %E
|
||||
; CHECK-NEXT: %sext = ashr i64 {{.*}}, 32
|
||||
; CHECK-NEXT: ret i64 %sext
|
||||
}
|
||||
|
||||
define i64 @test51(i64 %A, i1 %cond) {
|
||||
|
|
|
@ -7,6 +7,13 @@ define i32 @sdiv1(i32 %x) {
|
|||
ret i32 %y
|
||||
}
|
||||
|
||||
; CHECK: @sdiv2
|
||||
; CHECK: ashr exact i32 %x, 3
|
||||
define i32 @sdiv2(i32 %x) {
|
||||
%y = sdiv exact i32 %x, 8
|
||||
ret i32 %y
|
||||
}
|
||||
|
||||
; CHECK: @sdiv3
|
||||
; CHECK: %y = srem i32 %x, 3
|
||||
; CHECK: %z = sub i32 %x, %y
|
||||
|
@ -52,6 +59,24 @@ define i32 @udiv1(i32 %x, i32 %w) {
|
|||
ret i32 %z
|
||||
}
|
||||
|
||||
; CHECK: @udiv2
|
||||
; CHECK: %z = lshr exact i32 %x, %w
|
||||
; CHECK: ret i32 %z
|
||||
define i32 @udiv2(i32 %x, i32 %w) {
|
||||
%y = shl i32 1, %w
|
||||
%z = udiv exact i32 %x, %y
|
||||
ret i32 %z
|
||||
}
|
||||
|
||||
; CHECK: @ashr1
|
||||
; CHECK: %B = ashr exact i64 %A, 2
|
||||
; CHECK: ret i64 %B
|
||||
define i64 @ashr1(i64 %X) nounwind {
|
||||
%A = shl i64 %X, 8
|
||||
%B = ashr i64 %A, 2 ; X/4
|
||||
ret i64 %B
|
||||
}
|
||||
|
||||
; CHECK: @ashr_icmp
|
||||
; CHECK: %B = icmp eq i64 %X, 0
|
||||
; CHECK: ret i1 %B
|
||||
|
|
|
@ -28,3 +28,12 @@ define i1 @shl_icmp(i64 %X) nounwind {
|
|||
ret i1 %B
|
||||
}
|
||||
|
||||
; CHECK: @shl1
|
||||
; CHECK: %B = shl nuw nsw i64 %A, 8
|
||||
; CHECK: ret i64 %B
|
||||
define i64 @shl1(i64 %X, i64* %P) nounwind {
|
||||
%A = and i64 %X, 312
|
||||
store i64 %A, i64* %P ; multiple uses of A.
|
||||
%B = shl i64 %A, 8
|
||||
ret i64 %B
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ for.cond: ; preds = %for.cond, %codeRepl
|
|||
store i32 %storemerge, i32* @g_2, align 4
|
||||
%shl = shl i32 %storemerge, 30
|
||||
%conv2 = lshr i32 %shl, 24
|
||||
; CHECK: %0 = shl i32 %storemerge, 6
|
||||
; CHECK: %0 = shl nuw nsw i32 %storemerge, 6
|
||||
; CHECK: %conv2 = and i32 %0, 64
|
||||
%tobool = icmp eq i32 %conv2, 0
|
||||
br i1 %tobool, label %for.cond, label %codeRepl2
|
||||
|
|
|
@ -110,7 +110,7 @@ entry:
|
|||
ret i32 %b
|
||||
; CHECK: @test10
|
||||
; CHECK: shl i32 %i, 30
|
||||
; CHECK-NEXT: ashr i32
|
||||
; CHECK-NEXT: ashr exact i32
|
||||
; CHECK-NEXT: ret i32
|
||||
}
|
||||
|
||||
|
|
|
@ -451,7 +451,7 @@ entry:
|
|||
ret i64 %tmp46
|
||||
|
||||
; CHECK: @test37
|
||||
; CHECK: %tmp23 = shl i128 %tmp22, 32
|
||||
; CHECK: %tmp23 = shl nuw nsw i128 %tmp22, 32
|
||||
; CHECK: %ins = or i128 %tmp23, %A
|
||||
; CHECK: %tmp46 = trunc i128 %ins to i64
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ define i32 @test1(i32 %x) {
|
|||
ret i32 %tmp.3
|
||||
; CHECK: @test1
|
||||
; CHECK: %sext = shl i32 %x, 16
|
||||
; CHECK: %tmp.3 = ashr i32 %sext, 16
|
||||
; CHECK: %tmp.3 = ashr exact i32 %sext, 16
|
||||
; CHECK: ret i32 %tmp.3
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ define i32 @test2(i32 %x) {
|
|||
ret i32 %tmp.3
|
||||
; CHECK: @test2
|
||||
; CHECK: %sext = shl i32 %x, 16
|
||||
; CHECK: %tmp.3 = ashr i32 %sext, 16
|
||||
; CHECK: %tmp.3 = ashr exact i32 %sext, 16
|
||||
; CHECK: ret i32 %tmp.3
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ define i32 @test5(i32 %x) {
|
|||
ret i32 %tmp.3
|
||||
; CHECK: @test5
|
||||
; CHECK: %sext = shl i32 %x, 24
|
||||
; CHECK: %tmp.3 = ashr i32 %sext, 24
|
||||
; CHECK: %tmp.3 = ashr exact i32 %sext, 24
|
||||
; CHECK: ret i32 %tmp.3
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ define i32 @test6(i32 %x) {
|
|||
ret i32 %tmp.4
|
||||
; CHECK: @test6
|
||||
; CHECK: %tmp.2 = shl i32 %x, 16
|
||||
; CHECK: %tmp.4 = ashr i32 %tmp.2, 16
|
||||
; CHECK: %tmp.4 = ashr exact i32 %tmp.2, 16
|
||||
; CHECK: ret i32 %tmp.4
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,6 @@ entry:
|
|||
%sub = add i32 %xor, -67108864 ; <i32> [#uses=1]
|
||||
ret i32 %sub
|
||||
; CHECK: @test8
|
||||
; CHECK: %sub = ashr i32 %x, 5
|
||||
; CHECK: ret i32 %sub
|
||||
; CHECK: %shr = ashr i32 %x, 5
|
||||
; CHECK: ret i32 %shr
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ define i64 @test2(i64 %a) {
|
|||
ret i64 %d
|
||||
; CHECK: @test2
|
||||
; CHECK: shl i64 %a, 36
|
||||
; CHECK: %d = ashr i64 {{.*}}, 36
|
||||
; CHECK: %d = ashr exact i64 {{.*}}, 36
|
||||
; CHECK: ret i64 %d
|
||||
}
|
||||
define i64 @test3(i64 %a) {
|
||||
|
@ -92,7 +92,7 @@ define i64 @test8(i32 %A, i32 %B) {
|
|||
; CHECK: @test8
|
||||
; CHECK: %tmp38 = zext i32 %A to i64
|
||||
; CHECK: %tmp32 = zext i32 %B to i64
|
||||
; CHECK: %tmp33 = shl i64 %tmp32, 32
|
||||
; CHECK: %tmp33 = shl nuw i64 %tmp32, 32
|
||||
; CHECK: %ins35 = or i64 %tmp33, %tmp38
|
||||
; CHECK: ret i64 %ins35
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue