mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[InstCombine] improve demanded bits analysis of left-shifted operand
If we don't demand high bits, then we also don't care about those high bits of a left-shift operand regardless of shift amount. I noticed the sext/trunc pattern in a motivating example. It seems like there should be a low-bits with right-shift sibling, but I haven't looked at that yet. https://alive2.llvm.org/ce/z/JuS6jc https://rise4fun.com/Alive/Trm (not sure how to use 'width' with Alive1) https://alive2.llvm.org/ce/z/gRadbF Differential Revision: https://reviews.llvm.org/D101489
This commit is contained in:
parent
c7e45bd25e
commit
e3bd2dc38e
@ -559,6 +559,14 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||
return UndefValue::get(I->getType());
|
||||
}
|
||||
} else {
|
||||
// This is a variable shift, so we can't shift the demand mask by a known
|
||||
// amount. But if we are not demanding high bits, then we are not
|
||||
// demanding those bits from the pre-shifted operand either.
|
||||
if (unsigned CTLZ = DemandedMask.countLeadingZeros()) {
|
||||
APInt DemandedFromOp(APInt::getLowBitsSet(BitWidth, BitWidth - CTLZ));
|
||||
if (SimplifyDemandedBits(I, 0, DemandedFromOp, Known, Depth + 1))
|
||||
return I;
|
||||
}
|
||||
computeKnownBits(I, Known, Depth, CxtI);
|
||||
}
|
||||
break;
|
||||
|
@ -443,7 +443,8 @@ define i8 @rotate_right_commute_8bit_unmasked_shl(i32 %v, i32 %shift) {
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHIFT:%.*]] to i8
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], 3
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[V:%.*]] to i8
|
||||
; CHECK-NEXT: [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[TMP3]], i8 [[TMP3]], i8 [[TMP2]])
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[V]] to i8
|
||||
; CHECK-NEXT: [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[TMP3]], i8 [[TMP4]], i8 [[TMP2]])
|
||||
; CHECK-NEXT: ret i8 [[CONV2]]
|
||||
;
|
||||
%and = and i32 %shift, 3
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
define i16 @sext_shl_trunc_same_size(i16 %x, i32 %y) {
|
||||
; CHECK-LABEL: @sext_shl_trunc_same_size(
|
||||
; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[CONV1:%.*]] = zext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV1]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[T:%.*]] = trunc i32 [[SHL]] to i16
|
||||
; CHECK-NEXT: ret i16 [[T]]
|
||||
;
|
||||
@ -16,8 +16,8 @@ define i16 @sext_shl_trunc_same_size(i16 %x, i32 %y) {
|
||||
|
||||
define i5 @sext_shl_trunc_smaller(i16 %x, i32 %y) {
|
||||
; CHECK-LABEL: @sext_shl_trunc_smaller(
|
||||
; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[CONV1:%.*]] = zext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV1]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[T:%.*]] = trunc i32 [[SHL]] to i5
|
||||
; CHECK-NEXT: ret i5 [[T]]
|
||||
;
|
||||
@ -27,6 +27,8 @@ define i5 @sext_shl_trunc_smaller(i16 %x, i32 %y) {
|
||||
ret i5 %t
|
||||
}
|
||||
|
||||
; negative test - demanding 1 high-bit too many to change the extend
|
||||
|
||||
define i17 @sext_shl_trunc_larger(i16 %x, i32 %y) {
|
||||
; CHECK-LABEL: @sext_shl_trunc_larger(
|
||||
; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
|
||||
@ -42,8 +44,8 @@ define i17 @sext_shl_trunc_larger(i16 %x, i32 %y) {
|
||||
|
||||
define i32 @sext_shl_mask(i16 %x, i32 %y) {
|
||||
; CHECK-LABEL: @sext_shl_mask(
|
||||
; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[CONV1:%.*]] = zext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV1]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[T:%.*]] = and i32 [[SHL]], 65535
|
||||
; CHECK-NEXT: ret i32 [[T]]
|
||||
;
|
||||
@ -53,6 +55,8 @@ define i32 @sext_shl_mask(i16 %x, i32 %y) {
|
||||
ret i32 %t
|
||||
}
|
||||
|
||||
; negative test - demanding a bit that could change with sext
|
||||
|
||||
define i32 @sext_shl_mask_higher(i16 %x, i32 %y) {
|
||||
; CHECK-LABEL: @sext_shl_mask_higher(
|
||||
; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
|
||||
@ -66,9 +70,11 @@ define i32 @sext_shl_mask_higher(i16 %x, i32 %y) {
|
||||
ret i32 %t
|
||||
}
|
||||
|
||||
; May need some, but not all of the bits set by the 'or'.
|
||||
|
||||
define i32 @set_shl_mask(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: @set_shl_mask(
|
||||
; CHECK-NEXT: [[Z:%.*]] = or i32 [[X:%.*]], 196609
|
||||
; CHECK-NEXT: [[Z:%.*]] = or i32 [[X:%.*]], 65537
|
||||
; CHECK-NEXT: [[S:%.*]] = shl i32 [[Z]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[S]], 65536
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
|
Loading…
Reference in New Issue
Block a user