forked from OSchip/llvm-project
[InstCombine] try harder to form rotate (funnel shift) (PR20750)
We have a similar match for patterns ending in a truncate. This should be ok for all targets because the default expansion would still likely be better from replacing 2 'and' ops with 1. Attempt to show the logic equivalence in Alive (which doesn't currently have funnel-shift in its vocabulary AFAICT): %shamt = zext i8 %i to i32 %m = and i32 %shamt, 31 %neg = sub i32 0, %shamt %and4 = and i32 %neg, 31 %shl = shl i32 %v, %m %shr = lshr i32 %v, %and4 %or = or i32 %shr, %shl => %a = and i8 %i, 31 %shamt2 = zext i8 %a to i32 %neg2 = sub i32 0, %shamt2 %and4 = and i32 %neg2, 31 %shl = shl i32 %v, %shamt2 %shr = lshr i32 %v, %and4 %or = or i32 %shr, %shl https://rise4fun.com/Alive/V9r llvm-svn: 360605
This commit is contained in:
parent
c33f754e74
commit
760f61ab36
|
@ -1898,6 +1898,13 @@ static Instruction *matchRotate(Instruction &Or) {
|
|||
match(R, m_And(m_Neg(m_Specific(X)), m_SpecificInt(Mask))))
|
||||
return X;
|
||||
|
||||
// Similar to above, but the shift amount may be extended after masking,
|
||||
// so return the extended value as the parameter for the intrinsic.
|
||||
if (match(L, m_ZExt(m_And(m_Value(X), m_SpecificInt(Mask)))) &&
|
||||
match(R, m_And(m_Neg(m_ZExt(m_And(m_Specific(X), m_SpecificInt(Mask)))),
|
||||
m_SpecificInt(Mask))))
|
||||
return L;
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
|
|
|
@ -710,13 +710,8 @@ define i32 @rotl_constant_expr(i32 %shamt) {
|
|||
|
||||
define i32 @rotateleft32_doubleand1(i32 %v, i8 %r) {
|
||||
; CHECK-LABEL: @rotateleft32_doubleand1(
|
||||
; CHECK-NEXT: [[M:%.*]] = and i8 [[R:%.*]], 31
|
||||
; CHECK-NEXT: [[Z:%.*]] = zext i8 [[M]] to i32
|
||||
; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[Z]]
|
||||
; CHECK-NEXT: [[AND2:%.*]] = and i32 [[NEG]], 31
|
||||
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[V:%.*]], [[Z]]
|
||||
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[V]], [[AND2]]
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], [[SHL]]
|
||||
; CHECK-NEXT: [[Z:%.*]] = zext i8 [[R:%.*]] to i32
|
||||
; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[V:%.*]], i32 [[V]], i32 [[Z]])
|
||||
; CHECK-NEXT: ret i32 [[OR]]
|
||||
;
|
||||
%m = and i8 %r, 31
|
||||
|
@ -731,13 +726,8 @@ define i32 @rotateleft32_doubleand1(i32 %v, i8 %r) {
|
|||
|
||||
define i32 @rotateright32_doubleand1(i32 %v, i16 %r) {
|
||||
; CHECK-LABEL: @rotateright32_doubleand1(
|
||||
; CHECK-NEXT: [[M:%.*]] = and i16 [[R:%.*]], 31
|
||||
; CHECK-NEXT: [[Z:%.*]] = zext i16 [[M]] to i32
|
||||
; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[Z]]
|
||||
; CHECK-NEXT: [[AND2:%.*]] = and i32 [[NEG]], 31
|
||||
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[V:%.*]], [[AND2]]
|
||||
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[V]], [[Z]]
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], [[SHL]]
|
||||
; CHECK-NEXT: [[Z:%.*]] = zext i16 [[R:%.*]] to i32
|
||||
; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[V:%.*]], i32 [[V]], i32 [[Z]])
|
||||
; CHECK-NEXT: ret i32 [[OR]]
|
||||
;
|
||||
%m = and i16 %r, 31
|
||||
|
|
Loading…
Reference in New Issue