[llvm] [Xtensa] Implement lowering Mul/Div/Shift operations. (PR #99981)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 12 04:59:44 PDT 2024
================
@@ -713,6 +746,158 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
return DAG.getMergeValues(Ops, DL);
}
+SDValue XtensaTargetLowering::LowerShiftLeftParts(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ MVT VT = MVT::i32;
+ SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1);
+ SDValue Shamt = Op.getOperand(2);
+
+ // if Shamt - register size < 0: // Shamt < register size
+ // Lo = Lo << Shamt
+ // Hi = (Hi << Shamt) | (Lo >>u (register size - Shamt))
+ // else:
+ // Lo = 0
+ // Hi = Lo << (Shamt - register size)
+
+ SDValue MinusRegisterSize = DAG.getConstant(-32, DL, VT);
+ SDValue ShamtMinusRegisterSize =
+ DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize);
+
+ SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);
+ SDValue HiTrue = DAG.getNode(XtensaISD::SRCL, DL, VT, Hi, Lo, Shamt);
+ SDValue Zero = DAG.getConstant(0, DL, VT);
+ SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusRegisterSize);
+
+ SDValue Cond = DAG.getSetCC(DL, VT, ShamtMinusRegisterSize, Zero, ISD::SETLT);
+ Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, LoTrue, Zero);
+ Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, HiTrue, HiFalse);
+
+ return DAG.getMergeValues({Lo, Hi}, DL);
+}
+
+SDValue XtensaTargetLowering::LowerShiftRightParts(SDValue Op,
+ SelectionDAG &DAG,
+ bool IsSRA) const {
+ SDLoc DL(Op);
+ SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1);
+ SDValue Shamt = Op.getOperand(2);
+ MVT VT = MVT::i32;
+
+ // SRA expansion:
+ // if Shamt - register size < 0: // Shamt < register size
+ // Lo = (Lo >>u Shamt) | (Hi << u (register size - Shamt))
+ // Hi = Hi >>s Shamt
+ // else:
+ // Lo = Hi >>s (Shamt - register size);
+ // Hi = Hi >>s (register size - 1)
+ //
+ // SRL expansion:
+ // if Shamt - register size < 0: // Shamt < register size
+ // Lo = (Lo >>u Shamt) | (Hi << u (register size - Shamt))
+ // Hi = Hi >>u Shamt
+ // else:
+ // Lo = Hi >>u (Shamt - register size);
+ // Hi = 0;
+
+ unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL;
+ SDValue MinusRegisterSize = DAG.getConstant(-32, DL, VT);
+ SDValue RegisterSizeMinus1 = DAG.getConstant(32 - 1, DL, VT);
+ SDValue ShamtMinusRegisterSize =
+ DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize);
+
+ SDValue LoTrue = DAG.getNode(XtensaISD::SRCR, DL, VT, Hi, Lo, Shamt);
+ SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt);
+ SDValue Zero = DAG.getConstant(0, DL, VT);
+ SDValue LoFalse =
+ DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusRegisterSize);
+ SDValue HiFalse;
+
+ if (IsSRA) {
+ HiFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, RegisterSizeMinus1);
+ } else {
+ HiFalse = Zero;
+ }
+
+ SDValue Cond = DAG.getSetCC(DL, VT, ShamtMinusRegisterSize, Zero, ISD::SETLT);
+ Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, LoTrue, LoFalse);
+ Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, HiTrue, HiFalse);
+
+ return DAG.getMergeValues({Lo, Hi}, DL);
+}
+
+SDValue XtensaTargetLowering::LowerCTPOP(SDValue Op, SelectionDAG &DAG) const {
+ EVT VT = Op->getValueType(0);
+ SDValue Val = Op.getOperand(0);
+ SDLoc DL(Op);
+
+ if (VT != MVT::i32)
+ return SDValue();
+
+ // CTPOP expansion:
+ // Val = (Val - (Val >> 1)) & 0x55555555
+ // Val = ((Val >> 2) & 0x33333333) + (Val & 0x33333333)
+ // Val = ((Val >> 4) + Val) & 0x0f0f0f0f
+ // Val = (Val >> 8) + Val
+ // Val = (extract bits [16, 20] from Val) + Val
+ // Val = extract bits [0, 5] from Val
+
----------------
arsenm wrote:
Custom lowering can also just directly call TLI::expandCTPOP
https://github.com/llvm/llvm-project/pull/99981
More information about the llvm-commits
mailing list