-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[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
Changes from 4 commits
d379396
c42bf96
c697e00
ac634c8
f32928f
e6a00f4
08b5ec1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,11 +85,14 @@ 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); | ||
|
||
// Implement custom stack allocations | ||
setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom); | ||
// Implement custom stack save and restore | ||
|
@@ -514,6 +517,62 @@ XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, | |
return DAG.getNode(XtensaISD::RET, DL, MVT::Other, RetOps); | ||
} | ||
|
||
static unsigned getBranchOpcode(ISD::CondCode Cond, bool &BrInv) { | ||
BrInv = false; | ||
switch (Cond) { | ||
case ISD::SETEQ: | ||
return Xtensa::BEQ; | ||
case ISD::SETNE: | ||
return Xtensa::BNE; | ||
case ISD::SETLT: | ||
return Xtensa::BLT; | ||
case ISD::SETLE: | ||
BrInv = true; | ||
return Xtensa::BGE; | ||
case ISD::SETGT: | ||
BrInv = true; | ||
return Xtensa::BLT; | ||
case ISD::SETGE: | ||
return Xtensa::BGE; | ||
case ISD::SETULT: | ||
return Xtensa::BLTU; | ||
case ISD::SETULE: | ||
BrInv = true; | ||
return Xtensa::BGEU; | ||
case ISD::SETUGT: | ||
BrInv = true; | ||
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(); | ||
|
||
bool BrInv; | ||
unsigned BrKind = getBranchOpcode(CC, BrInv); | ||
SDValue TargetCC = DAG.getConstant(BrKind, DL, MVT::i32); | ||
|
||
// Wrap select nodes | ||
if (BrInv) { | ||
return DAG.getNode(XtensaISD::SELECT_CC, DL, Ty, RHS, LHS, TrueValue, | ||
FalseValue, TargetCC); | ||
} else { | ||
arsenm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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); | ||
|
@@ -676,6 +735,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: | ||
|
@@ -697,6 +758,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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||||||
}; | ||||||
} | ||||||
|
||||||
|
@@ -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; | ||||||
|
@@ -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; | ||||||
|
||||||
|
@@ -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; | ||||||
|
@@ -95,6 +114,10 @@ class XtensaTargetLowering : public TargetLowering { | |||||
SDValue getAddrPCRel(SDValue Op, SelectionDAG &DAG) const; | ||||||
|
||||||
CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const; | ||||||
|
||||||
// Implement EmitInstrWithCustomInserter for individual operation types. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment isn't helpful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||||||
MachineBasicBlock *emitSelectCC(MachineInstr &MI, | ||||||
MachineBasicBlock *BB) const; | ||||||
}; | ||||||
|
||||||
} // end namespace llvm | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't wrap anything
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed