From: Sanjay Patel Date: Mon, 13 May 2019 17:28:19 +0000 (+0000) Subject: [InstCombine] try harder to form rotate (funnel shift) (PR20750) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8ddb73575732d3a8f40bf8d668d96c763c4a818c;p=llvm [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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360605 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 31cf6386918..f1766fd4fce 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -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; }; diff --git a/test/Transforms/InstCombine/rotate.ll b/test/Transforms/InstCombine/rotate.ll index 984dac1cbc1..a11fcd97424 100644 --- a/test/Transforms/InstCombine/rotate.ll +++ b/test/Transforms/InstCombine/rotate.ll @@ -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