Skip to content

[Xtensa] Implement lowering SELECT_CC, SETCC. #97017

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 7 commits into from
Jul 11, 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
136 changes: 135 additions & 1 deletion llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,19 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
// indirect jump.
setOperationAction(ISD::BR_JT, MVT::Other, Custom);

setOperationPromotedToType(ISD::BR_CC, MVT::i1, MVT::i32);
setOperationAction(ISD::BR_CC, MVT::i32, Legal);
setOperationAction(ISD::BR_CC, MVT::i64, Expand);
setOperationAction(ISD::BR_CC, MVT::f32, Expand);

setOperationAction(ISD::SELECT, MVT::i32, Expand);
setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
setOperationAction(ISD::SETCC, MVT::i32, Expand);

setCondCodeAction(ISD::SETGT, MVT::i32, Expand);
setCondCodeAction(ISD::SETLE, MVT::i32, Expand);
setCondCodeAction(ISD::SETUGT, MVT::i32, Expand);
setCondCodeAction(ISD::SETULE, MVT::i32, Expand);

// Implement custom stack allocations
setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom);
// Implement custom stack save and restore
Expand Down Expand Up @@ -514,6 +522,50 @@ XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
return DAG.getNode(XtensaISD::RET, DL, MVT::Other, RetOps);
}

static unsigned getBranchOpcode(ISD::CondCode Cond) {
switch (Cond) {
case ISD::SETEQ:
return Xtensa::BEQ;
case ISD::SETNE:
return Xtensa::BNE;
case ISD::SETLT:
return Xtensa::BLT;
case ISD::SETLE:
return Xtensa::BGE;
case ISD::SETGT:
return Xtensa::BLT;
case ISD::SETGE:
return Xtensa::BGE;
case ISD::SETULT:
return Xtensa::BLTU;
case ISD::SETULE:
return Xtensa::BGEU;
case ISD::SETUGT:
return Xtensa::BLTU;
case ISD::SETUGE:
return Xtensa::BGEU;
default:
llvm_unreachable("Unknown branch kind");
}
}

SDValue XtensaTargetLowering::LowerSELECT_CC(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
EVT Ty = Op.getOperand(0).getValueType();
SDValue LHS = Op.getOperand(0);
SDValue RHS = Op.getOperand(1);
SDValue TrueValue = Op.getOperand(2);
SDValue FalseValue = Op.getOperand(3);
ISD::CondCode CC = cast<CondCodeSDNode>(Op->getOperand(4))->get();

unsigned BrOpcode = getBranchOpcode(CC);
SDValue TargetCC = DAG.getConstant(BrOpcode, DL, MVT::i32);

return DAG.getNode(XtensaISD::SELECT_CC, DL, Ty, LHS, RHS, TrueValue,
FalseValue, TargetCC);
}

SDValue XtensaTargetLowering::LowerImmediate(SDValue Op,
SelectionDAG &DAG) const {
const ConstantSDNode *CN = cast<ConstantSDNode>(Op);
Expand Down Expand Up @@ -676,6 +728,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
return LowerJumpTable(Op, DAG);
case ISD::ConstantPool:
return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG);
case ISD::SELECT_CC:
return LowerSELECT_CC(Op, DAG);
case ISD::STACKSAVE:
return LowerSTACKSAVE(Op, DAG);
case ISD::STACKRESTORE:
Expand All @@ -697,6 +751,86 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
return "XtensaISD::PCREL_WRAPPER";
case XtensaISD::RET:
return "XtensaISD::RET";
case XtensaISD::SELECT_CC:
return "XtensaISD::SELECT_CC";
}
return nullptr;
}

//===----------------------------------------------------------------------===//
// Custom insertion
//===----------------------------------------------------------------------===//

MachineBasicBlock *
XtensaTargetLowering::emitSelectCC(MachineInstr &MI,
MachineBasicBlock *MBB) const {
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
DebugLoc DL = MI.getDebugLoc();

MachineOperand &LHS = MI.getOperand(1);
MachineOperand &RHS = MI.getOperand(2);
MachineOperand &TrueValue = MI.getOperand(3);
MachineOperand &FalseValue = MI.getOperand(4);
unsigned BrKind = MI.getOperand(5).getImm();

// To "insert" a SELECT_CC instruction, we actually have to insert
// CopyMBB and SinkMBB blocks and add branch to MBB. We build phi
// operation in SinkMBB like phi (TrueVakue,FalseValue), where TrueValue
// is passed from MMB and FalseValue is passed from CopyMBB.
// MBB
// | \
// | CopyMBB
// | /
// SinkMBB
// The incoming instruction knows the
// destination vreg to set, the condition code register to branch on, the
// true/false values to select between, and a branch opcode to use.
const BasicBlock *LLVM_BB = MBB->getBasicBlock();
MachineFunction::iterator It = ++MBB->getIterator();

MachineFunction *F = MBB->getParent();
MachineBasicBlock *CopyMBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will need a code like this here (for a future patch that adds related tests), see 2dcf051:

  // Set the call frame size on entry to the new basic blocks.
  uint64_t CallFrameSize = TII.getCallFrameSizeAt(MI);
  CopyMBB->setCallFrameSize(CallFrameSize);
  SinkMBB->setCallFrameSize(CallFrameSize);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I will use this information in future.


F->insert(It, CopyMBB);
F->insert(It, SinkMBB);

// Transfer the remainder of MBB and its successor edges to SinkMBB.
SinkMBB->splice(SinkMBB->begin(), MBB,
std::next(MachineBasicBlock::iterator(MI)), MBB->end());
SinkMBB->transferSuccessorsAndUpdatePHIs(MBB);

MBB->addSuccessor(CopyMBB);
MBB->addSuccessor(SinkMBB);

BuildMI(MBB, DL, TII.get(BrKind))
.addReg(LHS.getReg())
.addReg(RHS.getReg())
.addMBB(SinkMBB);

CopyMBB->addSuccessor(SinkMBB);

// SinkMBB:
// %Result = phi [ %FalseValue, CopyMBB ], [ %TrueValue, MBB ]
// ...

BuildMI(*SinkMBB, SinkMBB->begin(), DL, TII.get(Xtensa::PHI),
MI.getOperand(0).getReg())
.addReg(FalseValue.getReg())
.addMBB(CopyMBB)
.addReg(TrueValue.getReg())
.addMBB(MBB);

MI.eraseFromParent(); // The pseudo instruction is gone now.
return SinkMBB;
}

MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
MachineInstr &MI, MachineBasicBlock *MBB) const {
switch (MI.getOpcode()) {
case Xtensa::SELECT:
return emitSelectCC(MI, MBB);
default:
llvm_unreachable("Unexpected instr type to insert");
}
}
24 changes: 23 additions & 1 deletion llvm/lib/Target/Xtensa/XtensaISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ enum {
// Wraps a TargetGlobalAddress that should be loaded using PC-relative
// accesses. Operand 0 is the address.
PCREL_WRAPPER,
RET
RET,

// Select with condition operator - This selects between a true value and
// a false value (ops #2 and #3) based on the boolean result of comparing
// the lhs and rhs (ops #0 and #1) of a conditional expression with the
// condition code in op #4
SELECT_CC,
};
}

Expand All @@ -44,6 +50,13 @@ class XtensaTargetLowering : public TargetLowering {
explicit XtensaTargetLowering(const TargetMachine &TM,
const XtensaSubtarget &STI);

EVT getSetCCResultType(const DataLayout &, LLVMContext &,
EVT VT) const override {
if (!VT.isVector())
return MVT::i32;
return VT.changeVectorElementTypeToInteger();
}

bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;

const char *getTargetNodeName(unsigned Opcode) const override;
Expand Down Expand Up @@ -71,6 +84,10 @@ class XtensaTargetLowering : public TargetLowering {

const XtensaSubtarget &getSubtarget() const { return Subtarget; }

MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const override;

private:
const XtensaSubtarget &Subtarget;

Expand All @@ -86,6 +103,8 @@ class XtensaTargetLowering : public TargetLowering {

SDValue LowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;

SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;

SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;

SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const;
Expand All @@ -95,6 +114,9 @@ class XtensaTargetLowering : public TargetLowering {
SDValue getAddrPCRel(SDValue Op, SelectionDAG &DAG) const;

CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const;

MachineBasicBlock *emitSelectCC(MachineInstr &MI,
MachineBasicBlock *BB) const;
};

} // end namespace llvm
Expand Down
18 changes: 9 additions & 9 deletions llvm/lib/Target/Xtensa/XtensaInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -416,15 +416,6 @@ def BBSI : RRI8_Inst<0x07, (outs),
let imm8 = target;
}

def : Pat<(brcc SETGT, AR:$s, AR:$t, bb:$target),
(BLT AR:$t, AR:$s, bb:$target)>;
def : Pat<(brcc SETUGT, AR:$s, AR:$t, bb:$target),
(BLTU AR:$t, AR:$s, bb:$target)>;
def : Pat<(brcc SETLE, AR:$s, AR:$t, bb:$target),
(BGE AR:$t, AR:$s, bb:$target)>;
def : Pat<(brcc SETULE, AR:$s, AR:$t, bb:$target),
(BGEU AR:$t, AR:$s, bb:$target)>;

//===----------------------------------------------------------------------===//
// Call and jump instructions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -574,3 +565,12 @@ let Defs = [SP], Uses = [SP] in {
"#ADJCALLSTACKUP",
[(Xtensa_callseq_end timm:$amt1, timm:$amt2)]>;
}

//===----------------------------------------------------------------------===//
// Generic select instruction
//===----------------------------------------------------------------------===//
let usesCustomInserter = 1 in {
def SELECT : Pseudo<(outs AR:$dst), (ins AR:$lhs, AR:$rhs, AR:$t, AR:$f, i32imm:$cond),
"!select $dst, $lhs, $rhs, $t, $f, $cond",
[(set i32:$dst, (Xtensa_select_cc i32:$lhs, i32:$rhs, i32:$t, i32:$f, imm:$cond))]>;
}
8 changes: 8 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaOperators.td
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ def SDT_XtensaWrapPtr : SDTypeProfile<1, 1,

def SDT_XtensaBrJT : SDTypeProfile<0, 2,
[SDTCisPtrTy<0>, SDTCisVT<1, i32>]>;

def SDT_XtensaSelectCC : SDTypeProfile<1, 5,
[SDTCisSameAs<0, 1>,
SDTCisSameAs<2, 3>,
SDTCisVT<5, i32>]>;
//===----------------------------------------------------------------------===//
// Node definitions
//===----------------------------------------------------------------------===//
Expand All @@ -38,3 +43,6 @@ def Xtensa_callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_XtensaCallSeqEnd,
SDNPOutGlue]>;

def Xtensa_brjt: SDNode<"XtensaISD::BR_JT", SDT_XtensaBrJT, [SDNPHasChain]>;

def Xtensa_select_cc: SDNode<"XtensaISD::SELECT_CC", SDT_XtensaSelectCC,
[SDNPInGlue]>;
Loading
Loading