i1-load fixed
This commit is contained in:
parent
09c99937e7
commit
b56de5888e
3 changed files with 34 additions and 10 deletions
|
|
@ -530,8 +530,6 @@ typedef struct FreeBlk {
|
||||||
static FreeBlk *freeList = (FreeBlk *)0;
|
static FreeBlk *freeList = (FreeBlk *)0;
|
||||||
static char *bumpPtr = (char *)0;
|
static char *bumpPtr = (char *)0;
|
||||||
static char *heapEnd = (char *)0;
|
static char *heapEnd = (char *)0;
|
||||||
// Use the bumpPtr nonzero-ness as the "initialized" flag — sidesteps
|
|
||||||
// an i1-narrowing isel bug on a dedicated bool flag.
|
|
||||||
static void mallocInitOnce(void) {
|
static void mallocInitOnce(void) {
|
||||||
if (bumpPtr) return;
|
if (bumpPtr) return;
|
||||||
bumpPtr = __heap_start ? __heap_start : HEAP_DEFAULT_START;
|
bumpPtr = __heap_start ? __heap_start : HEAP_DEFAULT_START;
|
||||||
|
|
@ -782,8 +780,7 @@ void perror(const char *prefix) {
|
||||||
// span days. CLOCKS_PER_SEC is 60 (defined in time.h).
|
// span days. CLOCKS_PER_SEC is 60 (defined in time.h).
|
||||||
|
|
||||||
// Toolbox-init flag, set by iigsToolboxInit(). time() guards on it.
|
// Toolbox-init flag, set by iigsToolboxInit(). time() guards on it.
|
||||||
// volatile to dodge the i1-narrowing isel bug on bool flag globals.
|
static unsigned short __toolboxInited = 0;
|
||||||
static volatile unsigned short __toolboxInited = 0;
|
|
||||||
|
|
||||||
void iigsToolboxInit(void) {
|
void iigsToolboxInit(void) {
|
||||||
if (__toolboxInited) return;
|
if (__toolboxInited) return;
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,7 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
// --- State ---
|
// --- State ---
|
||||||
// Declared volatile to defeat the GlobalOpt i1-narrowing pass that
|
static int gResourceReady = 0;
|
||||||
// otherwise produces an `i1, zext` load the W65816 backend can't select.
|
|
||||||
// (See MEMORY.md: feedback_i1_load_custom.md.)
|
|
||||||
static volatile int gResourceReady = 0;
|
|
||||||
static ResourceFileT gFiles[IIGS_RES_MAX_FILES];
|
static ResourceFileT gFiles[IIGS_RES_MAX_FILES];
|
||||||
static HandleSlotT gHandles[IIGS_RES_MAX_HANDLES];
|
static HandleSlotT gHandles[IIGS_RES_MAX_HANDLES];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,8 +151,13 @@ W65816TargetLowering::W65816TargetLowering(const TargetMachine &TM,
|
||||||
// every assignment is 0 or 1. Custom-lower so LowerLoad rewrites
|
// every assignment is 0 or 1. Custom-lower so LowerLoad rewrites
|
||||||
// `zext/sext/anyext from i1` into a plain byte load + appropriate
|
// `zext/sext/anyext from i1` into a plain byte load + appropriate
|
||||||
// mask. Both i16 and i8 result widths can appear, depending on
|
// mask. Both i16 and i8 result widths can appear, depending on
|
||||||
// whether the consumer wants the value as `short` or `bool`.
|
// whether the consumer wants the value as `short` or `bool`. Also
|
||||||
for (MVT ResVT : {MVT::i8, MVT::i16}) {
|
// i32 result widths under ptr32: an `if (!g)` guard against a
|
||||||
|
// narrowed-to-i1 global feeds an i32 comparison, so the legalizer
|
||||||
|
// requests ZEXTLOAD/SEXTLOAD/EXTLOAD i32 ← i1. Without Custom action
|
||||||
|
// for the i32 result the legalizer leaves the load alone, isel has
|
||||||
|
// no matching pattern, and we get a "Cannot select" fatal at -O2.
|
||||||
|
for (MVT ResVT : {MVT::i8, MVT::i16, MVT::i32}) {
|
||||||
setLoadExtAction(ISD::ZEXTLOAD, ResVT, MVT::i1, Custom);
|
setLoadExtAction(ISD::ZEXTLOAD, ResVT, MVT::i1, Custom);
|
||||||
setLoadExtAction(ISD::SEXTLOAD, ResVT, MVT::i1, Custom);
|
setLoadExtAction(ISD::SEXTLOAD, ResVT, MVT::i1, Custom);
|
||||||
setLoadExtAction(ISD::EXTLOAD, ResVT, MVT::i1, Custom);
|
setLoadExtAction(ISD::EXTLOAD, ResVT, MVT::i1, Custom);
|
||||||
|
|
@ -1029,6 +1034,31 @@ SDValue W65816TargetLowering::LowerLoad(SDValue Op,
|
||||||
// slot, global) or i32 (ptr32 deref); the recursive ADD handles
|
// slot, global) or i32 (ptr32 deref); the recursive ADD handles
|
||||||
// address arithmetic correctly via LowerI32Bin.
|
// address arithmetic correctly via LowerI32Bin.
|
||||||
if (VT == MVT::i32) {
|
if (VT == MVT::i32) {
|
||||||
|
EVT MemVT = Ld->getMemoryVT();
|
||||||
|
// ZEXTLOAD/SEXTLOAD/EXTLOAD from i1 memory — GlobalOpt narrowed a
|
||||||
|
// byte global to i1 because every assignment is 0/1. The under-
|
||||||
|
// lying storage is still 1 byte: do ONE byte load, mask to a
|
||||||
|
// single bit, then zero/sign-extend to i32. Splitting into two
|
||||||
|
// i16 loads would over-read the global.
|
||||||
|
if (MemVT == MVT::i1) {
|
||||||
|
SDValue ByteLd = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i16, Chain,
|
||||||
|
Ptr, MVT::i8, Ld->getMemOperand());
|
||||||
|
SDValue Bit = DAG.getNode(ISD::AND, DL, MVT::i16, ByteLd,
|
||||||
|
DAG.getConstant(1, DL, MVT::i16));
|
||||||
|
SDValue Lo, Hi;
|
||||||
|
if (Ld->getExtensionType() == ISD::SEXTLOAD) {
|
||||||
|
// i1 sign-extend: bit 0 -> -1 (= 0xFFFF in i16) -> {0xFFFF,
|
||||||
|
// 0xFFFF} in i32. bit 0 = 0 -> 0 -> {0, 0}.
|
||||||
|
Lo = DAG.getNode(ISD::SUB, DL, MVT::i16,
|
||||||
|
DAG.getConstant(0, DL, MVT::i16), Bit);
|
||||||
|
Hi = Lo;
|
||||||
|
} else {
|
||||||
|
Lo = Bit;
|
||||||
|
Hi = DAG.getConstant(0, DL, MVT::i16);
|
||||||
|
}
|
||||||
|
SDValue Wide = buildWide32(DAG, DL, Lo, Hi);
|
||||||
|
return DAG.getMergeValues({Wide, ByteLd.getValue(1)}, DL);
|
||||||
|
}
|
||||||
EVT PtrVT = Ptr.getValueType();
|
EVT PtrVT = Ptr.getValueType();
|
||||||
SDValue Two = DAG.getConstant(2, DL, PtrVT);
|
SDValue Two = DAG.getConstant(2, DL, PtrVT);
|
||||||
SDValue Ptr2 = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, Two);
|
SDValue Ptr2 = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, Two);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue