Teach instcombine all sorts of great stuff about shifts that have exact, nuw or

nsw bits on them.

llvm-svn: 147528
This commit is contained in:
Nick Lewycky 2012-01-04 09:28:29 +00:00
parent 98a7d766e3
commit d6260dc3cb
3 changed files with 113 additions and 8 deletions

View File

@ -576,7 +576,16 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
ShiftOp->getOpcode() != Instruction::Shl) {
assert(ShiftOp->getOpcode() == Instruction::LShr ||
ShiftOp->getOpcode() == Instruction::AShr);
Value *Shift = Builder->CreateShl(X, ConstantInt::get(Ty, ShiftDiff));
ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);
if (ShiftOp->isExact()) {
// (X >>?,exact C1) << C2 --> X << (C2-C1)
BinaryOperator *NewShl = BinaryOperator::Create(Instruction::Shl,
X, ShiftDiffCst);
NewShl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());
NewShl->setHasNoSignedWrap(I.hasNoSignedWrap());
return NewShl;
}
Value *Shift = Builder->CreateShl(X, ShiftDiffCst);
APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2));
return BinaryOperator::CreateAnd(Shift,
@ -587,14 +596,35 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
if (I.getOpcode() == Instruction::LShr &&
ShiftOp->getOpcode() == Instruction::Shl) {
assert(ShiftOp->getOpcode() == Instruction::Shl);
Value *Shift = Builder->CreateLShr(X, ConstantInt::get(Ty, ShiftDiff));
ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);
// (X <<nuw C1) >>u C2 --> X >>u (C2-C1)
if (ShiftOp->hasNoUnsignedWrap()) {
BinaryOperator *NewLShr = BinaryOperator::Create(Instruction::LShr,
X, ShiftDiffCst);
NewLShr->setIsExact(I.isExact());
return NewLShr;
}
Value *Shift = Builder->CreateLShr(X, ShiftDiffCst);
APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2));
return BinaryOperator::CreateAnd(Shift,
ConstantInt::get(I.getContext(),Mask));
}
// We can't handle (X << C1) >>s C2, it shifts arbitrary bits in.
// We can't handle (X << C1) >>s C2, it shifts arbitrary bits in. However,
// we can handle (X <<nsw C1) >>s C2 since it only shifts in sign bits.
if (I.getOpcode() == Instruction::AShr &&
ShiftOp->getOpcode() == Instruction::Shl) {
assert(ShiftOp->getOpcode() == Instruction::Shl);
if (ShiftOp->hasNoSignedWrap()) {
// (X <<nsw C1) >>s C2 --> X >>s (C2-C1)
ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);
BinaryOperator *NewAShr = BinaryOperator::Create(Instruction::AShr,
X, ShiftDiffCst);
NewAShr->setIsExact(I.isExact());
return NewAShr;
}
}
} else {
assert(ShiftAmt2 < ShiftAmt1);
uint32_t ShiftDiff = ShiftAmt1-ShiftAmt2;
@ -620,14 +650,34 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
// (X << C1) >>u C2 --> X << (C1-C2) & (-1 >> C2)
if (I.getOpcode() == Instruction::LShr &&
ShiftOp->getOpcode() == Instruction::Shl) {
Value *Shift = Builder->CreateShl(X, ConstantInt::get(Ty, ShiftDiff));
ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);
if (ShiftOp->hasNoUnsignedWrap()) {
// (X <<nuw C1) >>u C2 --> X <<nuw (C1-C2)
BinaryOperator *NewShl = BinaryOperator::Create(Instruction::Shl,
X, ShiftDiffCst);
NewShl->setHasNoUnsignedWrap(true);
return NewShl;
}
Value *Shift = Builder->CreateShl(X, ShiftDiffCst);
APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2));
return BinaryOperator::CreateAnd(Shift,
ConstantInt::get(I.getContext(),Mask));
}
// We can't handle (X << C1) >>a C2, it shifts arbitrary bits in.
// We can't handle (X << C1) >>s C2, it shifts arbitrary bits in. However,
// we can handle (X <<nsw C1) >>s C2 since it only shifts in sign bits.
if (I.getOpcode() == Instruction::AShr &&
ShiftOp->getOpcode() == Instruction::Shl) {
if (ShiftOp->hasNoSignedWrap()) {
// (X <<nsw C1) >>s C2 --> X <<nsw (C1-C2)
ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);
BinaryOperator *NewShl = BinaryOperator::Create(Instruction::Shl,
X, ShiftDiffCst);
NewShl->setHasNoSignedWrap(true);
return NewShl;
}
}
}
}
return 0;

View File

@ -682,8 +682,9 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
if (BitWidth <= ShiftAmt || KnownZero[BitWidth-ShiftAmt-1] ||
(HighBits & ~DemandedMask) == HighBits) {
// Perform the logical shift right.
Instruction *NewVal = BinaryOperator::CreateLShr(
I->getOperand(0), SA, I->getName());
BinaryOperator *NewVal = BinaryOperator::CreateLShr(I->getOperand(0),
SA, I->getName());
NewVal->setIsExact(cast<BinaryOperator>(I)->isExact());
return InsertNewInstWith(NewVal, *I);
} else if ((KnownOne & SignBit) != 0) { // New bits are known one.
KnownOne |= HighBits;

View File

@ -560,3 +560,57 @@ define i32 @test47(i32 %a) {
; CHECK-NEXT: %z = lshr exact i32 %a, 2
; CHECK-NEXT: ret i32 %z
}
define i32 @test48(i32 %x) {
%A = lshr exact i32 %x, 1
%B = shl i32 %A, 3
ret i32 %B
; CHECK: @test48
; CHECK-NEXT: %B = shl i32 %x, 2
; CHECK-NEXT: ret i32 %B
}
define i32 @test49(i32 %x) {
%A = ashr exact i32 %x, 1
%B = shl i32 %A, 3
ret i32 %B
; CHECK: @test49
; CHECK-NEXT: %B = shl i32 %x, 2
; CHECK-NEXT: ret i32 %B
}
define i32 @test50(i32 %x) {
%A = shl nsw i32 %x, 1
%B = ashr i32 %A, 3
ret i32 %B
; CHECK: @test50
; CHECK-NEXT: %B = ashr i32 %x, 2
; CHECK-NEXT: ret i32 %B
}
define i32 @test51(i32 %x) {
%A = shl nuw i32 %x, 1
%B = lshr i32 %A, 3
ret i32 %B
; CHECK: @test51
; CHECK-NEXT: %B = lshr i32 %x, 2
; CHECK-NEXT: ret i32 %B
}
define i32 @test52(i32 %x) {
%A = shl nsw i32 %x, 3
%B = ashr i32 %A, 1
ret i32 %B
; CHECK: @test52
; CHECK-NEXT: %B = shl nsw i32 %x, 2
; CHECK-NEXT: ret i32 %B
}
define i32 @test53(i32 %x) {
%A = shl nuw i32 %x, 3
%B = lshr i32 %A, 1
ret i32 %B
; CHECK: @test53
; CHECK-NEXT: %B = shl nuw i32 %x, 2
; CHECK-NEXT: ret i32 %B
}