xref: /openbmc/linux/arch/mips/include/asm/unroll.h (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
16baaeadaSPaul Burton /* SPDX-License-Identifier: GPL-2.0-only */
26baaeadaSPaul Burton #ifndef __ASM_UNROLL_H__
36baaeadaSPaul Burton #define __ASM_UNROLL_H__
46baaeadaSPaul Burton 
56baaeadaSPaul Burton /*
66baaeadaSPaul Burton  * Explicitly unroll a loop, for use in cases where doing so is performance
76baaeadaSPaul Burton  * critical.
86baaeadaSPaul Burton  *
96baaeadaSPaul Burton  * Ideally we'd rely upon the compiler to provide this but there's no commonly
106baaeadaSPaul Burton  * available means to do so. For example GCC's "#pragma GCC unroll"
116baaeadaSPaul Burton  * functionality would be ideal but is only available from GCC 8 onwards. Using
126baaeadaSPaul Burton  * -funroll-loops is an option but GCC tends to make poor choices when
136baaeadaSPaul Burton  * compiling our string functions. -funroll-all-loops leads to massive code
146baaeadaSPaul Burton  * bloat, even if only applied to the string functions.
156baaeadaSPaul Burton  */
166baaeadaSPaul Burton #define unroll(times, fn, ...) do {				\
176baaeadaSPaul Burton 	extern void bad_unroll(void)				\
186baaeadaSPaul Burton 		__compiletime_error("Unsupported unroll");	\
196baaeadaSPaul Burton 								\
206baaeadaSPaul Burton 	/*							\
216baaeadaSPaul Burton 	 * We can't unroll if the number of iterations isn't	\
226ec4476aSLinus Torvalds 	 * compile-time constant. Unfortunately clang versions	\
236ec4476aSLinus Torvalds 	 * up until 8.0 tend to miss obvious constants & cause	\
246baaeadaSPaul Burton 	 * this check to fail, even though they go on to	\
256baaeadaSPaul Burton 	 * generate reasonable code for the switch statement,	\
266baaeadaSPaul Burton 	 * so we skip the sanity check for those compilers.	\
276baaeadaSPaul Burton 	 */							\
289321f1aaSNathan Chancellor 	BUILD_BUG_ON(!__builtin_constant_p(times));		\
296baaeadaSPaul Burton 								\
306baaeadaSPaul Burton 	switch (times) {					\
31*df561f66SGustavo A. R. Silva 	case 32: fn(__VA_ARGS__); fallthrough;			\
32*df561f66SGustavo A. R. Silva 	case 31: fn(__VA_ARGS__); fallthrough;			\
33*df561f66SGustavo A. R. Silva 	case 30: fn(__VA_ARGS__); fallthrough;			\
34*df561f66SGustavo A. R. Silva 	case 29: fn(__VA_ARGS__); fallthrough;			\
35*df561f66SGustavo A. R. Silva 	case 28: fn(__VA_ARGS__); fallthrough;			\
36*df561f66SGustavo A. R. Silva 	case 27: fn(__VA_ARGS__); fallthrough;			\
37*df561f66SGustavo A. R. Silva 	case 26: fn(__VA_ARGS__); fallthrough;			\
38*df561f66SGustavo A. R. Silva 	case 25: fn(__VA_ARGS__); fallthrough;			\
39*df561f66SGustavo A. R. Silva 	case 24: fn(__VA_ARGS__); fallthrough;			\
40*df561f66SGustavo A. R. Silva 	case 23: fn(__VA_ARGS__); fallthrough;			\
41*df561f66SGustavo A. R. Silva 	case 22: fn(__VA_ARGS__); fallthrough;			\
42*df561f66SGustavo A. R. Silva 	case 21: fn(__VA_ARGS__); fallthrough;			\
43*df561f66SGustavo A. R. Silva 	case 20: fn(__VA_ARGS__); fallthrough;			\
44*df561f66SGustavo A. R. Silva 	case 19: fn(__VA_ARGS__); fallthrough;			\
45*df561f66SGustavo A. R. Silva 	case 18: fn(__VA_ARGS__); fallthrough;			\
46*df561f66SGustavo A. R. Silva 	case 17: fn(__VA_ARGS__); fallthrough;			\
47*df561f66SGustavo A. R. Silva 	case 16: fn(__VA_ARGS__); fallthrough;			\
48*df561f66SGustavo A. R. Silva 	case 15: fn(__VA_ARGS__); fallthrough;			\
49*df561f66SGustavo A. R. Silva 	case 14: fn(__VA_ARGS__); fallthrough;			\
50*df561f66SGustavo A. R. Silva 	case 13: fn(__VA_ARGS__); fallthrough;			\
51*df561f66SGustavo A. R. Silva 	case 12: fn(__VA_ARGS__); fallthrough;			\
52*df561f66SGustavo A. R. Silva 	case 11: fn(__VA_ARGS__); fallthrough;			\
53*df561f66SGustavo A. R. Silva 	case 10: fn(__VA_ARGS__); fallthrough;			\
54*df561f66SGustavo A. R. Silva 	case 9: fn(__VA_ARGS__); fallthrough;			\
55*df561f66SGustavo A. R. Silva 	case 8: fn(__VA_ARGS__); fallthrough;			\
56*df561f66SGustavo A. R. Silva 	case 7: fn(__VA_ARGS__); fallthrough;			\
57*df561f66SGustavo A. R. Silva 	case 6: fn(__VA_ARGS__); fallthrough;			\
58*df561f66SGustavo A. R. Silva 	case 5: fn(__VA_ARGS__); fallthrough;			\
59*df561f66SGustavo A. R. Silva 	case 4: fn(__VA_ARGS__); fallthrough;			\
60*df561f66SGustavo A. R. Silva 	case 3: fn(__VA_ARGS__); fallthrough;			\
61*df561f66SGustavo A. R. Silva 	case 2: fn(__VA_ARGS__); fallthrough;			\
62*df561f66SGustavo A. R. Silva 	case 1: fn(__VA_ARGS__); fallthrough;			\
636baaeadaSPaul Burton 	case 0: break;						\
646baaeadaSPaul Burton 								\
656baaeadaSPaul Burton 	default:						\
666baaeadaSPaul Burton 		/*						\
676baaeadaSPaul Burton 		 * Either the iteration count is unreasonable	\
686baaeadaSPaul Burton 		 * or we need to add more cases above.		\
696baaeadaSPaul Burton 		 */						\
706baaeadaSPaul Burton 		bad_unroll();					\
716baaeadaSPaul Burton 		break;						\
726baaeadaSPaul Burton 	}							\
736baaeadaSPaul Burton } while (0)
746baaeadaSPaul Burton 
756baaeadaSPaul Burton #endif /* __ASM_UNROLL_H__ */
76