Skip to content

[ARM] Stop gluing ALU nodes to branches / selects #116970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 18 additions & 35 deletions llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,6 @@ class ARMDAGToDAGISel : public SelectionDAGISel {
bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);

bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32);
return true;
}

bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc);
bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
Expand Down Expand Up @@ -4123,17 +4116,15 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
SDValue Chain = N->getOperand(0);
SDValue N1 = N->getOperand(1);
SDValue N2 = N->getOperand(2);
SDValue N3 = N->getOperand(3);
SDValue InGlue = N->getOperand(4);
SDValue Flags = N->getOperand(3);
assert(N1.getOpcode() == ISD::BasicBlock);
assert(N2.getOpcode() == ISD::Constant);
assert(N3.getOpcode() == ISD::Register);

unsigned CC = (unsigned)N2->getAsZExtVal();

if (InGlue.getOpcode() == ARMISD::CMPZ) {
if (InGlue.getOperand(0).getOpcode() == ISD::INTRINSIC_W_CHAIN) {
SDValue Int = InGlue.getOperand(0);
if (Flags.getOpcode() == ARMISD::CMPZ) {
if (Flags.getOperand(0).getOpcode() == ISD::INTRINSIC_W_CHAIN) {
SDValue Int = Flags.getOperand(0);
uint64_t ID = Int->getConstantOperandVal(1);

// Handle low-overhead loops.
Expand All @@ -4155,15 +4146,15 @@ void ARMDAGToDAGISel::Select(SDNode *N) {

ReplaceUses(N, LoopEnd);
CurDAG->RemoveDeadNode(N);
CurDAG->RemoveDeadNode(InGlue.getNode());
CurDAG->RemoveDeadNode(Flags.getNode());
CurDAG->RemoveDeadNode(Int.getNode());
return;
}
}

bool SwitchEQNEToPLMI;
SelectCMPZ(InGlue.getNode(), SwitchEQNEToPLMI);
InGlue = N->getOperand(4);
SelectCMPZ(Flags.getNode(), SwitchEQNEToPLMI);
Flags = N->getOperand(3);

if (SwitchEQNEToPLMI) {
switch ((ARMCC::CondCodes)CC) {
Expand All @@ -4179,25 +4170,18 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
}

SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32);
SDValue Ops[] = { N1, Tmp2, N3, Chain, InGlue };
SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other,
MVT::Glue, Ops);
Chain = SDValue(ResNode, 0);
if (N->getNumValues() == 2) {
InGlue = SDValue(ResNode, 1);
ReplaceUses(SDValue(N, 1), InGlue);
}
ReplaceUses(SDValue(N, 0),
SDValue(Chain.getNode(), Chain.getResNo()));
CurDAG->RemoveDeadNode(N);
Chain = CurDAG->getCopyToReg(Chain, dl, ARM::CPSR, Flags, SDValue());
SDValue Ops[] = {N1, Tmp2, CurDAG->getRegister(ARM::CPSR, MVT::i32), Chain,
Chain.getValue(1)};
CurDAG->SelectNodeTo(N, Opc, MVT::Other, Ops);
return;
}

case ARMISD::CMPZ: {
// select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0)
// This allows us to avoid materializing the expensive negative constant.
// The CMPZ #0 is useless and will be peepholed away but we need to keep it
// for its glue output.
// The CMPZ #0 is useless and will be peepholed away but we need to keep
// it for its flags output.
SDValue X = N->getOperand(0);
auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode());
if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) {
Expand All @@ -4224,19 +4208,19 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
}
if (Add) {
SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)};
CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2);
CurDAG->MorphNodeTo(N, ARMISD::CMPZ, N->getVTList(), Ops2);
}
}
// Other cases are autogenerated.
break;
}

case ARMISD::CMOV: {
SDValue InGlue = N->getOperand(4);
SDValue Flags = N->getOperand(3);

if (InGlue.getOpcode() == ARMISD::CMPZ) {
if (Flags.getOpcode() == ARMISD::CMPZ) {
bool SwitchEQNEToPLMI;
SelectCMPZ(InGlue.getNode(), SwitchEQNEToPLMI);
SelectCMPZ(Flags.getNode(), SwitchEQNEToPLMI);

if (SwitchEQNEToPLMI) {
SDValue ARMcc = N->getOperand(2);
Expand All @@ -4253,10 +4237,9 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
}
SDValue NewARMcc = CurDAG->getConstant((unsigned)CC, dl, MVT::i32);
SDValue Ops[] = {N->getOperand(0), N->getOperand(1), NewARMcc,
N->getOperand(3), N->getOperand(4)};
N->getOperand(3)};
CurDAG->MorphNodeTo(N, ARMISD::CMOV, N->getVTList(), Ops);
}

}
// Other cases are autogenerated.
break;
Expand Down
Loading