From 25781e329b51ca84e5fd697705cb0377af64f90b Mon Sep 17 00:00:00 2001
From: Clifford Wolf <clifford@clifford.at>
Date: Thu, 9 Apr 2015 13:20:19 +0200
Subject: Fixed const2big performance bug

---
 kernel/calc.cc | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

(limited to 'kernel')

diff --git a/kernel/calc.cc b/kernel/calc.cc
index aa3e8b919..99980e92d 100644
--- a/kernel/calc.cc
+++ b/kernel/calc.cc
@@ -41,21 +41,28 @@ static void extend_u0(RTLIL::Const &arg, int width, bool is_signed)
 
 static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos)
 {
-	BigInteger result = 0, this_bit = 1;
-	for (size_t i = 0; i < val.bits.size(); i++) {
-		if (val.bits[i] == RTLIL::State::S1) {
-			if (as_signed && i+1 == val.bits.size())
-				result -= this_bit;
-			else
-				result += this_bit;
-		}
-		else if (val.bits[i] != RTLIL::State::S0) {
-			if (undef_bit_pos < 0)
-				undef_bit_pos = i;
-		}
-		this_bit *= 2;
+	BigUnsigned mag;
+
+	BigInteger::Sign sign = BigInteger::positive;
+	State inv_sign_bit = RTLIL::State::S1;
+	size_t num_bits = val.bits.size();
+
+	if (as_signed && num_bits && val.bits[num_bits-1] == RTLIL::State::S1) {
+		inv_sign_bit = RTLIL::State::S0;
+		sign = BigInteger::negative;
+		num_bits--;
 	}
-	return result;
+
+	for (size_t i = 0; i < num_bits; i++)
+		if (val.bits[i] == RTLIL::State::S0 || val.bits[i] == RTLIL::State::S1)
+			mag.setBit(i, val.bits[i] == inv_sign_bit);
+		else if (undef_bit_pos < 0)
+			undef_bit_pos = i;
+
+	if (sign == BigInteger::negative)
+		mag += 1;
+
+	return BigInteger(mag, sign);
 }
 
 static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_bit_pos)
-- 
cgit v1.2.3