forked from OSchip/llvm-project
[InstCombine] allow ashr/lshr demanded bits folds with splat constants
llvm-svn: 300888
This commit is contained in:
parent
3106fc476c
commit
fb5b3e773a
|
@ -503,9 +503,9 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||||
KnownZero.setLowBits(ShiftAmt);
|
KnownZero.setLowBits(ShiftAmt);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Instruction::LShr:
|
case Instruction::LShr: {
|
||||||
// For a logical shift right
|
const APInt *SA;
|
||||||
if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
if (match(I->getOperand(1), m_APInt(SA))) {
|
||||||
uint64_t ShiftAmt = SA->getLimitedValue(BitWidth-1);
|
uint64_t ShiftAmt = SA->getLimitedValue(BitWidth-1);
|
||||||
|
|
||||||
// Unsigned shift right.
|
// Unsigned shift right.
|
||||||
|
@ -526,7 +526,8 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||||
KnownZero.setHighBits(ShiftAmt); // high bits known zero.
|
KnownZero.setHighBits(ShiftAmt); // high bits known zero.
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Instruction::AShr:
|
}
|
||||||
|
case Instruction::AShr: {
|
||||||
// If this is an arithmetic shift right and only the low-bit is set, we can
|
// If this is an arithmetic shift right and only the low-bit is set, we can
|
||||||
// always convert this into a logical shr, even if the shift amount is
|
// always convert this into a logical shr, even if the shift amount is
|
||||||
// variable. The low bit of the shift cannot be an input sign bit unless
|
// variable. The low bit of the shift cannot be an input sign bit unless
|
||||||
|
@ -543,12 +544,13 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||||
if (DemandedMask.isSignMask())
|
if (DemandedMask.isSignMask())
|
||||||
return I->getOperand(0);
|
return I->getOperand(0);
|
||||||
|
|
||||||
if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
const APInt *SA;
|
||||||
|
if (match(I->getOperand(1), m_APInt(SA))) {
|
||||||
uint32_t ShiftAmt = SA->getLimitedValue(BitWidth-1);
|
uint32_t ShiftAmt = SA->getLimitedValue(BitWidth-1);
|
||||||
|
|
||||||
// Signed shift right.
|
// Signed shift right.
|
||||||
APInt DemandedMaskIn(DemandedMask.shl(ShiftAmt));
|
APInt DemandedMaskIn(DemandedMask.shl(ShiftAmt));
|
||||||
// If any of the "high bits" are demanded, we should set the sign bit as
|
// If any of the high bits are demanded, we should set the sign bit as
|
||||||
// demanded.
|
// demanded.
|
||||||
if (DemandedMask.countLeadingZeros() <= ShiftAmt)
|
if (DemandedMask.countLeadingZeros() <= ShiftAmt)
|
||||||
DemandedMaskIn.setSignBit();
|
DemandedMaskIn.setSignBit();
|
||||||
|
@ -561,6 +563,7 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||||
if (SimplifyDemandedBits(I, 0, DemandedMaskIn, KnownZero, KnownOne,
|
if (SimplifyDemandedBits(I, 0, DemandedMaskIn, KnownZero, KnownOne,
|
||||||
Depth + 1))
|
Depth + 1))
|
||||||
return I;
|
return I;
|
||||||
|
|
||||||
assert(!(KnownZero & KnownOne) && "Bits known to be one AND zero?");
|
assert(!(KnownZero & KnownOne) && "Bits known to be one AND zero?");
|
||||||
// Compute the new bits that are at the top now.
|
// Compute the new bits that are at the top now.
|
||||||
APInt HighBits(APInt::getHighBitsSet(BitWidth, ShiftAmt));
|
APInt HighBits(APInt::getHighBitsSet(BitWidth, ShiftAmt));
|
||||||
|
@ -576,16 +579,16 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||||
// are demanded, turn this into an unsigned shift right.
|
// are demanded, turn this into an unsigned shift right.
|
||||||
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.
|
BinaryOperator *LShr = BinaryOperator::CreateLShr(I->getOperand(0),
|
||||||
BinaryOperator *NewVal = BinaryOperator::CreateLShr(I->getOperand(0),
|
I->getOperand(1));
|
||||||
SA, I->getName());
|
LShr->setIsExact(cast<BinaryOperator>(I)->isExact());
|
||||||
NewVal->setIsExact(cast<BinaryOperator>(I)->isExact());
|
return InsertNewInstWith(LShr, *I);
|
||||||
return InsertNewInstWith(NewVal, *I);
|
|
||||||
} else if ((KnownOne & SignMask) != 0) { // New bits are known one.
|
} else if ((KnownOne & SignMask) != 0) { // New bits are known one.
|
||||||
KnownOne |= HighBits;
|
KnownOne |= HighBits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Instruction::SRem:
|
case Instruction::SRem:
|
||||||
if (ConstantInt *Rem = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
if (ConstantInt *Rem = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
||||||
// X % -1 demands all the bits because we don't want to introduce
|
// X % -1 demands all the bits because we don't want to introduce
|
||||||
|
|
|
@ -1270,8 +1270,7 @@ define <2 x i64> @test_64_splat_vec(<2 x i32> %t) {
|
||||||
|
|
||||||
define <2 x i8> @ashr_demanded_bits_splat(<2 x i8> %x) {
|
define <2 x i8> @ashr_demanded_bits_splat(<2 x i8> %x) {
|
||||||
; CHECK-LABEL: @ashr_demanded_bits_splat(
|
; CHECK-LABEL: @ashr_demanded_bits_splat(
|
||||||
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> %x, <i8 -128, i8 -128>
|
; CHECK-NEXT: [[SHR:%.*]] = ashr <2 x i8> %x, <i8 7, i8 7>
|
||||||
; CHECK-NEXT: [[SHR:%.*]] = ashr exact <2 x i8> [[AND]], <i8 7, i8 7>
|
|
||||||
; CHECK-NEXT: ret <2 x i8> [[SHR]]
|
; CHECK-NEXT: ret <2 x i8> [[SHR]]
|
||||||
;
|
;
|
||||||
%and = and <2 x i8> %x, <i8 128, i8 128>
|
%and = and <2 x i8> %x, <i8 128, i8 128>
|
||||||
|
@ -1281,8 +1280,7 @@ define <2 x i8> @ashr_demanded_bits_splat(<2 x i8> %x) {
|
||||||
|
|
||||||
define <2 x i8> @lshr_demanded_bits_splat(<2 x i8> %x) {
|
define <2 x i8> @lshr_demanded_bits_splat(<2 x i8> %x) {
|
||||||
; CHECK-LABEL: @lshr_demanded_bits_splat(
|
; CHECK-LABEL: @lshr_demanded_bits_splat(
|
||||||
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> %x, <i8 -128, i8 -128>
|
; CHECK-NEXT: [[SHR:%.*]] = lshr <2 x i8> %x, <i8 7, i8 7>
|
||||||
; CHECK-NEXT: [[SHR:%.*]] = lshr exact <2 x i8> [[AND]], <i8 7, i8 7>
|
|
||||||
; CHECK-NEXT: ret <2 x i8> [[SHR]]
|
; CHECK-NEXT: ret <2 x i8> [[SHR]]
|
||||||
;
|
;
|
||||||
%and = and <2 x i8> %x, <i8 128, i8 128>
|
%and = and <2 x i8> %x, <i8 128, i8 128>
|
||||||
|
|
|
@ -15,9 +15,9 @@ define <2 x i1> @test1(<2 x i64> %a) {
|
||||||
; The ashr turns into an lshr.
|
; The ashr turns into an lshr.
|
||||||
define <2 x i64> @test2(<2 x i64> %a) {
|
define <2 x i64> @test2(<2 x i64> %a) {
|
||||||
; CHECK-LABEL: @test2(
|
; CHECK-LABEL: @test2(
|
||||||
; CHECK-NEXT: [[B:%.*]] = and <2 x i64> %a, <i64 65535, i64 65535>
|
; CHECK-NEXT: [[B:%.*]] = and <2 x i64> %a, <i64 65534, i64 65534>
|
||||||
; CHECK-NEXT: [[T:%.*]] = lshr <2 x i64> [[B]], <i64 1, i64 1>
|
; CHECK-NEXT: [[TMP1:%.*]] = lshr exact <2 x i64> [[B]], <i64 1, i64 1>
|
||||||
; CHECK-NEXT: ret <2 x i64> [[T]]
|
; CHECK-NEXT: ret <2 x i64> [[TMP1]]
|
||||||
;
|
;
|
||||||
%b = and <2 x i64> %a, <i64 65535, i64 65535>
|
%b = and <2 x i64> %a, <i64 65535, i64 65535>
|
||||||
%t = ashr <2 x i64> %b, <i64 1, i64 1>
|
%t = ashr <2 x i64> %b, <i64 1, i64 1>
|
||||||
|
|
Loading…
Reference in New Issue