Add runtime markers for a full-width 32x32 multiply (0x12345678 * 0x9abcdef0 = 0x242d2080) and for a wide-dividend remainder, so a 16-bit-truncated MPYS or a wrong FS1 cannot still produce the expected small results. Compute the 16x16 unsigned product in unsigned arithmetic to remove the signed-overflow annotation, and reject a regressed nuw nsw multiply in the optimized IR.
45 lines
1.8 KiB
C
45 lines
1.8 KiB
C
/* m4 mul.c -- 32-bit multiply/divide marker test.
|
|
*
|
|
* Markers (0x20 bits apart, written by mul_test):
|
|
* 018A8000 mul(6,7) == 42
|
|
* 018A8020 umul16(0xffff,0xffff) == 0xfffe0001 (16x16 MPYU path)
|
|
* 018A8040 sdiv(100,7) == 14
|
|
* 018A8060 udiv(0xfffffffe,7) == 613566756
|
|
* 018A8080 srem(100,7) == 2
|
|
* 018A80A0 urem(100,7) == 2
|
|
* 018A80C0 sdiv(-100,7) == -14
|
|
* 018A80E0 srem(-100,7) == -2
|
|
* 018A8140 mul(0x12345678,0x9ABCDEF0) == 0x242D2080 (wide 32x32 product)
|
|
* 018A8160 urem(0xfffffffe,7) == 2 (wide quotient in the remainder)
|
|
*/
|
|
#define MARK(n) (*(volatile unsigned int *)(0x018A8000u + (n)*0x20u))
|
|
|
|
int mul(int a, int b) { return a * b; }
|
|
|
|
/* A 16x16 unsigned product: both operands are masked to 16 bits, which is the
|
|
* form the target selects to MPYU. The product must be computed in unsigned
|
|
* arithmetic: 0xffff * 0xffff does not fit in signed int, so `int * int` would
|
|
* be signed overflow and the optimizer could narrow or rename the result. */
|
|
int umul16(int a, int b) {
|
|
return (int)((unsigned)(a & 0xffff) * (unsigned)(b & 0xffff));
|
|
}
|
|
|
|
int sdiv(int a, int b) { return a / b; }
|
|
unsigned udiv(unsigned a, unsigned b) { return a / b; }
|
|
int srem(int a, int b) { return a % b; }
|
|
unsigned urem(unsigned a, unsigned b) { return a % b; }
|
|
|
|
int mul_test(void) {
|
|
MARK(0) = (unsigned)mul(6, 7);
|
|
MARK(1) = (unsigned)umul16(0xffff, 0xffff);
|
|
MARK(2) = (unsigned)sdiv(100, 7);
|
|
MARK(3) = udiv(0xfffffffeu, 7u);
|
|
MARK(4) = (unsigned)srem(100, 7);
|
|
MARK(5) = urem(100u, 7u);
|
|
MARK(6) = (unsigned)sdiv(-100, 7);
|
|
MARK(7) = (unsigned)srem(-100, 7);
|
|
MARK(10) = (unsigned)mul(0x12345678, 0x9ABCDEF0);
|
|
MARK(11) = urem(0xfffffffeu, 7u);
|
|
return 0;
|
|
}
|