diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index f9f35f66319b5..142414ddf7132 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -819,49 +819,6 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInSign(SDNode *Node) { return false; } -// (xor X, (and (xor X, C1), C2)) -// -> (qc.insbi X, (C1 >> ShAmt), Width, ShAmt) -// where C2 is a shifted mask with width=Width and shift=ShAmt -bool RISCVDAGToDAGISel::tryBitfieldInsertOpFromXor(SDNode *Node) { - - if (!Subtarget->hasVendorXqcibm()) - return false; - - using namespace SDPatternMatch; - - SDValue X; - APInt CImm, CMask; - if (!sd_match( - Node, - m_Xor(m_Value(X), - m_OneUse(m_And(m_OneUse(m_Xor(m_Deferred(X), m_ConstInt(CImm))), - m_ConstInt(CMask)))))) - return false; - - unsigned Width, ShAmt; - if (!CMask.isShiftedMask(ShAmt, Width)) - return false; - - int64_t Imm = CImm.getSExtValue(); - Imm >>= ShAmt; - - SDLoc DL(Node); - SDValue ImmNode; - auto Opc = RISCV::QC_INSB; - - if (isInt<5>(Imm)) { - Opc = RISCV::QC_INSBI; - ImmNode = CurDAG->getSignedTargetConstant(Imm, DL, MVT::i32); - } else { - ImmNode = selectImm(CurDAG, DL, MVT::i32, Imm, *Subtarget); - } - SDValue Ops[] = {X, ImmNode, CurDAG->getTargetConstant(Width, DL, MVT::i32), - CurDAG->getTargetConstant(ShAmt, DL, MVT::i32)}; - ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, MVT::i32, Ops)); - - return true; -} - bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node, const SDLoc &DL, MVT VT, SDValue X, unsigned Msb, @@ -1442,9 +1399,6 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { if (tryShrinkShlLogicImm(Node)) return; - if (tryBitfieldInsertOpFromXor(Node)) - return; - break; case ISD::AND: { auto *N1C = dyn_cast(Node->getOperand(1)); diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h index c329a4c6ec62e..ba129457d6284 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h @@ -75,7 +75,6 @@ class RISCVDAGToDAGISel : public SelectionDAGISel { bool trySignedBitfieldExtract(SDNode *Node); bool trySignedBitfieldInsertInSign(SDNode *Node); bool trySignedBitfieldInsertInMask(SDNode *Node); - bool tryBitfieldInsertOpFromXor(SDNode *Node); bool tryBitfieldInsertOpFromOrAndImm(SDNode *Node); bool tryUnsignedBitfieldExtract(SDNode *Node, const SDLoc &DL, MVT VT, SDValue X, unsigned Msb, unsigned Lsb); diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index a33224845e2b7..f247987c992e9 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -16065,6 +16065,44 @@ static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1, return DAG.getNode(ISD::XOR, DL, VT, NewOr, TrueV.getOperand(1)); } +// (xor X, (xor (and X, C2), Y)) +// ->(qc_insb X, (sra Y, ShAmt), Width, ShAmt) +// where C2 is a shifted mask with width = Width and shift = ShAmt +// qc_insb might become qc.insb or qc.insbi depending on the operands. +static SDValue combineXorToBitfieldInsert(SDNode *N, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget) { + if (!Subtarget.hasVendorXqcibm()) + return SDValue(); + + using namespace SDPatternMatch; + + SDValue Base, Inserted; + APInt CMask; + if (!sd_match(N, m_Xor(m_Value(Base), + m_OneUse(m_Xor(m_OneUse(m_And(m_Deferred(Base), + m_ConstInt(CMask))), + m_Value(Inserted)))))) + return SDValue(); + + if (N->getValueType(0) != MVT::i32) + return SDValue(); + + unsigned Width, ShAmt; + if (!CMask.isShiftedMask(ShAmt, Width)) + return SDValue(); + + SDLoc DL(N); + + // `Inserted` needs to be right shifted before it is put into the + // instruction. + Inserted = DAG.getNode(ISD::SRA, DL, MVT::i32, Inserted, + DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL)); + + SDValue Ops[] = {Base, Inserted, DAG.getConstant(Width, DL, MVT::i32), + DAG.getConstant(ShAmt, DL, MVT::i32)}; + return DAG.getNode(RISCVISD::QC_INSB, DL, MVT::i32, Ops); +} + static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget) { SelectionDAG &DAG = DCI.DAG; @@ -16137,6 +16175,9 @@ static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, } } + if (SDValue V = combineXorToBitfieldInsert(N, DAG, Subtarget)) + return V; + if (SDValue V = combineBinOpToReduce(N, DAG, Subtarget)) return V; if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget)) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td index 2c64b0c220fba..dc58f1e2c0d61 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td @@ -22,6 +22,13 @@ def SDT_SetMultiple : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, def qc_setwmi : RVSDNode<"QC_SETWMI", SDT_SetMultiple, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def qc_insb : RVSDNode<"QC_INSB", SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, + SDTCisVT<0, i32>, + SDTCisInt<3>, + SDTCisInt<4>]>, + []>; + def uimm5nonzero : RISCVOp, ImmLeaf(Imm);}]> { let ParserMatchClass = UImmAsmOperand<5, "NonZero">; @@ -1508,6 +1515,11 @@ def : Pat<(i32 (and GPRNoX0:$rs, 1023)), (QC_EXTU GPRNoX0:$rs, 10, 0)>; def : Pat<(i32 (and GPRNoX0:$rs, 2047)), (QC_EXTU GPRNoX0:$rs, 11, 0)>; def : Pat<(i32 (bitreverse GPRNoX0:$rs1)), (QC_BREV32 GPRNoX0:$rs1)>; + +def : Pat<(qc_insb GPRNoX0:$rd, simm5:$imm5, uimm5_plus1:$width, uimm5:$shamt), + (QC_INSBI GPRNoX0:$rd, simm5:$imm5, uimm5_plus1:$width, uimm5:$shamt)>; +def : Pat<(qc_insb GPRNoX0:$rd, GPR:$rs1, uimm5_plus1:$width, uimm5:$shamt), + (QC_INSB GPRNoX0:$rd, GPR:$rs1, uimm5_plus1:$width, uimm5:$shamt)>; } // Predicates = [HasVendorXqcibm, IsRV32] // If Zbb is enabled sext.b/h is preferred since they are compressible diff --git a/llvm/test/CodeGen/RISCV/xqcibm-insbi.ll b/llvm/test/CodeGen/RISCV/xqcibm-insbi.ll index e4a545169d210..3f9fe88d96701 100644 --- a/llvm/test/CodeGen/RISCV/xqcibm-insbi.ll +++ b/llvm/test/CodeGen/RISCV/xqcibm-insbi.ll @@ -4,259 +4,169 @@ ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibm --verify-machineinstrs < %s \ ; RUN: | FileCheck %s -check-prefixes=RV32XQCIBM -define i32 @insbi(i32 %in1) nounwind { -; RV32I-LABEL: insbi: +define i32 @insb(i32 %in1, i32 %in2) { +; RV32I-LABEL: insb: ; RV32I: # %bb.0: -; RV32I-NEXT: xori a1, a0, 176 -; RV32I-NEXT: andi a1, a1, 496 -; RV32I-NEXT: xor a0, a1, a0 -; RV32I-NEXT: ret -; -; RV32XQCIBM-LABEL: insbi: -; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: qc.insbi a0, 11, 5, 4 -; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, 176 - %and1 = and i32 %xor1, 496 - %xor2 = xor i32 %and1, %in1 - ret i32 %xor2 -} - -define i32 @insbi_comm_xor(i32 %in1) nounwind { -; RV32I-LABEL: insbi_comm_xor: -; RV32I: # %bb.0: -; RV32I-NEXT: li a1, 9 -; RV32I-NEXT: li a2, 15 -; RV32I-NEXT: slli a1, a1, 9 -; RV32I-NEXT: xor a1, a0, a1 -; RV32I-NEXT: slli a2, a2, 9 -; RV32I-NEXT: and a1, a1, a2 -; RV32I-NEXT: xor a0, a1, a0 -; RV32I-NEXT: ret -; -; RV32XQCIBM-LABEL: insbi_comm_xor: -; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: qc.insbi a0, 9, 4, 9 -; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 4608, %in1 - %and1 = and i32 %xor1, 7680 - %xor2 = xor i32 %and1, %in1 - ret i32 %xor2 -} - -define i32 @insbi_comm_and(i32 %in1) nounwind { -; RV32I-LABEL: insbi_comm_and: -; RV32I: # %bb.0: -; RV32I-NEXT: li a1, 11 -; RV32I-NEXT: li a2, 15 -; RV32I-NEXT: slli a1, a1, 9 -; RV32I-NEXT: xor a1, a0, a1 -; RV32I-NEXT: slli a2, a2, 9 -; RV32I-NEXT: and a1, a1, a2 -; RV32I-NEXT: xor a0, a1, a0 -; RV32I-NEXT: ret -; -; RV32XQCIBM-LABEL: insbi_comm_and: -; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: qc.insbi a0, 11, 4, 9 -; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, 5632 - %and1 = and i32 7680, %xor1 - %xor2 = xor i32 %and1, %in1 - ret i32 %xor2 -} - -define i32 @insbi_comm_xor2(i32 %in1) nounwind { -; RV32I-LABEL: insbi_comm_xor2: -; RV32I: # %bb.0: -; RV32I-NEXT: xori a1, a0, 176 -; RV32I-NEXT: andi a1, a1, 496 +; RV32I-NEXT: slli a1, a1, 1 +; RV32I-NEXT: andi a2, a0, -2 +; RV32I-NEXT: xor a1, a1, a2 ; RV32I-NEXT: xor a0, a0, a1 ; RV32I-NEXT: ret ; -; RV32XQCIBM-LABEL: insbi_comm_xor2: +; RV32XQCIBM-LABEL: insb: ; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: qc.insbi a0, 11, 5, 4 -; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, 176 - %and1 = and i32 %xor1, 496 - %xor2 = xor i32 %in1, %and1 - ret i32 %xor2 -} - -define i32 @insbi_immg(i32 %in1) nounwind { -; RV32I-LABEL: insbi_immg: -; RV32I: # %bb.0: -; RV32I-NEXT: xori a1, a0, 256 -; RV32I-NEXT: andi a1, a1, 496 -; RV32I-NEXT: xor a0, a1, a0 -; RV32I-NEXT: ret -; -; RV32XQCIBM-LABEL: insbi_immg: -; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: li a1, 16 -; RV32XQCIBM-NEXT: qc.insb a0, a1, 5, 4 +; RV32XQCIBM-NEXT: qc.ext a1, a1, 31, 0 +; RV32XQCIBM-NEXT: qc.insb a0, a1, 31, 1 ; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, 256 - %and1 = and i32 %xor1, 496 - %xor2 = xor i32 %and1, %in1 + %shl1 = shl i32 %in2, 1 + %in1.masked = and i32 %in1, -2 + %xor1 = xor i32 %shl1, %in1.masked + %xor2 = xor i32 %in1, %xor1 ret i32 %xor2 } -define i32 @insbi_not_shifted_mask(i32 %in1) nounwind { -; RV32I-LABEL: insbi_not_shifted_mask: +define i32 @insb_and_multiple(i32 %in1, i32 %in2) { +; RV32I-LABEL: insb_and_multiple: ; RV32I: # %bb.0: -; RV32I-NEXT: xori a1, a0, 128 -; RV32I-NEXT: andi a1, a1, 716 -; RV32I-NEXT: xor a0, a1, a0 +; RV32I-NEXT: slli a1, a1, 1 +; RV32I-NEXT: andi a2, a0, -2 +; RV32I-NEXT: xor a1, a1, a2 +; RV32I-NEXT: xor a0, a0, a1 +; RV32I-NEXT: add a0, a0, a2 ; RV32I-NEXT: ret ; -; RV32XQCIBM-LABEL: insbi_not_shifted_mask: +; RV32XQCIBM-LABEL: insb_and_multiple: ; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: xori a1, a0, 128 -; RV32XQCIBM-NEXT: andi a1, a1, 716 +; RV32XQCIBM-NEXT: slli a1, a1, 1 +; RV32XQCIBM-NEXT: andi a2, a0, -2 +; RV32XQCIBM-NEXT: xor a1, a1, a2 ; RV32XQCIBM-NEXT: xor a0, a0, a1 +; RV32XQCIBM-NEXT: add a0, a0, a2 ; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, 176 - %and1 = and i32 %xor1, 716 - %xor2 = xor i32 %and1, %in1 - ret i32 %xor2 + %shl1 = shl i32 %in2, 1 + %in1.masked = and i32 %in1, -2 + %xor1 = xor i32 %shl1, %in1.masked + %xor2 = xor i32 %in1, %xor1 + %add1 = add i32 %xor2, %in1.masked + ret i32 %add1 } -define i32 @insbi_width_z(i32 %in1) nounwind { -; RV32I-LABEL: insbi_width_z: +define i32 @insb_xor_multiple(i32 %in1, i32 %in2) { +; RV32I-LABEL: insb_xor_multiple: ; RV32I: # %bb.0: -; RV32I-NEXT: andi a1, a0, 256 -; RV32I-NEXT: xor a0, a1, a0 +; RV32I-NEXT: slli a1, a1, 1 +; RV32I-NEXT: andi a2, a0, -2 +; RV32I-NEXT: xor a1, a1, a2 +; RV32I-NEXT: xor a0, a0, a1 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: ret ; -; RV32XQCIBM-LABEL: insbi_width_z: +; RV32XQCIBM-LABEL: insb_xor_multiple: ; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: andi a1, a0, 256 +; RV32XQCIBM-NEXT: slli a1, a1, 1 +; RV32XQCIBM-NEXT: andi a2, a0, -2 +; RV32XQCIBM-NEXT: xor a1, a1, a2 ; RV32XQCIBM-NEXT: xor a0, a0, a1 +; RV32XQCIBM-NEXT: add a0, a0, a1 ; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, 176 - %and1 = and i32 %xor1, 256 - %xor2 = xor i32 %and1, %in1 - ret i32 %xor2 + %shl1 = shl i32 %in2, 1 + %in1.masked = and i32 %in1, -2 + %xor1 = xor i32 %shl1, %in1.masked + %xor2 = xor i32 %in1, %xor1 + %add1 = add i32 %xor2, %xor1 + ret i32 %add1 } -define i32 @insbi_mul_use_and(i32 %in1, i32 %in2) nounwind { -; RV32I-LABEL: insbi_mul_use_and: +define i32 @insb_shl_multiple(i32 %in1, i32 %in2) { +; RV32I-LABEL: insb_shl_multiple: ; RV32I: # %bb.0: -; RV32I-NEXT: li a1, 11 -; RV32I-NEXT: li a2, 15 -; RV32I-NEXT: slli a1, a1, 9 -; RV32I-NEXT: slli a2, a2, 9 -; RV32I-NEXT: xor a1, a0, a1 -; RV32I-NEXT: and a1, a1, a2 -; RV32I-NEXT: xor a2, a1, a0 +; RV32I-NEXT: slli a1, a1, 1 +; RV32I-NEXT: andi a2, a0, -2 +; RV32I-NEXT: xor a2, a1, a2 +; RV32I-NEXT: xor a0, a0, a2 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: add a0, a0, a2 ; RV32I-NEXT: ret ; -; RV32XQCIBM-LABEL: insbi_mul_use_and: +; RV32XQCIBM-LABEL: insb_shl_multiple: ; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: li a1, 11 -; RV32XQCIBM-NEXT: li a2, 15 -; RV32XQCIBM-NEXT: slli a1, a1, 9 -; RV32XQCIBM-NEXT: slli a2, a2, 9 -; RV32XQCIBM-NEXT: xor a1, a1, a0 -; RV32XQCIBM-NEXT: and a1, a1, a2 -; RV32XQCIBM-NEXT: xor a2, a1, a0 +; RV32XQCIBM-NEXT: slli a1, a1, 1 +; RV32XQCIBM-NEXT: srai a2, a1, 1 +; RV32XQCIBM-NEXT: qc.insb a0, a2, 31, 1 ; RV32XQCIBM-NEXT: add a0, a0, a1 -; RV32XQCIBM-NEXT: add a0, a0, a2 ; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, 5632 - %and1 = and i32 %xor1, 7680 - %xor2 = xor i32 %and1, %in1 - %add1 = add i32 %in1, %and1 - %add2 = add i32 %add1, %xor2 - ret i32 %add2 + %shl1 = shl i32 %in2, 1 + %in1.masked = and i32 %in1, -2 + %and1 = xor i32 %shl1, %in1.masked + %xor2 = xor i32 %in1, %and1 + %add1 = add i32 %xor2, %shl1 + ret i32 %add1 } -define i32 @insbi_mul_use_xor(i32 %in1, i32 %in2) nounwind { -; RV32I-LABEL: insbi_mul_use_xor: +define i32 @insb_comm(i32 %in1, i32 %in2) { +; RV32I-LABEL: insb_comm: ; RV32I: # %bb.0: -; RV32I-NEXT: xori a1, a0, 176 -; RV32I-NEXT: andi a2, a1, 496 -; RV32I-NEXT: xor a2, a2, a0 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: add a0, a0, a2 +; RV32I-NEXT: slli a1, a1, 1 +; RV32I-NEXT: andi a2, a0, -2 +; RV32I-NEXT: xor a1, a2, a1 +; RV32I-NEXT: xor a0, a0, a1 ; RV32I-NEXT: ret ; -; RV32XQCIBM-LABEL: insbi_mul_use_xor: +; RV32XQCIBM-LABEL: insb_comm: ; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: xori a1, a0, 176 -; RV32XQCIBM-NEXT: andi a2, a1, 496 -; RV32XQCIBM-NEXT: xor a2, a2, a0 -; RV32XQCIBM-NEXT: add a0, a0, a1 -; RV32XQCIBM-NEXT: add a0, a0, a2 +; RV32XQCIBM-NEXT: qc.ext a1, a1, 31, 0 +; RV32XQCIBM-NEXT: qc.insb a0, a1, 31, 1 ; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, 176 - %and1 = and i32 %xor1, 496 - %xor2 = xor i32 %and1, %in1 - %add1 = add i32 %in1, %xor1 - %add2 = add i32 %add1, %xor2 - ret i32 %add2 + %shl1 = shl i32 %in2, 1 + %in1.masked = and i32 %in1, -2 + %xor1 = xor i32 %in1.masked, %shl1 + %xor2 = xor i32 %in1, %xor1 + ret i32 %xor2 } -define i32 @insbi_imm_too_neg(i32 %in1) nounwind { -; RV32I-LABEL: insbi_imm_too_neg: +define i32 @insb_comm1(i32 %in1, i32 %in2) { +; RV32I-LABEL: insb_comm1: ; RV32I: # %bb.0: -; RV32I-NEXT: xori a1, a0, -34 -; RV32I-NEXT: andi a1, a1, -2 +; RV32I-NEXT: slli a1, a1, 1 +; RV32I-NEXT: andi a2, a0, -2 +; RV32I-NEXT: xor a1, a2, a1 ; RV32I-NEXT: xor a0, a1, a0 ; RV32I-NEXT: ret ; -; RV32XQCIBM-LABEL: insbi_imm_too_neg: +; RV32XQCIBM-LABEL: insb_comm1: ; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: li a1, -17 +; RV32XQCIBM-NEXT: qc.ext a1, a1, 31, 0 ; RV32XQCIBM-NEXT: qc.insb a0, a1, 31, 1 ; RV32XQCIBM-NEXT: ret - %xor1 = xor i32 %in1, -34 - %and1 = and i32 %xor1, -2 - %xor2 = xor i32 %and1, %in1 + %shl1 = shl i32 %in2, 1 + %in1.masked = and i32 %in1, -2 + %xor1 = xor i32 %in1.masked, %shl1 + %xor2 = xor i32 %xor1, %in1 ret i32 %xor2 } -define i64 @insbi_i64(i64 %in1) nounwind { -; RV32I-LABEL: insbi_i64: +define i64 @insb_i64(i64 %in1, i64 %in2) { +; RV32I-LABEL: insb_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: lui a2, 57344 -; RV32I-NEXT: lui a3, 1044480 -; RV32I-NEXT: xor a2, a0, a2 -; RV32I-NEXT: and a2, a2, a3 -; RV32I-NEXT: zext.b a3, a1 -; RV32I-NEXT: xor a1, a3, a1 +; RV32I-NEXT: srli a1, a2, 31 +; RV32I-NEXT: slli a3, a3, 1 +; RV32I-NEXT: slli a2, a2, 1 +; RV32I-NEXT: or a1, a3, a1 +; RV32I-NEXT: andi a3, a0, -2 +; RV32I-NEXT: xor a2, a3, a2 ; RV32I-NEXT: xor a0, a2, a0 ; RV32I-NEXT: ret ; -; RV32XQCIBM-LABEL: insbi_i64: -; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: qc.extu a2, a1, 8, 0 -; RV32XQCIBM-NEXT: xor a1, a1, a2 -; RV32XQCIBM-NEXT: qc.insbi a0, 14, 8, 24 -; RV32XQCIBM-NEXT: ret - %xor1 = xor i64 %in1, 234881024 - %and1 = and i64 %xor1, 1099494850560 - %xor2 = xor i64 %and1, %in1 - ret i64 %xor2 -} -define i64 @insbi_i64_large_mask(i64 %in1) nounwind { -; RV32I-LABEL: insbi_i64_large_mask: -; RV32I: # %bb.0: -; RV32I-NEXT: xori a2, a1, 9 -; RV32I-NEXT: andi a2, a2, 15 -; RV32I-NEXT: xor a1, a2, a1 -; RV32I-NEXT: ret -; -; RV32XQCIBM-LABEL: insbi_i64_large_mask: +; RV32XQCIBM-LABEL: insb_i64: ; RV32XQCIBM: # %bb.0: -; RV32XQCIBM-NEXT: qc.insbi a1, 9, 4, 0 +; RV32XQCIBM-NEXT: srli a1, a2, 31 +; RV32XQCIBM-NEXT: slli a3, a3, 1 +; RV32XQCIBM-NEXT: qc.ext a2, a2, 31, 0 +; RV32XQCIBM-NEXT: or a1, a1, a3 +; RV32XQCIBM-NEXT: qc.insb a0, a2, 31, 1 ; RV32XQCIBM-NEXT: ret - %xor1 = xor i64 %in1, 38654705664 - %and1 = and i64 %xor1, 64424509440 - %xor2 = xor i64 %and1, %in1 + %shl1 = shl i64 %in2, 1 + %in1.masked = and i64 %in1, -2 + %xor1 = xor i64 %in1.masked, %shl1 + %xor2 = xor i64 %xor1, %in1 ret i64 %xor2 }