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