Custom Lowering of ARM zero-extending loads

Hi,

For my research, I need to reshape the current ARM backend to support armv2a. Zero-extend half word load (ldrh) is not supported by armv2a, so I need to make the code generation to not generate ldrh instructions. I want to replace all those instances with a 32-bit load (ldr) and then and the result with 0xffff to mask out the upper bits.

These are the modifications that I have made to accomplish that:

  1. Register the ZEXTLOAD for custom lowering:

setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);

  1. Implement a custom lowering function:

static SDValue LowerExtLoad(SDValue Op, SelectionDAG &DAG) {
LoadSDNode *LD = dyn_cast(Op.getNode());
ISD::LoadExtType ExtType = LD->getExtensionType();

if (LD->getExtensionType() == ISD::ZEXTLOAD) {
DEBUG(errs() << “ZEXTLOAD\n”);
SDValue Chain = LD->getChain();
SDValue Ptr = LD->getBasePtr();
DebugLoc dl = Op.getNode()->getDebugLoc();
SDValue LdResult = DAG.getExtLoad(ISD::EXTLOAD, dl, MVT::i32,
Chain, Ptr, LD->getPointerInfo(), MVT::i32,
LD->isVolatile(), LD->isNonTemporal(),
LD->getAlignment());
Chain = LdResult.getValue(1);
SDValue Mask = DAG.getConstant(0x1, MVT::i32);
DAG.ReplaceAllUsesOfValueWith(SDValue(LD, 0), LdResult);
DAG.ReplaceAllUsesOfValueWith(SDValue(LD, 1), Chain);

DAG.RemoveDeadNode(LD);
//return DAG.getNode(ISD::AND, dl, MVT::i32, Op, Mask);
}

}

Apologize, I pressed the wrong key and the message was sent before I completed it. Bellow is the complete implementation of the custom lowering function:

static SDValue LowerExtLoad(SDValue Op, SelectionDAG &DAG) {
LoadSDNode *LD = dyn_cast(Op.getNode());
ISD::LoadExtType ExtType = LD->getExtensionType();

if (LD->getExtensionType() == ISD::ZEXTLOAD) {
DEBUG(errs() << “ZEXTLOAD\n”);
SDValue Chain = LD->getChain();
SDValue Ptr = LD->getBasePtr();
DebugLoc dl = Op.getNode()->getDebugLoc();
SDValue LdResult = DAG.getExtLoad(ISD::EXTLOAD, dl, MVT::i32,
Chain, Ptr, LD->getPointerInfo(), MVT::i32,
LD->isVolatile(), LD->isNonTemporal(),
LD->getAlignment());
Chain = LdResult.getValue(1);
SDValue Mask = DAG.getConstant(0xffff, MVT::i32);
DAG.ReplaceAllUsesOfValueWith(SDValue(LD, 0), LdResult);
DAG.ReplaceAllUsesOfValueWith(SDValue(LD, 1), Chain);
DAG.RemoveDeadNode(LD);
return DAG.getNode(ISD::AND, dl, MVT::i32, LdResult, Mask);
}
else
return Op;
}

However, when I get the following error during the compilation of the test file.

llc: /files3/scratch/gho705/llvm/llvm-3.2.src/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:694: bool llvm::SelectionDAG::RemoveNodeFromCSEMaps(llvm::SDNode*): Assertion `N->getOpcode() != ISD::DELETED_NODE && “DELETED_NODE in CSEMap!”’ failed.

I am wondering what was wrong with the way I removed the current illegal extending load?

Thank you,

Giang