1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

Implement constant folding for bitreverse

llvm-svn: 263945
This commit is contained in:
Matt Arsenault 2016-03-21 15:00:35 +00:00
parent 8f3f76a980
commit f2fb55d608
5 changed files with 166 additions and 2 deletions

View File

@ -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;

View File

@ -1286,6 +1286,7 @@ bool llvm::canConstantFoldCallTo(const Function *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(StringRef Name, unsigned IntrinsicID,
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());

View File

@ -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;

View File

@ -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

View File

@ -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());
}
}
}