[llvm] r347561 - [DemandedBits] Add support for funnel shifts

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 26 07:36:57 PST 2018


Author: nikic
Date: Mon Nov 26 07:36:57 2018
New Revision: 347561

URL: http://llvm.org/viewvc/llvm-project?rev=347561&view=rev
Log:
[DemandedBits] Add support for funnel shifts

Add support for funnel shifts to the DemandedBits analysis. The
demanded bits of the first two operands can be determined if the
shift amount is constant. The demanded bits of the third operand
(shift amount) can be determined if the bitwidth is a power of two.

This is basically the same functionality as implemented in D54869
and D54478, but for DemandedBits rather than InstCombine.

Differential Revision: https://reviews.llvm.org/D54876

Modified:
    llvm/trunk/lib/Analysis/DemandedBits.cpp
    llvm/trunk/test/Analysis/DemandedBits/intrinsics.ll

Modified: llvm/trunk/lib/Analysis/DemandedBits.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/DemandedBits.cpp?rev=347561&r1=347560&r2=347561&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/DemandedBits.cpp (original)
+++ llvm/trunk/lib/Analysis/DemandedBits.cpp Mon Nov 26 07:36:57 2018
@@ -142,6 +142,27 @@ void DemandedBits::determineLiveOperandB
                  std::min(BitWidth, Known.countMaxTrailingZeros()+1));
         }
         break;
+      case Intrinsic::fshl:
+      case Intrinsic::fshr:
+        if (OperandNo == 2) {
+          // Shift amount is modulo the bitwidth. For powers of two we have
+          // SA % BW == SA & (BW - 1).
+          if (isPowerOf2_32(BitWidth))
+            AB = BitWidth - 1;
+        } else if (auto *SA = dyn_cast<ConstantInt>(II->getOperand(2))) {
+          // TODO: Support vectors.
+          // Normalize to funnel shift left. APInt shifts of BitWidth are well-
+          // defined, so no need to special-case zero shifts here.
+          uint64_t ShiftAmt = SA->getValue().urem(BitWidth);
+          if (II->getIntrinsicID() == Intrinsic::fshr)
+            ShiftAmt = BitWidth - ShiftAmt;
+
+          if (OperandNo == 0)
+            AB = AOut.lshr(ShiftAmt);
+          else if (OperandNo == 1)
+            AB = AOut.shl(BitWidth - ShiftAmt);
+        }
+        break;
       }
     break;
   case Instruction::Add:

Modified: llvm/trunk/test/Analysis/DemandedBits/intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/DemandedBits/intrinsics.ll?rev=347561&r1=347560&r2=347561&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/DemandedBits/intrinsics.ll (original)
+++ llvm/trunk/test/Analysis/DemandedBits/intrinsics.ll Mon Nov 26 07:36:57 2018
@@ -23,3 +23,82 @@ define i8 @test_bitreverse(i32 %x) {
 }
 declare i32 @llvm.bitreverse.i32(i32)
 
+; Funnel shifts
+declare i32 @llvm.fshl.i32(i32, i32, i32)
+declare i33 @llvm.fshr.i33(i33, i33, i33)
+
+; CHECK-DAG: DemandedBits: 0xff for   %x2 = or i32 %x, 1
+; CHECK-DAG: DemandedBits: 0xff000000 for   %y2 = or i32 %y, 1
+; CHECK-DAG: DemandedBits: 0xffff for   %z = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 8)
+; CHECK-DAG: DemandedBits: 0xffffffff for   %r = and i32 %z, 65535
+define i32 @test_fshl(i32 %x, i32 %y) {
+  %x2 = or i32 %x, 1
+  %y2 = or i32 %y, 1
+  %z = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 8)
+  %r = and i32 %z, 65535
+  ret i32 %r
+}
+
+; CHECK-DAG: DemandedBits: 0xff for   %x2 = or i33 %x, 1
+; CHECK-DAG: DemandedBits: 0x1fe000000 for   %y2 = or i33 %y, 1
+; CHECK-DAG: DemandedBits: 0xffff for   %z = call i33 @llvm.fshr.i33(i33 %x2, i33 %y2, i33 25)
+; CHECK-DAG: DemandedBits: 0x1ffffffff for   %r = and i33 %z, 65535
+define i33 @test_fshr(i33 %x, i33 %y) {
+  %x2 = or i33 %x, 1
+  %y2 = or i33 %y, 1
+  %z = call i33 @llvm.fshr.i33(i33 %x2, i33 %y2, i33 25)
+  %r = and i33 %z, 65535
+  ret i33 %r
+}
+
+; CHECK-DAG: DemandedBits: 0xffff for   %x2 = or i32 %x, 1
+; CHECK-DAG: DemandedBits: 0x0 for   %y2 = or i32 %y, 1
+; CHECK-DAG: DemandedBits: 0xffff for   %z = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 0)
+; CHECK-DAG: DemandedBits: 0xffffffff for   %r = and i32 %z, 65535
+define i32 @test_fshl_zero_shift(i32 %x, i32 %y) {
+  %x2 = or i32 %x, 1
+  %y2 = or i32 %y, 1
+  %z = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 0)
+  %r = and i32 %z, 65535
+  ret i32 %r
+}
+
+; CHECK-DAG: DemandedBits: 0x0 for   %x2 = or i33 %x, 1
+; CHECK-DAG: DemandedBits: 0xffff for   %y2 = or i33 %y, 1
+; CHECK-DAG: DemandedBits: 0xffff for   %z = call i33 @llvm.fshr.i33(i33 %x2, i33 %y2, i33 33)
+; CHECK-DAG: DemandedBits: 0x1ffffffff for   %r = and i33 %z, 65535
+define i33 @test_fshr_full_shift(i33 %x, i33 %y) {
+  %x2 = or i33 %x, 1
+  %y2 = or i33 %y, 1
+  %z = call i33 @llvm.fshr.i33(i33 %x2, i33 %y2, i33 33)
+  %r = and i33 %z, 65535
+  ret i33 %r
+}
+
+; CHECK-DAG: DemandedBits: 0xffffffff for   %x2 = or i32 %x, 1
+; CHECK-DAG: DemandedBits: 0xffffffff for   %y2 = or i32 %y, 1
+; CHECK-DAG: DemandedBits: 0x1f for   %z2 = or i32 %z, 1
+; CHECK-DAG: DemandedBits: 0xffff for   %f = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 %z2)
+; CHECK-DAG: DemandedBits: 0xffffffff for   %r = and i32 %f, 65535
+define i32 @test_fshl_pow2_bitwidth(i32 %x, i32 %y, i32 %z) {
+  %x2 = or i32 %x, 1
+  %y2 = or i32 %y, 1
+  %z2 = or i32 %z, 1
+  %f = call i32 @llvm.fshl.i32(i32 %x2, i32 %y2, i32 %z2)
+  %r = and i32 %f, 65535
+  ret i32 %r
+}
+
+; CHECK-DAG: DemandedBits: 0x1ffffffff for   %x2 = or i33 %x, 1
+; CHECK-DAG: DemandedBits: 0x1ffffffff for   %y2 = or i33 %y, 1
+; CHECK-DAG: DemandedBits: 0x1ffffffff for   %z2 = or i33 %z, 1
+; CHECK-DAG: DemandedBits: 0xffff for   %f = call i33 @llvm.fshr.i33(i33 %x2, i33 %y2, i33 %z2)
+; CHECK-DAG: DemandedBits: 0x1ffffffff for   %r = and i33 %f, 65535
+define i33 @test_fshr_non_pow2_bitwidth(i33 %x, i33 %y, i33 %z) {
+  %x2 = or i33 %x, 1
+  %y2 = or i33 %y, 1
+  %z2 = or i33 %z, 1
+  %f = call i33 @llvm.fshr.i33(i33 %x2, i33 %y2, i33 %z2)
+  %r = and i33 %f, 65535
+  ret i33 %r
+}




More information about the llvm-commits mailing list