[llvm] r263945 - Implement constant folding for bitreverse

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 21 08:00:35 PDT 2016


Author: arsenm
Date: Mon Mar 21 10:00:35 2016
New Revision: 263945

URL: http://llvm.org/viewvc/llvm-project?rev=263945&view=rev
Log:
Implement constant folding for bitreverse

Modified:
    llvm/trunk/include/llvm/ADT/APInt.h
    llvm/trunk/lib/Analysis/ConstantFolding.cpp
    llvm/trunk/lib/Support/APInt.cpp
    llvm/trunk/test/Transforms/InstCombine/bitreverse-fold.ll
    llvm/trunk/unittests/ADT/APIntTest.cpp

Modified: llvm/trunk/include/llvm/ADT/APInt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=263945&r1=263944&r2=263945&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APInt.h (original)
+++ llvm/trunk/include/llvm/ADT/APInt.h Mon Mar 21 10:00:35 2016
@@ -1451,6 +1451,10 @@ public:
   /// \returns a byte-swapped representation of this APInt Value.
   APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const;
 
+  /// \returns the value with the bit representation reversed of this APInt
+  /// Value.
+  APInt LLVM_ATTRIBUTE_UNUSED_RESULT reverseBits() const;
+
   /// \brief Converts this APInt to a double value.
   double roundToDouble(bool isSigned) const;
 

Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=263945&r1=263944&r2=263945&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original)
+++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Mon Mar 21 10:00:35 2016
@@ -1286,6 +1286,7 @@ bool llvm::canConstantFoldCallTo(const F
   case Intrinsic::umul_with_overflow:
   case Intrinsic::convert_from_fp16:
   case Intrinsic::convert_to_fp16:
+  case Intrinsic::bitreverse:
   case Intrinsic::x86_sse_cvtss2si:
   case Intrinsic::x86_sse_cvtss2si64:
   case Intrinsic::x86_sse_cvttss2si:
@@ -1618,6 +1619,8 @@ static Constant *ConstantFoldScalarCall(
         return ConstantInt::get(Ty->getContext(), Op->getValue().byteSwap());
       case Intrinsic::ctpop:
         return ConstantInt::get(Ty, Op->getValue().countPopulation());
+      case Intrinsic::bitreverse:
+        return ConstantInt::get(Ty->getContext(), Op->getValue().reverseBits());
       case Intrinsic::convert_from_fp16: {
         APFloat Val(APFloat::IEEEhalf, Op->getValue());
 

Modified: llvm/trunk/lib/Support/APInt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=263945&r1=263944&r2=263945&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APInt.cpp (original)
+++ llvm/trunk/lib/Support/APInt.cpp Mon Mar 21 10:00:35 2016
@@ -787,6 +787,36 @@ APInt APInt::byteSwap() const {
   return Result;
 }
 
+APInt APInt::reverseBits() const {
+  switch (BitWidth) {
+  case 64:
+    return APInt(BitWidth, llvm::reverseBits<uint64_t>(VAL));
+  case 32:
+    return APInt(BitWidth, llvm::reverseBits<uint32_t>(VAL));
+  case 16:
+    return APInt(BitWidth, llvm::reverseBits<uint16_t>(VAL));
+  case 8:
+    return APInt(BitWidth, llvm::reverseBits<uint8_t>(VAL));
+  default:
+    break;
+  }
+
+  APInt Val(*this);
+  APInt Reversed(*this);
+  int S = BitWidth - 1;
+
+  const APInt One(BitWidth, 1);
+
+  for ((Val = Val.lshr(1)); Val != 0; (Val = Val.lshr(1))) {
+    Reversed <<= 1;
+    Reversed |= (Val & One);
+    --S;
+  }
+
+  Reversed <<= S;
+  return Reversed;
+}
+
 APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
                                             const APInt& API2) {
   APInt A = API1, B = API2;

Modified: llvm/trunk/test/Transforms/InstCombine/bitreverse-fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bitreverse-fold.ll?rev=263945&r1=263944&r2=263945&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/bitreverse-fold.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/bitreverse-fold.ll Mon Mar 21 10:00:35 2016
@@ -1,11 +1,96 @@
 ; RUN: opt < %s -instcombine -S | FileCheck %s
 
-define i32 @test1(i32 %p) {
-; CHECK-LABEL: @test1
+define i32 @identity_bitreverse_i32(i32 %p) {
+; CHECK-LABEL: @identity_bitreverse_i32(
 ; CHECK-NEXT: ret i32 %p
   %a = call i32 @llvm.bitreverse.i32(i32 %p)
   %b = call i32 @llvm.bitreverse.i32(i32 %a)
   ret i32 %b
 }
 
+; CHECK-LABEL: @identity_bitreverse_v2i32(
+; CHECK-NEXT: ret <2 x i32> %p
+define <2 x i32> @identity_bitreverse_v2i32(<2 x i32> %p) {
+  %a = call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %p)
+  %b = call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %a)
+  ret <2 x i32> %b
+}
+
+; CHECK-LABEL: @reverse_0_i32(
+; CHECK-NEXT: ret i32 0
+define i32 @reverse_0_i32() {
+  %x = call i32 @llvm.bitreverse.i32(i32 0)
+  ret i32 %x
+}
+
+; CHECK-LABEL: @reverse_1_i32(
+; CHECK-NEXT: ret i32 -2147483648
+define i32 @reverse_1_i32() {
+  %x = call i32 @llvm.bitreverse.i32(i32 1)
+  ret i32 %x
+}
+
+; CHECK-LABEL: @reverse_neg1_i32(
+; CHECK-NEXT: ret i32 -1
+define i32 @reverse_neg1_i32() {
+  %x = call i32 @llvm.bitreverse.i32(i32 -1)
+  ret i32 %x
+}
+
+; CHECK-LABEL: @reverse_false_i1(
+; CHECK-NEXT: ret i1 false
+define i1 @reverse_false_i1() {
+  %x = call i1 @llvm.bitreverse.i1(i1 false)
+  ret i1 %x
+}
+
+; CHECK-LABEL: @reverse_true_i1(
+; CHECK-NEXT: ret i1 true
+define i1 @reverse_true_i1() {
+  %x = call i1 @llvm.bitreverse.i1(i1 true)
+  ret i1 %x
+}
+
+; CHECK-LABEL: @reverse_false_v2i1(
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
+define <2 x i1> @reverse_false_v2i1() {
+  %x = call <2  x i1> @llvm.bitreverse.v2i1(<2 x i1> zeroinitializer)
+  ret <2 x i1> %x
+}
+
+; CHECK-LABEL: @reverse_true_v2i1(
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
+define <2 x i1> @reverse_true_v2i1() {
+  %x = call <2 x i1> @llvm.bitreverse.v2i1(<2 x i1> <i1 true, i1 true>)
+  ret <2 x i1> %x
+}
+
+; CHECK-LABEL: @bitreverse_920_1234_v2i32(
+; CHECK-NEXT: ret <2 x i32> <i32 432013312, i32 1260388352>
+define <2 x i32> @bitreverse_920_1234_v2i32() {
+  %x = call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> <i32 920, i32 1234>)
+  ret <2 x i32> %x
+}
+
+; CHECK-LABEL: @reverse_100_i3(
+; CHECK-NEXT: ret i3 1
+define i3 @reverse_100_i3() {
+  %x = call i3 @llvm.bitreverse.i3(i3 100)
+  ret i3 %x
+}
+
+; CHECK-LABEL: @reverse_6_3_v2i3(
+; CHECK-NEXT: ret <2 x i3> <i3 3, i3 -2>
+define <2 x i3> @reverse_6_3_v2i3() {
+  %x = call <2  x i3> @llvm.bitreverse.v2i3(<2 x i3> <i3 6, i3 3>)
+  ret <2 x i3> %x
+}
+
+declare i1 @llvm.bitreverse.i1(i1) readnone
+declare <2 x i1> @llvm.bitreverse.v2i1(<2 x i1>) readnone
+
+declare i3 @llvm.bitreverse.i3(i3) readnone
+declare <2 x i3> @llvm.bitreverse.v2i3(<2 x i3>) readnone
+
 declare i32 @llvm.bitreverse.i32(i32) readnone
+declare <2 x i32> @llvm.bitreverse.v2i32(<2 x i32>) readnone

Modified: llvm/trunk/unittests/ADT/APIntTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=263945&r1=263944&r2=263945&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APIntTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APIntTest.cpp Mon Mar 21 10:00:35 2016
@@ -1023,3 +1023,45 @@ TEST(APIntTest, SelfMoveAssignment) {
 #pragma clang diagnostic pop
 #endif
 }
+
+TEST(APIntTest, reverseBits) {
+  EXPECT_EQ(1, APInt(1, 1).reverseBits());
+  EXPECT_EQ(0, APInt(1, 0).reverseBits());
+
+  EXPECT_EQ(3, APInt(2, 3).reverseBits());
+  EXPECT_EQ(3, APInt(2, 3).reverseBits());
+
+  EXPECT_EQ(0xb, APInt(4, 0xd).reverseBits());
+  EXPECT_EQ(0xd, APInt(4, 0xb).reverseBits());
+  EXPECT_EQ(0xf, APInt(4, 0xf).reverseBits());
+
+  EXPECT_EQ(0x30, APInt(7, 0x6).reverseBits());
+  EXPECT_EQ(0x5a, APInt(7, 0x2d).reverseBits());
+
+  EXPECT_EQ(0x0f, APInt(8, 0xf0).reverseBits());
+  EXPECT_EQ(0xf0, APInt(8, 0x0f).reverseBits());
+
+  EXPECT_EQ(0x0f0f, APInt(16, 0xf0f0).reverseBits());
+  EXPECT_EQ(0xf0f0, APInt(16, 0x0f0f).reverseBits());
+
+  EXPECT_EQ(0x0f0f0f0f, APInt(32, 0xf0f0f0f0).reverseBits());
+  EXPECT_EQ(0xf0f0f0f0, APInt(32, 0x0f0f0f0f).reverseBits());
+
+  EXPECT_EQ(0x402880a0 >> 1, APInt(31, 0x05011402).reverseBits());
+
+  EXPECT_EQ(0x0f0f0f0f, APInt(32, 0xf0f0f0f0).reverseBits());
+  EXPECT_EQ(0xf0f0f0f0, APInt(32, 0x0f0f0f0f).reverseBits());
+
+  EXPECT_EQ(0x0f0f0f0f0f0f0f0f, APInt(64, 0xf0f0f0f0f0f0f0f0).reverseBits());
+  EXPECT_EQ(0xf0f0f0f0f0f0f0f0, APInt(64, 0x0f0f0f0f0f0f0f0f).reverseBits());
+
+  for (unsigned N : { 1, 8, 16, 24, 31, 32, 33,
+                      63, 64, 65, 127, 128, 257, 1024 }) {
+    for (unsigned I = 0; I < N; ++I) {
+      APInt X = APInt::getOneBitSet(N, I);
+      APInt Y = APInt::getOneBitSet(N, N - (I + 1));
+      EXPECT_EQ(Y, X.reverseBits());
+      EXPECT_EQ(X, Y.reverseBits());
+    }
+  }
+}




More information about the llvm-commits mailing list