qsort.c: take an upstream FreeBSD change.

  r334928 | kib | 2018-06-10 10:54:44 -0700 (Sun, 10 Jun 2018) | 16 lines

  libc qsort(3): stop aliasing.

  Qsort swap code aliases the sorted array elements to ints and longs in
  order to do swap by machine words.  Unfortunately this breaks with the
  full code optimization, e.g. LTO.

  See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83201 which seems to
  reference code directly copied from libc/stdlib/qsort.c.

  PR: 228780
  Reported by:  mliska@suse.cz
  Reviewed by:  brooks
  Sponsored by: The FreeBSD Foundation
  MFC after:  2 weeks
  Differential revision:  https://reviews.freebsd.org/D15714

Test: treehugger
Change-Id: Iac608b13bbf8a2dcb48c935a7871c0d2f05bff79
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/qsort.c b/libc/upstream-freebsd/lib/libc/stdlib/qsort.c
index 1ccc518..e0db4f3 100644
--- a/libc/upstream-freebsd/lib/libc/stdlib/qsort.c
+++ b/libc/upstream-freebsd/lib/libc/stdlib/qsort.c
@@ -1,4 +1,6 @@
 /*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
  * Copyright (c) 1992, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -31,7 +33,7 @@
 static char sccsid[] = "@(#)qsort.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/libc/stdlib/qsort.c 334928 2018-06-10 17:54:44Z kib $");
 
 #include <stdlib.h>
 
@@ -41,53 +43,27 @@
 typedef int		 cmp_t(const void *, const void *);
 #endif
 static inline char	*med3(char *, char *, char *, cmp_t *, void *);
-static inline void	 swapfunc(char *, char *, size_t, int, int);
 
 #define	MIN(a, b)	((a) < (b) ? a : b)
 
 /*
  * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
  */
-#define	swapcode(TYPE, parmi, parmj, n) {		\
-	size_t i = (n) / sizeof (TYPE);			\
-	TYPE *pi = (TYPE *) (parmi);		\
-	TYPE *pj = (TYPE *) (parmj);		\
-	do { 						\
-		TYPE	t = *pi;		\
-		*pi++ = *pj;				\
-		*pj++ = t;				\
-	} while (--i > 0);				\
-}
-
-#define	SWAPINIT(TYPE, a, es) swaptype_ ## TYPE =	\
-	((char *)a - (char *)0) % sizeof(TYPE) ||	\
-	es % sizeof(TYPE) ? 2 : es == sizeof(TYPE) ? 0 : 1;
 
 static inline void
-swapfunc(char *a, char *b, size_t n, int swaptype_long, int swaptype_int)
+swapfunc(char *a, char *b, size_t es)
 {
-	if (swaptype_long <= 1)
-		swapcode(long, a, b, n)
-	else if (swaptype_int <= 1)
-		swapcode(int, a, b, n)
-	else
-		swapcode(char, a, b, n)
+	char t;
+
+	do {
+		t = *a;
+		*a++ = *b;
+		*b++ = t;
+	} while (--es > 0);
 }
 
-#define	swap(a, b)					\
-	if (swaptype_long == 0) {			\
-		long t = *(long *)(a);			\
-		*(long *)(a) = *(long *)(b);		\
-		*(long *)(b) = t;			\
-	} else if (swaptype_int == 0) {			\
-		int t = *(int *)(a);			\
-		*(int *)(a) = *(int *)(b);		\
-		*(int *)(b) = t;			\
-	} else						\
-		swapfunc(a, b, es, swaptype_long, swaptype_int)
-
 #define	vecswap(a, b, n)				\
-	if ((n) > 0) swapfunc(a, b, n, swaptype_long, swaptype_int)
+	if ((n) > 0) swapfunc(a, b, n)
 
 #ifdef I_AM_QSORT_R
 #define	CMP(t, x, y) (cmp((t), (x), (y)))
@@ -119,17 +95,16 @@
 	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
 	size_t d1, d2;
 	int cmp_result;
-	int swaptype_long, swaptype_int, swap_cnt;
+	int swap_cnt;
 
-loop:	SWAPINIT(long, a, es);
-	SWAPINIT(int, a, es);
+loop:
 	swap_cnt = 0;
 	if (n < 7) {
 		for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
 			for (pl = pm; 
 			     pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
 			     pl -= es)
-				swap(pl, pl - es);
+				swapfunc(pl, pl - es, es);
 		return;
 	}
 	pm = (char *)a + (n / 2) * es;
@@ -145,7 +120,7 @@
 		}
 		pm = med3(pl, pm, pn, cmp, thunk);
 	}
-	swap(a, pm);
+	swapfunc(a, pm, es);
 	pa = pb = (char *)a + es;
 
 	pc = pd = (char *)a + (n - 1) * es;
@@ -153,7 +128,7 @@
 		while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
 			if (cmp_result == 0) {
 				swap_cnt = 1;
-				swap(pa, pb);
+				swapfunc(pa, pb, es);
 				pa += es;
 			}
 			pb += es;
@@ -161,14 +136,14 @@
 		while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
 			if (cmp_result == 0) {
 				swap_cnt = 1;
-				swap(pc, pd);
+				swapfunc(pc, pd, es);
 				pd -= es;
 			}
 			pc -= es;
 		}
 		if (pb > pc)
 			break;
-		swap(pb, pc);
+		swapfunc(pb, pc, es);
 		swap_cnt = 1;
 		pb += es;
 		pc -= es;
@@ -178,7 +153,7 @@
 			for (pl = pm; 
 			     pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
 			     pl -= es)
-				swap(pl, pl - es);
+				swapfunc(pl, pl - es, es);
 		return;
 	}