[InstCombine] Optimize away the unnecessary multi-use sign-extend

C.f. https://bugs.llvm.org/show_bug.cgi?id=47765

Added a case for handling the sign-extend (Shl+AShr) for multiple uses,
to optimize it away for an individual use,
when the demanded bits aren't affected by sign-extend.

https://rise4fun.com/Alive/lgf

Reviewed By: lebedev.ri

Differential Revision: https://reviews.llvm.org/D91343
This commit is contained in:
Bhramar Vatsa 2020-12-01 16:35:04 +03:00 committed by Roman Lebedev
parent 94ead0190f
commit fd679107d6
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
2 changed files with 35 additions and 2 deletions

View File

@ -899,6 +899,33 @@ Value *InstCombinerImpl::SimplifyMultipleUseDemandedBits(
break;
}
case Instruction::AShr: {
// Compute the Known bits to simplify things downstream.
computeKnownBits(I, Known, Depth, CxtI);
// If this user is only demanding bits that we know, return the known
// constant.
if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
return Constant::getIntegerValue(ITy, Known.One);
// If the right shift operand 0 is a result of a left shift by the same
// amount, this is probably a zero/sign extension, which may be unnecessary,
// if we do not demand any of the new sign bits. So, return the original
// operand instead.
const APInt *ShiftRC;
const APInt *ShiftLC;
Value *X;
unsigned BitWidth = DemandedMask.getBitWidth();
if (match(I,
m_AShr(m_Shl(m_Value(X), m_APInt(ShiftLC)), m_APInt(ShiftRC))) &&
ShiftLC == ShiftRC &&
DemandedMask.isSubsetOf(APInt::getLowBitsSet(
BitWidth, BitWidth - ShiftRC->getZExtValue()))) {
return X;
}
break;
}
default:
// Compute the Known bits to simplify things downstream.
computeKnownBits(I, Known, Depth, CxtI);

View File

@ -979,7 +979,7 @@ define i32 @lowmask_sext_in_reg(i32 %x) {
; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 20
; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[L]], 20
; CHECK-NEXT: call void @use32(i32 [[R]])
; CHECK-NEXT: [[AND:%.*]] = and i32 [[R]], 4095
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 4095
; CHECK-NEXT: ret i32 [[AND]]
;
%l = shl i32 %x, 20
@ -989,6 +989,8 @@ define i32 @lowmask_sext_in_reg(i32 %x) {
ret i32 %and
}
; Negative test - mismatched shift amounts
define i32 @lowmask_not_sext_in_reg(i32 %x) {
; CHECK-LABEL: @lowmask_not_sext_in_reg(
; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 19
@ -1004,6 +1006,8 @@ define i32 @lowmask_not_sext_in_reg(i32 %x) {
ret i32 %and
}
; Negative test - too much shift for mask
define i32 @not_lowmask_sext_in_reg(i32 %x) {
; CHECK-LABEL: @not_lowmask_sext_in_reg(
; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 20
@ -1019,6 +1023,8 @@ define i32 @not_lowmask_sext_in_reg(i32 %x) {
ret i32 %and
}
; Negative test - too much shift for mask
define i32 @not_lowmask_sext_in_reg2(i32 %x) {
; CHECK-LABEL: @not_lowmask_sext_in_reg2(
; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 21
@ -1039,7 +1045,7 @@ define <2 x i32> @lowmask_sext_in_reg_splat(<2 x i32> %x, <2 x i32>* %p) {
; CHECK-NEXT: [[L:%.*]] = shl <2 x i32> [[X:%.*]], <i32 20, i32 20>
; CHECK-NEXT: [[R:%.*]] = ashr exact <2 x i32> [[L]], <i32 20, i32 20>
; CHECK-NEXT: store <2 x i32> [[R]], <2 x i32>* [[P:%.*]], align 8
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[R]], <i32 4095, i32 4095>
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X]], <i32 4095, i32 4095>
; CHECK-NEXT: ret <2 x i32> [[AND]]
;
%l = shl <2 x i32> %x, <i32 20, i32 20>