Skip to content

Commit fab515c

Browse files
authored
[Xtensa] Implement lowering Mul/Div/Shift operations. (#99981)
Implement lowering of the Mul/Div operations and also shift parts operations. Implement lowering of the bit manipulations, like ROT/SWAP/CTPOP/CTTZ/CTLZ.
1 parent c79d1fa commit fab515c

11 files changed

+2697
-8
lines changed

llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class XtensaDAGToDAGISel : public SelectionDAGISel {
6767
Valid = isValidAddrOffset(Scale, OffsetVal);
6868

6969
if (Valid) {
70-
// If the first operand is a FI, get the TargetFI Node
70+
// If the first operand is a FI, get the TargetFI Node.
7171
if (FrameIndexSDNode *FIN =
7272
dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
7373
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
@@ -125,12 +125,90 @@ FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM,
125125

126126
void XtensaDAGToDAGISel::Select(SDNode *Node) {
127127
SDLoc DL(Node);
128+
EVT VT = Node->getValueType(0);
128129

129130
// If we have a custom node, we already have selected!
130131
if (Node->isMachineOpcode()) {
131132
Node->setNodeId(-1);
132133
return;
133134
}
134135

136+
switch (Node->getOpcode()) {
137+
case ISD::SHL: {
138+
SDValue N0 = Node->getOperand(0);
139+
SDValue N1 = Node->getOperand(1);
140+
auto *C = dyn_cast<ConstantSDNode>(N1);
141+
// If C is constant in range [1..31] then we can generate SLLI
142+
// instruction using pattern matching, otherwise generate SLL.
143+
if (!C || C->isZero()) {
144+
SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N1);
145+
SDNode *SLL =
146+
CurDAG->getMachineNode(Xtensa::SLL, DL, VT, N0, SDValue(SSL, 0));
147+
ReplaceNode(Node, SLL);
148+
return;
149+
}
150+
break;
151+
}
152+
case ISD::SRL: {
153+
SDValue N0 = Node->getOperand(0);
154+
SDValue N1 = Node->getOperand(1);
155+
auto *C = dyn_cast<ConstantSDNode>(N1);
156+
157+
// If C is constant then we can generate SRLI
158+
// instruction using pattern matching or EXTUI, otherwise generate SRL.
159+
if (C) {
160+
if (isUInt<4>(C->getZExtValue()))
161+
break;
162+
unsigned ShAmt = C->getZExtValue();
163+
SDNode *EXTUI = CurDAG->getMachineNode(
164+
Xtensa::EXTUI, DL, VT, N0, CurDAG->getTargetConstant(ShAmt, DL, VT),
165+
CurDAG->getTargetConstant(32 - ShAmt, DL, VT));
166+
ReplaceNode(Node, EXTUI);
167+
return;
168+
}
169+
170+
SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);
171+
SDNode *SRL =
172+
CurDAG->getMachineNode(Xtensa::SRL, DL, VT, N0, SDValue(SSR, 0));
173+
ReplaceNode(Node, SRL);
174+
return;
175+
}
176+
case ISD::SRA: {
177+
SDValue N0 = Node->getOperand(0);
178+
SDValue N1 = Node->getOperand(1);
179+
auto *C = dyn_cast<ConstantSDNode>(N1);
180+
// If C is constant then we can generate SRAI
181+
// instruction using pattern matching, otherwise generate SRA.
182+
if (!C) {
183+
SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);
184+
SDNode *SRA =
185+
CurDAG->getMachineNode(Xtensa::SRA, DL, VT, N0, SDValue(SSR, 0));
186+
ReplaceNode(Node, SRA);
187+
return;
188+
}
189+
break;
190+
}
191+
case XtensaISD::SRCL: {
192+
SDValue N0 = Node->getOperand(0);
193+
SDValue N1 = Node->getOperand(1);
194+
SDValue N2 = Node->getOperand(2);
195+
SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N2);
196+
SDNode *SRC =
197+
CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSL, 0));
198+
ReplaceNode(Node, SRC);
199+
return;
200+
}
201+
case XtensaISD::SRCR: {
202+
SDValue N0 = Node->getOperand(0);
203+
SDValue N1 = Node->getOperand(1);
204+
SDValue N2 = Node->getOperand(2);
205+
SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N2);
206+
SDNode *SRC =
207+
CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSR, 0));
208+
ReplaceNode(Node, SRC);
209+
return;
210+
}
211+
}
212+
135213
SelectCode(Node);
136214
}

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp

Lines changed: 167 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/CodeGen/MachineJumpTableInfo.h"
2222
#include "llvm/CodeGen/MachineRegisterInfo.h"
2323
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
24+
#include "llvm/IR/GlobalVariable.h"
2425
#include "llvm/Support/Debug.h"
2526
#include "llvm/Support/ErrorHandling.h"
2627
#include "llvm/Support/MathExtras.h"
@@ -98,6 +99,32 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
9899
setCondCodeAction(ISD::SETUGT, MVT::i32, Expand);
99100
setCondCodeAction(ISD::SETULE, MVT::i32, Expand);
100101

102+
setOperationAction(ISD::MUL, MVT::i32, Expand);
103+
setOperationAction(ISD::MULHU, MVT::i32, Expand);
104+
setOperationAction(ISD::MULHS, MVT::i32, Expand);
105+
setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
106+
setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
107+
108+
setOperationAction(ISD::SDIV, MVT::i32, Expand);
109+
setOperationAction(ISD::UDIV, MVT::i32, Expand);
110+
setOperationAction(ISD::SREM, MVT::i32, Expand);
111+
setOperationAction(ISD::UREM, MVT::i32, Expand);
112+
setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
113+
setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
114+
115+
setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
116+
setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom);
117+
setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom);
118+
119+
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
120+
setOperationAction(ISD::ROTL, MVT::i32, Expand);
121+
setOperationAction(ISD::ROTR, MVT::i32, Expand);
122+
setOperationAction(ISD::CTPOP, MVT::i32, Custom);
123+
setOperationAction(ISD::CTTZ, MVT::i32, Expand);
124+
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
125+
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
126+
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
127+
101128
// Implement custom stack allocations
102129
setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom);
103130
// Implement custom stack save and restore
@@ -629,8 +656,12 @@ SDValue XtensaTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const {
629656
EVT PtrVT = Table.getValueType();
630657
unsigned EntrySize = MJTI->getEntrySize(TD);
631658

632-
Index = DAG.getNode(ISD::MUL, DL, Index.getValueType(), Index,
633-
DAG.getConstant(EntrySize, DL, Index.getValueType()));
659+
assert((MJTI->getEntrySize(TD) == 4) && "Unsupported jump-table entry size");
660+
661+
Index = DAG.getNode(
662+
ISD::SHL, DL, Index.getValueType(), Index,
663+
DAG.getConstant(Log2_32(EntrySize), DL, Index.getValueType()));
664+
634665
SDValue Addr = DAG.getNode(ISD::ADD, DL, Index.getValueType(), Index, Table);
635666
SDValue LD =
636667
DAG.getLoad(PtrVT, DL, Chain, Addr,
@@ -662,10 +693,12 @@ SDValue XtensaTargetLowering::getAddrPCRel(SDValue Op,
662693
return DAG.getNode(XtensaISD::PCREL_WRAPPER, DL, Ty, Op);
663694
}
664695

665-
SDValue XtensaTargetLowering::LowerConstantPool(ConstantPoolSDNode *CP,
696+
SDValue XtensaTargetLowering::LowerConstantPool(SDValue Op,
666697
SelectionDAG &DAG) const {
667-
EVT PtrVT = getPointerTy(DAG.getDataLayout());
698+
EVT PtrVT = Op.getValueType();
699+
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
668700
SDValue Result;
701+
669702
if (!CP->isMachineConstantPoolEntry()) {
670703
Result = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, CP->getAlign(),
671704
CP->getOffset());
@@ -713,6 +746,119 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
713746
return DAG.getMergeValues(Ops, DL);
714747
}
715748

749+
SDValue XtensaTargetLowering::LowerShiftLeftParts(SDValue Op,
750+
SelectionDAG &DAG) const {
751+
SDLoc DL(Op);
752+
MVT VT = MVT::i32;
753+
SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1);
754+
SDValue Shamt = Op.getOperand(2);
755+
756+
// if Shamt - register size < 0: // Shamt < register size
757+
// Lo = Lo << Shamt
758+
// Hi = (Hi << Shamt) | (Lo >>u (register size - Shamt))
759+
// else:
760+
// Lo = 0
761+
// Hi = Lo << (Shamt - register size)
762+
763+
SDValue MinusRegisterSize = DAG.getConstant(-32, DL, VT);
764+
SDValue ShamtMinusRegisterSize =
765+
DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize);
766+
767+
SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);
768+
SDValue HiTrue = DAG.getNode(XtensaISD::SRCL, DL, VT, Hi, Lo, Shamt);
769+
SDValue Zero = DAG.getConstant(0, DL, VT);
770+
SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusRegisterSize);
771+
772+
SDValue Cond = DAG.getSetCC(DL, VT, ShamtMinusRegisterSize, Zero, ISD::SETLT);
773+
Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, LoTrue, Zero);
774+
Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, HiTrue, HiFalse);
775+
776+
return DAG.getMergeValues({Lo, Hi}, DL);
777+
}
778+
779+
SDValue XtensaTargetLowering::LowerShiftRightParts(SDValue Op,
780+
SelectionDAG &DAG,
781+
bool IsSRA) const {
782+
SDLoc DL(Op);
783+
SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1);
784+
SDValue Shamt = Op.getOperand(2);
785+
MVT VT = MVT::i32;
786+
787+
// SRA expansion:
788+
// if Shamt - register size < 0: // Shamt < register size
789+
// Lo = (Lo >>u Shamt) | (Hi << u (register size - Shamt))
790+
// Hi = Hi >>s Shamt
791+
// else:
792+
// Lo = Hi >>s (Shamt - register size);
793+
// Hi = Hi >>s (register size - 1)
794+
//
795+
// SRL expansion:
796+
// if Shamt - register size < 0: // Shamt < register size
797+
// Lo = (Lo >>u Shamt) | (Hi << u (register size - Shamt))
798+
// Hi = Hi >>u Shamt
799+
// else:
800+
// Lo = Hi >>u (Shamt - register size);
801+
// Hi = 0;
802+
803+
unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL;
804+
SDValue MinusRegisterSize = DAG.getConstant(-32, DL, VT);
805+
SDValue RegisterSizeMinus1 = DAG.getConstant(32 - 1, DL, VT);
806+
SDValue ShamtMinusRegisterSize =
807+
DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize);
808+
809+
SDValue LoTrue = DAG.getNode(XtensaISD::SRCR, DL, VT, Hi, Lo, Shamt);
810+
SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt);
811+
SDValue Zero = DAG.getConstant(0, DL, VT);
812+
SDValue LoFalse =
813+
DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusRegisterSize);
814+
SDValue HiFalse;
815+
816+
if (IsSRA) {
817+
HiFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, RegisterSizeMinus1);
818+
} else {
819+
HiFalse = Zero;
820+
}
821+
822+
SDValue Cond = DAG.getSetCC(DL, VT, ShamtMinusRegisterSize, Zero, ISD::SETLT);
823+
Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, LoTrue, LoFalse);
824+
Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, HiTrue, HiFalse);
825+
826+
return DAG.getMergeValues({Lo, Hi}, DL);
827+
}
828+
829+
SDValue XtensaTargetLowering::LowerCTPOP(SDValue Op, SelectionDAG &DAG) const {
830+
auto &TLI = DAG.getTargetLoweringInfo();
831+
return TLI.expandCTPOP(Op.getNode(), DAG);
832+
}
833+
834+
bool XtensaTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
835+
SDValue C) const {
836+
APInt Imm;
837+
unsigned EltSizeInBits;
838+
839+
if (ISD::isConstantSplatVector(C.getNode(), Imm)) {
840+
EltSizeInBits = VT.getScalarSizeInBits();
841+
} else if (VT.isScalarInteger()) {
842+
EltSizeInBits = VT.getSizeInBits();
843+
if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode()))
844+
Imm = ConstNode->getAPIntValue();
845+
else
846+
return false;
847+
} else {
848+
return false;
849+
}
850+
851+
// Omit if data size exceeds.
852+
if (EltSizeInBits > 32)
853+
return false;
854+
855+
// Convert MULT to LSL.
856+
if (Imm.isPowerOf2() && Imm.isIntN(5))
857+
return true;
858+
859+
return false;
860+
}
861+
716862
SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
717863
SelectionDAG &DAG) const {
718864
switch (Op.getOpcode()) {
@@ -726,8 +872,10 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
726872
return LowerBlockAddress(Op, DAG);
727873
case ISD::JumpTable:
728874
return LowerJumpTable(Op, DAG);
875+
case ISD::CTPOP:
876+
return LowerCTPOP(Op, DAG);
729877
case ISD::ConstantPool:
730-
return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG);
878+
return LowerConstantPool(Op, DAG);
731879
case ISD::SELECT_CC:
732880
return LowerSELECT_CC(Op, DAG);
733881
case ISD::STACKSAVE:
@@ -736,6 +884,12 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
736884
return LowerSTACKRESTORE(Op, DAG);
737885
case ISD::DYNAMIC_STACKALLOC:
738886
return LowerDYNAMIC_STACKALLOC(Op, DAG);
887+
case ISD::SHL_PARTS:
888+
return LowerShiftLeftParts(Op, DAG);
889+
case ISD::SRA_PARTS:
890+
return LowerShiftRightParts(Op, DAG, true);
891+
case ISD::SRL_PARTS:
892+
return LowerShiftRightParts(Op, DAG, false);
739893
default:
740894
report_fatal_error("Unexpected node to lower");
741895
}
@@ -747,12 +901,18 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
747901
return "XtensaISD::BR_JT";
748902
case XtensaISD::CALL:
749903
return "XtensaISD::CALL";
904+
case XtensaISD::EXTUI:
905+
return "XtensaISD::EXTUI";
750906
case XtensaISD::PCREL_WRAPPER:
751907
return "XtensaISD::PCREL_WRAPPER";
752908
case XtensaISD::RET:
753909
return "XtensaISD::RET";
754910
case XtensaISD::SELECT_CC:
755911
return "XtensaISD::SELECT_CC";
912+
case XtensaISD::SRCL:
913+
return "XtensaISD::SRCL";
914+
case XtensaISD::SRCR:
915+
return "XtensaISD::SRCR";
756916
}
757917
return nullptr;
758918
}
@@ -827,6 +987,8 @@ XtensaTargetLowering::emitSelectCC(MachineInstr &MI,
827987

828988
MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
829989
MachineInstr &MI, MachineBasicBlock *MBB) const {
990+
DebugLoc DL = MI.getDebugLoc();
991+
830992
switch (MI.getOpcode()) {
831993
case Xtensa::SELECT:
832994
return emitSelectCC(MI, MBB);

0 commit comments

Comments
 (0)