forked from OSchip/llvm-project
[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:
parent
94ead0190f
commit
fd679107d6
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue