host-utils: Use __int128_t for mul[us]64
Replace some x86_64 specific inline assembly with something that all 64-bit hosts ought to optimize well. At worst this becomes a call to the gcc __multi3 routine, which is no worse than our implementation in util/host-utils.c. With gcc 4.7, we get identical code generation for x86_64. We now get native multiplication on ia64 and s390x hosts. With minor improvements to gcc we can get it for ppc64 as well. Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
		
							parent
							
								
									be96bd3fbf
								
							
						
					
					
						commit
						f540166b7d
					
				| 
						 | 
					@ -3150,6 +3150,22 @@ if compile_prog "" "" ; then
 | 
				
			||||||
    cpuid_h=yes
 | 
					    cpuid_h=yes
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					########################################
 | 
				
			||||||
 | 
					# check if __[u]int128_t is usable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int128=no
 | 
				
			||||||
 | 
					cat > $TMPC << EOF
 | 
				
			||||||
 | 
					__int128_t a;
 | 
				
			||||||
 | 
					__uint128_t b;
 | 
				
			||||||
 | 
					int main (void) {
 | 
				
			||||||
 | 
					  a = a + b;
 | 
				
			||||||
 | 
					  b = a * b;
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					if compile_prog "" "" ; then
 | 
				
			||||||
 | 
					    int128=yes
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##########################################
 | 
					##########################################
 | 
				
			||||||
# End of CC checks
 | 
					# End of CC checks
 | 
				
			||||||
| 
						 | 
					@ -3692,6 +3708,10 @@ if test "$cpuid_h" = "yes" ; then
 | 
				
			||||||
  echo "CONFIG_CPUID_H=y" >> $config_host_mak
 | 
					  echo "CONFIG_CPUID_H=y" >> $config_host_mak
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if test "$int128" = "yes" ; then
 | 
				
			||||||
 | 
					  echo "CONFIG_INT128=y" >> $config_host_mak
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if test "$glusterfs" = "yes" ; then
 | 
					if test "$glusterfs" = "yes" ; then
 | 
				
			||||||
  echo "CONFIG_GLUSTERFS=y" >> $config_host_mak
 | 
					  echo "CONFIG_GLUSTERFS=y" >> $config_host_mak
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,22 +28,21 @@
 | 
				
			||||||
#include "qemu/compiler.h"   /* QEMU_GNUC_PREREQ */
 | 
					#include "qemu/compiler.h"   /* QEMU_GNUC_PREREQ */
 | 
				
			||||||
#include <limits.h>
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__x86_64__)
 | 
					#ifdef CONFIG_INT128
 | 
				
			||||||
#define __HAVE_FAST_MULU64__
 | 
					 | 
				
			||||||
static inline void mulu64(uint64_t *plow, uint64_t *phigh,
 | 
					static inline void mulu64(uint64_t *plow, uint64_t *phigh,
 | 
				
			||||||
                          uint64_t a, uint64_t b)
 | 
					                          uint64_t a, uint64_t b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    __asm__ ("mul %0\n\t"
 | 
					    __uint128_t r = (__uint128_t)a * b;
 | 
				
			||||||
             : "=d" (*phigh), "=a" (*plow)
 | 
					    *plow = r;
 | 
				
			||||||
             : "a" (a), "0" (b));
 | 
					    *phigh = r >> 64;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#define __HAVE_FAST_MULS64__
 | 
					
 | 
				
			||||||
static inline void muls64(uint64_t *plow, uint64_t *phigh,
 | 
					static inline void muls64(uint64_t *plow, uint64_t *phigh,
 | 
				
			||||||
                          int64_t a, int64_t b)
 | 
					                          int64_t a, int64_t b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    __asm__ ("imul %0\n\t"
 | 
					    __int128_t r = (__int128_t)a * b;
 | 
				
			||||||
             : "=d" (*phigh), "=a" (*plow)
 | 
					    *plow = r;
 | 
				
			||||||
             : "a" (a), "0" (b));
 | 
					    *phigh = r >> 64;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
 | 
					void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@
 | 
				
			||||||
//#define DEBUG_MULDIV
 | 
					//#define DEBUG_MULDIV
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Long integer helpers */
 | 
					/* Long integer helpers */
 | 
				
			||||||
#if !defined(__x86_64__)
 | 
					#ifndef CONFIG_INT128
 | 
				
			||||||
static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
 | 
					static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    *plow += a;
 | 
					    *plow += a;
 | 
				
			||||||
| 
						 | 
					@ -102,4 +102,4 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
 | 
				
			||||||
           a, b, *phigh, *plow);
 | 
					           a, b, *phigh, *plow);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* !defined(__x86_64__) */
 | 
					#endif /* !CONFIG_INT128 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue