__builtin_constant_p for trivial operations
Marc Glisse
marc.glisse at inria.fr
Sat Feb 19 15:09:00 CET 2011
Hello,
would something like the attached ugliness be acceptable? (don't take it
as a real patch, it wasn't properly tested and is incomplete)
The goal is that, if I have a C++ mpz_class variable z, z*=-1 and z/2 get
translated to mpz_neg and mpz_tdiv_q_2exp instead of mpz_mul_si and
mpz_tdiv_q_ui. With zero runtime penalty.
Using macros is ugly, but using inline functions is less convenient than
for mpz_abs because I need a way to refer to the real function (it would
still be doable of course).
--
Marc Glisse
-------------- next part --------------
--- /usr/include/gmp-x86_64.h 2010-01-09 08:13:00.000000000 +0100
+++ i/gmp.h 2011-02-19 12:15:18.149446310 +0100
@@ -695,14 +695,14 @@
#define mpz_add __gmpz_add
__GMP_DECLSPEC void mpz_add __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
-#define mpz_add_ui __gmpz_add_ui
-__GMP_DECLSPEC void mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+#define _mpz_add_ui __gmpz_add_ui
+__GMP_DECLSPEC void _mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
#define mpz_addmul __gmpz_addmul
__GMP_DECLSPEC void mpz_addmul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
-#define mpz_addmul_ui __gmpz_addmul_ui
-__GMP_DECLSPEC void mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+#define _mpz_addmul_ui __gmpz_addmul_ui
+__GMP_DECLSPEC void _mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
#define mpz_and __gmpz_and
__GMP_DECLSPEC void mpz_and __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
@@ -985,11 +985,11 @@
#define mpz_mul_2exp __gmpz_mul_2exp
__GMP_DECLSPEC void mpz_mul_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
-#define mpz_mul_si __gmpz_mul_si
-__GMP_DECLSPEC void mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, long int));
+#define _mpz_mul_si __gmpz_mul_si
+__GMP_DECLSPEC void _mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, long int));
-#define mpz_mul_ui __gmpz_mul_ui
-__GMP_DECLSPEC void mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+#define _mpz_mul_ui __gmpz_mul_ui
+__GMP_DECLSPEC void _mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
#define mpz_neg __gmpz_neg
#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg)
@@ -1061,8 +1061,8 @@
#define mpz_scan1 __gmpz_scan1
__GMP_DECLSPEC unsigned long int mpz_scan1 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE;
-#define mpz_set __gmpz_set
-__GMP_DECLSPEC void mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr));
+#define _mpz_set __gmpz_set
+__GMP_DECLSPEC void _mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr));
#define mpz_set_d __gmpz_set_d
__GMP_DECLSPEC void mpz_set_d __GMP_PROTO ((mpz_ptr, double));
@@ -1081,8 +1081,8 @@
#define mpz_set_str __gmpz_set_str
__GMP_DECLSPEC int mpz_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int));
-#define mpz_set_ui __gmpz_set_ui
-__GMP_DECLSPEC void mpz_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int));
+#define _mpz_set_ui __gmpz_set_ui
+__GMP_DECLSPEC void _mpz_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int));
#define mpz_setbit __gmpz_setbit
__GMP_DECLSPEC void mpz_setbit __GMP_PROTO ((mpz_ptr, unsigned long int));
@@ -1104,8 +1104,8 @@
#define mpz_sub __gmpz_sub
__GMP_DECLSPEC void mpz_sub __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
-#define mpz_sub_ui __gmpz_sub_ui
-__GMP_DECLSPEC void mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+#define _mpz_sub_ui __gmpz_sub_ui
+__GMP_DECLSPEC void _mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
#define mpz_ui_sub __gmpz_ui_sub
__GMP_DECLSPEC void mpz_ui_sub __GMP_PROTO ((mpz_ptr, unsigned long int, mpz_srcptr));
@@ -1113,8 +1113,8 @@
#define mpz_submul __gmpz_submul
__GMP_DECLSPEC void mpz_submul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
-#define mpz_submul_ui __gmpz_submul_ui
-__GMP_DECLSPEC void mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+#define _mpz_submul_ui __gmpz_submul_ui
+__GMP_DECLSPEC void _mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
#define mpz_swap __gmpz_swap
__GMP_DECLSPEC void mpz_swap __GMP_PROTO ((mpz_ptr, mpz_ptr)) __GMP_NOTHROW;
@@ -1128,8 +1128,8 @@
#define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp
__GMP_DECLSPEC void mpz_tdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
-#define mpz_tdiv_q_ui __gmpz_tdiv_q_ui
-__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+#define _mpz_tdiv_q_ui __gmpz_tdiv_q_ui
+__GMP_DECLSPEC unsigned long int _mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
#define mpz_tdiv_qr __gmpz_tdiv_qr
__GMP_DECLSPEC void mpz_tdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
@@ -1236,8 +1236,8 @@
__GMP_DECLSPEC size_t mpq_out_str __GMP_PROTO ((FILE *, int, mpq_srcptr));
#endif
-#define mpq_set __gmpq_set
-__GMP_DECLSPEC void mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr));
+#define _mpq_set __gmpq_set
+__GMP_DECLSPEC void _mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr));
#define mpq_set_d __gmpq_set_d
__GMP_DECLSPEC void mpq_set_d __GMP_PROTO ((mpq_ptr, double));
@@ -1410,8 +1410,8 @@
#define mpf_reldiff __gmpf_reldiff
__GMP_DECLSPEC void mpf_reldiff __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
-#define mpf_set __gmpf_set
-__GMP_DECLSPEC void mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr));
+#define _mpf_set __gmpf_set
+__GMP_DECLSPEC void _mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr));
#define mpf_set_d __gmpf_set_d
__GMP_DECLSPEC void mpf_set_d __GMP_PROTO ((mpf_ptr, double));
@@ -1633,7 +1633,7 @@
mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u)
{
if (__gmp_w != __gmp_u)
- mpz_set (__gmp_w, __gmp_u);
+ _mpz_set (__gmp_w, __gmp_u);
__gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size);
}
#endif
@@ -1731,7 +1731,7 @@
mpz_neg (mpz_ptr __gmp_w, mpz_srcptr __gmp_u)
{
if (__gmp_w != __gmp_u)
- mpz_set (__gmp_w, __gmp_u);
+ _mpz_set (__gmp_w, __gmp_u);
__gmp_w->_mp_size = - __gmp_w->_mp_size;
}
#endif
@@ -1802,7 +1802,7 @@
mpq_abs (mpq_ptr __gmp_w, mpq_srcptr __gmp_u)
{
if (__gmp_w != __gmp_u)
- mpq_set (__gmp_w, __gmp_u);
+ _mpq_set (__gmp_w, __gmp_u);
__gmp_w->_mp_num._mp_size = __GMP_ABS (__gmp_w->_mp_num._mp_size);
}
#endif
@@ -1812,7 +1812,7 @@
mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u)
{
if (__gmp_w != __gmp_u)
- mpq_set (__gmp_w, __gmp_u);
+ _mpq_set (__gmp_w, __gmp_u);
__gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size;
}
#endif
@@ -2142,8 +2142,64 @@
#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0)
#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0)
-/* When using GCC, optimize certain common comparisons. */
+/* When using GCC, optimize certain common operations. */
#if defined (__GNUC__) && __GNUC__ >= 2
+#define mpz_set(Zd,Zs) \
+ ((__builtin_constant_p ((Zd) == (Zs)) && (Zd) == (Zs)) \
+ ?(void)0:_mpz_set(Zd,Zs))
+#define mpq_set(Zd,Zs) \
+ ((__builtin_constant_p ((Zd) == (Zs)) && (Zd) == (Zs)) \
+ ?(void)0:_mpq_set(Zd,Zs))
+#define mpf_set(Zd,Zs) \
+ ((__builtin_constant_p ((Zd) == (Zs)) && (Zd) == (Zs)) \
+ ?(void)0:_mpf_set(Zd,Zs))
+#define mpz_add_ui(Zd,Zs,UI) \
+ (__builtin_constant_p (UI) && (UI) == 0 \
+ ? mpz_set(Zd,Zs) : _mpz_add_ui (Zd,Zs,UI))
+#define mpz_mul_ui(Zd,Zs,UI) \
+ (__builtin_constant_p (UI) && (UI) == 0 \
+ ? (void)((Zd)->_mp_size = 0) : \
+ __builtin_constant_p (UI) && (UI) == 1 \
+ ? mpz_set(Zd,Zs) : \
+ __builtin_constant_p (UI) && (UI) == 2 \
+ ? mpz_mul_2exp(Zd,Zs,1) : \
+ __builtin_constant_p (UI) && (UI) == 4 \
+ ? mpz_mul_2exp(Zd,Zs,2) : \
+ __builtin_constant_p (UI) && (UI) == 8 \
+ ? mpz_mul_2exp(Zd,Zs,3) : \
+ _mpz_mul_ui (Zd,Zs,UI))
+#define mpz_tdiv_q_ui(Zd,Zs,UI) \
+ (__builtin_constant_p (UI) && (UI) == 1 \
+ ? mpz_set(Zd,Zs) : \
+ __builtin_constant_p (UI) && (UI) == 2 \
+ ? mpz_tdiv_q_2exp(Zd,Zs,1) : \
+ __builtin_constant_p (UI) && (UI) == 4 \
+ ? mpz_tdiv_q_2exp(Zd,Zs,2) : \
+ __builtin_constant_p (UI) && (UI) == 8 \
+ ? mpz_tdiv_q_2exp(Zd,Zs,3) : \
+ _mpz_mul_ui (Zd,Zs,UI))
+#define mpz_mul_si(Zd,Zs,UI) \
+ (__builtin_constant_p (UI) \
+ ? mpz_mul_ui(Zd,Zs,(UI>=0)?(UI):-(UI)),((UI)>=0?(void)0:mpz_neg(Zd,Zd)) : \
+ _mpz_mul_si (Zd,Zs,UI))
+#define mpz_addmul_ui(Zd,Zs,UI) \
+ (__builtin_constant_p (UI) && (UI) == 0 \
+ ? mpz_set(Zd,Zs) : \
+ __builtin_constant_p (UI) && (UI) == 1 \
+ ? mpz_add(Zd,Zd,Zs) : \
+ _mpz_addmul_ui (Zd,Zs,UI))
+#define mpz_sub_ui(Zd,Zs,UI) \
+ (__builtin_constant_p (UI) && (UI) == 0 \
+ ? mpz_set(Zd,Zs) : _mpz_sub_ui (Zd,Zs,UI))
+#define mpz_submul_ui(Zd,Zs,UI) \
+ (__builtin_constant_p (UI) && (UI) == 0 \
+ ? mpz_set(Zd,Zs) : \
+ __builtin_constant_p (UI) && (UI) == 1 \
+ ? mpz_sub(Zd,Zd,Zs) : \
+ _mpz_submul_ui (Zd,Zs,UI))
+#define mpz_set_ui(Z,UI) \
+ (__builtin_constant_p (UI) && (UI) == 0 \
+ ? (void)((Z)->_mp_size = 0) : _mpz_set_ui (Z,UI))
#define mpz_cmp_ui(Z,UI) \
(__builtin_constant_p (UI) && (UI) == 0 \
? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI))
@@ -2160,6 +2216,16 @@
? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \
: _mpq_cmp_si (q, n, d))
#else
+#define mpz_set(Zd,Zs) _mpz_set(Zd,Zs)
+#define mpq_set(Zd,Zs) _mpq_set(Zd,Zs)
+#define mpf_set(Zd,Zs) _mpf_set(Zd,Zs)
+#define mpz_set_ui(Z,UI) _mpz_set_ui (Z,UI)
+#define mpz_add_ui(Zd,Zs,UI) _mpz_add_ui (Zd,Zs,UI)
+#define mpz_sub_ui(Zd,Zs,UI) _mpz_sub_ui (Zd,Zs,UI)
+#define mpz_addmul_ui(Zd,Zs,UI) _mpz_addmul_ui (Zd,Zs,UI)
+#define mpz_submul_ui(Zd,Zs,UI) _mpz_addmul_ui (Zd,Zs,UI)
+#define mpz_tdiv_q_ui(Zd,Zs,UI) _mpz_tdiv_q_ui (Zd,Zs,UI)
+#define mpz_mul_ui(Zd,Zs,UI) _mpz_mul_ui (Zd,Zs,UI)
#define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI)
#define mpz_cmp_si(Z,UI) _mpz_cmp_si (Z,UI)
#define mpq_cmp_ui(Q,NUI,DUI) _mpq_cmp_ui (Q,NUI,DUI)
More information about the gmp-discuss
mailing list