The signed version of our "magic number" computation for the integer approximation

of a constant had a minor typo introduced when copying it from the book, which
caused it to favor negative approximations over positive approximations in many
cases. Positive approximations require fewer operations beyond the multiplication.

In the case of division by 3, we still generate code that is a single instruction
larger than GCC's code.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126097 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Cameron Zwarich
2011-02-21 00:22:02 +00:00
parent 0b85d07d46
commit 8d7285d0e5
4 changed files with 24 additions and 8 deletions

View File

@@ -1505,7 +1505,7 @@ APInt::ms APInt::magic() const {
r2 = r2 - ad; r2 = r2 - ad;
} }
delta = ad - r2; delta = ad - r2;
} while (q1.ule(delta) || (q1 == delta && r1 == 0)); } while (q1.ult(delta) || (q1 == delta && r1 == 0));
mag.m = q2 + 1; mag.m = q2 + 1;
if (d.isNegative()) mag.m = -mag.m; // resulting magic number if (d.isNegative()) mag.m = -mag.m; // resulting magic number

View File

@@ -1888,12 +1888,10 @@ Compiles to: $clang t.c -S -o - -O3 -mkernel -fomit-frame-pointer
_t: ## @t _t: ## @t
movslq %edi, %rax movslq %edi, %rax
imulq $-1431655765, %rax, %rcx ## imm = 0xFFFFFFFFAAAAAAAB imulq $1431655766, %rax, %rax ## imm = 0x55555556
shrq $32, %rcx movq %rax, %rcx
addl %ecx, %eax shrq $63, %rcx
movl %eax, %ecx shrq $32, %rax
shrl $31, %ecx
shrl %eax
addl %ecx, %eax addl %ecx, %eax
movsbl %al, %eax movsbl %al, %eax
ret ret

View File

@@ -40,7 +40,7 @@ entry:
%div = sdiv i16 %x, 33 ; <i32> [#uses=1] %div = sdiv i16 %x, 33 ; <i32> [#uses=1]
ret i16 %div ret i16 %div
; CHECK: test4: ; CHECK: test4:
; CHECK: imull $-1985, %ecx, %ecx ; CHECK: imull $1986, %eax, %eax
} }
define i32 @test5(i32 %A) nounwind { define i32 @test5(i32 %A) nounwind {

View File

@@ -332,6 +332,24 @@ TEST(APIntTest, Log2) {
EXPECT_EQ(APInt(15, 9).exactLogBase2(), -1); EXPECT_EQ(APInt(15, 9).exactLogBase2(), -1);
} }
TEST(APIntTest, magic) {
EXPECT_EQ(APInt(32, 3).magic().m, APInt(32, "55555556", 16));
EXPECT_EQ(APInt(32, 3).magic().s, 0U);
EXPECT_EQ(APInt(32, 5).magic().m, APInt(32, "66666667", 16));
EXPECT_EQ(APInt(32, 5).magic().s, 1U);
EXPECT_EQ(APInt(32, 7).magic().m, APInt(32, "92492493", 16));
EXPECT_EQ(APInt(32, 7).magic().s, 2U);
}
TEST(APIntTest, magicu) {
EXPECT_EQ(APInt(32, 3).magicu().m, APInt(32, "AAAAAAAB", 16));
EXPECT_EQ(APInt(32, 3).magicu().s, 1U);
EXPECT_EQ(APInt(32, 5).magicu().m, APInt(32, "CCCCCCCD", 16));
EXPECT_EQ(APInt(32, 5).magicu().s, 2U);
EXPECT_EQ(APInt(32, 7).magicu().m, APInt(32, "24924925", 16));
EXPECT_EQ(APInt(32, 7).magicu().s, 3U);
}
#ifdef GTEST_HAS_DEATH_TEST #ifdef GTEST_HAS_DEATH_TEST
#ifndef NDEBUG #ifndef NDEBUG
TEST(APIntTest, StringDeath) { TEST(APIntTest, StringDeath) {