This commit is contained in:
244
test/val/pr2951.c
Normal file
244
test/val/pr2951.c
Normal file
@@ -0,0 +1,244 @@
|
||||
|
||||
/* bug #2942/#2947: OptStackOps() sometimes removes Lhs loads shared with Rhs.
|
||||
**
|
||||
** These are synthetic, extreme reuse test cases: AX unchanged by pushax.
|
||||
** These do not occur with the current codegen, runtime and optimizers, but
|
||||
** may occur in the future. If the runtime or codegen change sufficiently to
|
||||
** break these tests, they can be deleted.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int fail = 0;
|
||||
|
||||
#define TRASH_AX 0x55AA
|
||||
|
||||
int stat_val;
|
||||
|
||||
int stat_add_full(int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = stat_val;
|
||||
/* AX = AX + AX */
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosaddax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int stat_xor_full(int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = stat_val;
|
||||
/* AX = AX ^ AX */
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosxorax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int stat_xor_and(int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = stat_val;
|
||||
/* AX = AX ^ (AX & 0xFFF0) */
|
||||
asm("jsr pushax");
|
||||
asm("and #$F0");
|
||||
asm("jsr tosxorax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int stat_or_inx(int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = stat_val;
|
||||
/* AX = AX | (AX + 0x100) */
|
||||
asm("jsr pushax");
|
||||
asm("inx");
|
||||
asm("jsr tosorax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int stat_and_add(int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = stat_val;
|
||||
/* AX = (AX & 0xFFF0) + (AX & 0xFFF0) */
|
||||
asm("and #$F0");
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosaddax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int stat_inx_add(int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = stat_val;
|
||||
/* AX = (AX + 0x100) + (AX + 0x100) */
|
||||
asm("inx");
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosaddax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int stat_inx_or(int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = stat_val;
|
||||
/* AX = (AX + 0x100) | (AX + 0x100) */
|
||||
asm("inx");
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosorax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
|
||||
int loc_add_full(int val, int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = val;
|
||||
/* AX = AX + AX */
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosaddax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int loc_xor_full(int val, int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = val;
|
||||
/* AX = AX ^ AX */
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosxorax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int loc_xor_and(int val, int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = val;
|
||||
/* AX = AX ^ (AX & 0xFFF0) */
|
||||
asm("jsr pushax");
|
||||
asm("and #$F0");
|
||||
asm("jsr tosxorax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int loc_or_inx(int val, int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = val;
|
||||
/* AX = AX | (AX + 0x100) */
|
||||
asm("jsr pushax");
|
||||
asm("inx");
|
||||
asm("jsr tosorax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int loc_and_add(int val, int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = val;
|
||||
/* AX = (AX & 0xFFF0) + (AX & 0xFFF0) */
|
||||
asm("and #$F0");
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosaddax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int loc_inx_add(int val, int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = val;
|
||||
/* AX = (AX + 0x100) + (AX + 0x100) */
|
||||
asm("inx");
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosaddax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
int loc_inx_or(int val, int trash)
|
||||
{
|
||||
(void)trash;
|
||||
|
||||
__AX__ = val;
|
||||
/* AX = (AX + 0x100) | (AX + 0x100) */
|
||||
asm("inx");
|
||||
asm("jsr pushax");
|
||||
asm("jsr tosorax");
|
||||
|
||||
return __AX__;
|
||||
}
|
||||
|
||||
|
||||
void test_stat(int (*func)(int /*trash*/), int num, int ref, const char* expr)
|
||||
{
|
||||
int res;
|
||||
|
||||
stat_val = num;
|
||||
res = func(TRASH_AX);
|
||||
if (res != ref) {
|
||||
printf("Fail (stat): %s -> 0x%x\n", expr, res);
|
||||
++fail;
|
||||
}
|
||||
}
|
||||
|
||||
void test_loc(int (*func)(int, int /*trash*/), int num, int ref, const char* expr)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = func(num, TRASH_AX);
|
||||
if (res != ref) {
|
||||
printf("Fail (loc): %s -> 0x%x\n", expr, res);
|
||||
++fail;
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST_STATIC(func, num, ref) test_stat(func, num, (ref), #ref)
|
||||
#define TEST_LOCAL(func, num, ref) test_loc(func, num, (ref), #ref)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TEST_STATIC(stat_add_full, 0x321, 0x321 + 0x321);
|
||||
TEST_STATIC(stat_xor_full, 0x321, 0x321 ^ 0x321);
|
||||
TEST_STATIC(stat_xor_and, 0x321, 0x321 ^ (0x321 & 0xFFF0));
|
||||
TEST_STATIC(stat_or_inx, 0x321, 0x321 | (0x321 + 0x100));
|
||||
TEST_STATIC(stat_and_add, 0x321, (0x321 & 0xFFF0) + (0x321 & 0xFFF0));
|
||||
TEST_STATIC(stat_inx_add, 0x321, (0x321 + 0x100) + (0x321 + 0x100));
|
||||
TEST_STATIC(stat_inx_or, 0x321, (0x321 + 0x100) | (0x321 + 0x100));
|
||||
|
||||
TEST_LOCAL(loc_add_full, 0x321, 0x321 + 0x321);
|
||||
TEST_LOCAL(loc_xor_full, 0x321, 0x321 ^ 0x321);
|
||||
TEST_LOCAL(loc_xor_and, 0x321, 0x321 ^ (0x321 & 0xFFF0));
|
||||
TEST_LOCAL(loc_or_inx, 0x321, 0x321 | (0x321 + 0x100));
|
||||
TEST_LOCAL(loc_and_add, 0x321, (0x321 & 0xFFF0) + (0x321 & 0xFFF0));
|
||||
TEST_LOCAL(loc_inx_add, 0x321, (0x321 + 0x100) + (0x321 + 0x100));
|
||||
TEST_LOCAL(loc_inx_or, 0x321, (0x321 + 0x100) | (0x321 + 0x100));
|
||||
|
||||
return fail == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
Reference in New Issue
Block a user