]> granicus.if.org Git - llvm/commitdiff
[InstCombine] try harder to form rotate (funnel shift) (PR20750)
authorSanjay Patel <spatel@rotateright.com>
Mon, 13 May 2019 17:28:19 +0000 (17:28 +0000)
committerSanjay Patel <spatel@rotateright.com>
Mon, 13 May 2019 17:28:19 +0000 (17:28 +0000)
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

lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
test/Transforms/InstCombine/rotate.ll

index 31cf63869189fd2d73703ef5f2a931488c1ff1b3..f1766fd4fce79970a0aa2588880f300ec80a9fc1 100644 (file)
@@ -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;
   };
 
index 984dac1cbc1352a720837e7d29877dc90ab3b26d..a11fcd974246a141dd2b913597496d7f6d663225 100644 (file)
@@ -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