mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-18 13:34:04 +00:00
Teach instcombine all sorts of great stuff about shifts that have exact, nuw or
nsw bits on them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147528 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
515783466c
commit
148fd55ef3
@ -576,7 +576,16 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
|
|||||||
ShiftOp->getOpcode() != Instruction::Shl) {
|
ShiftOp->getOpcode() != Instruction::Shl) {
|
||||||
assert(ShiftOp->getOpcode() == Instruction::LShr ||
|
assert(ShiftOp->getOpcode() == Instruction::LShr ||
|
||||||
ShiftOp->getOpcode() == Instruction::AShr);
|
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));
|
APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2));
|
||||||
return BinaryOperator::CreateAnd(Shift,
|
return BinaryOperator::CreateAnd(Shift,
|
||||||
@ -587,14 +596,35 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
|
|||||||
if (I.getOpcode() == Instruction::LShr &&
|
if (I.getOpcode() == Instruction::LShr &&
|
||||||
ShiftOp->getOpcode() == Instruction::Shl) {
|
ShiftOp->getOpcode() == Instruction::Shl) {
|
||||||
assert(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));
|
APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2));
|
||||||
return BinaryOperator::CreateAnd(Shift,
|
return BinaryOperator::CreateAnd(Shift,
|
||||||
ConstantInt::get(I.getContext(),Mask));
|
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 {
|
} else {
|
||||||
assert(ShiftAmt2 < ShiftAmt1);
|
assert(ShiftAmt2 < ShiftAmt1);
|
||||||
uint32_t ShiftDiff = ShiftAmt1-ShiftAmt2;
|
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)
|
// (X << C1) >>u C2 --> X << (C1-C2) & (-1 >> C2)
|
||||||
if (I.getOpcode() == Instruction::LShr &&
|
if (I.getOpcode() == Instruction::LShr &&
|
||||||
ShiftOp->getOpcode() == Instruction::Shl) {
|
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));
|
APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2));
|
||||||
return BinaryOperator::CreateAnd(Shift,
|
return BinaryOperator::CreateAnd(Shift,
|
||||||
ConstantInt::get(I.getContext(),Mask));
|
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;
|
return 0;
|
||||||
|
@ -682,8 +682,9 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
|||||||
if (BitWidth <= ShiftAmt || KnownZero[BitWidth-ShiftAmt-1] ||
|
if (BitWidth <= ShiftAmt || KnownZero[BitWidth-ShiftAmt-1] ||
|
||||||
(HighBits & ~DemandedMask) == HighBits) {
|
(HighBits & ~DemandedMask) == HighBits) {
|
||||||
// Perform the logical shift right.
|
// Perform the logical shift right.
|
||||||
Instruction *NewVal = BinaryOperator::CreateLShr(
|
BinaryOperator *NewVal = BinaryOperator::CreateLShr(I->getOperand(0),
|
||||||
I->getOperand(0), SA, I->getName());
|
SA, I->getName());
|
||||||
|
NewVal->setIsExact(cast<BinaryOperator>(I)->isExact());
|
||||||
return InsertNewInstWith(NewVal, *I);
|
return InsertNewInstWith(NewVal, *I);
|
||||||
} else if ((KnownOne & SignBit) != 0) { // New bits are known one.
|
} else if ((KnownOne & SignBit) != 0) { // New bits are known one.
|
||||||
KnownOne |= HighBits;
|
KnownOne |= HighBits;
|
||||||
|
@ -560,3 +560,57 @@ define i32 @test47(i32 %a) {
|
|||||||
; CHECK-NEXT: %z = lshr exact i32 %a, 2
|
; CHECK-NEXT: %z = lshr exact i32 %a, 2
|
||||||
; CHECK-NEXT: ret i32 %z
|
; 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…
x
Reference in New Issue
Block a user