mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-16 08:08:01 +00:00
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:
parent
98a7d766e3
commit
d6260dc3cb
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user