__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