[llvm] d036381 - [RISCV] Add changes to have better coverage for qc.insb and qc.insbi (#154135)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 3 00:05:42 PDT 2025
Author: quic_hchandel
Date: 2025-09-03T12:35:38+05:30
New Revision: d0363815dd4acde08168e930cb529ee10f86b838
URL: https://github.com/llvm/llvm-project/commit/d0363815dd4acde08168e930cb529ee10f86b838
DIFF: https://github.com/llvm/llvm-project/commit/d0363815dd4acde08168e930cb529ee10f86b838.diff
LOG: [RISCV] Add changes to have better coverage for qc.insb and qc.insbi (#154135)
Before this patch, the selection for `QC_INSB` and `QC_INSBI` entirely
happens in C++, and does not support more than one non-constant input.
This patch seeks to rectify this shortcoming, by moving the C++ into a
target-specific DAGCombine, and adding `RISCV::QC_INSB`. One advantage
is this simplifies the code for handling `QC_INSBI`, as the C++ no
longer needs to choose between the two instructions based on the
inserted value (this is still done, but via ISel Patterns).
Another advantage of the DAGCombine is that this introduction can also
shift the inserted value to the `QC_INSB`, which our patterns need (and
were previously doing to the constant), and this shift can be
CSE'd/optimised with any prior shifts, if they exist. This allows the
inserted value to be variable, rather than a constant.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
llvm/test/CodeGen/RISCV/xqcibm-insbi.ll
Removed:
################################################################################
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<ConstantSDNode>(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 5aef6fbff54fe..327de613b6ccb 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -16156,6 +16156,48 @@ 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();
+
+ // Check if all zero bits in CMask are also zero in Inserted
+ if (!DAG.MaskedValueIsZero(Inserted, ~CMask))
+ 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;
@@ -16228,6 +16270,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 31ea1b4c70a14..f1ac093117f30 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<XLenVT>,
ImmLeaf<XLenVT, [{return (Imm != 0) && isUInt<5>(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..54eab0de0465e 100644
--- a/llvm/test/CodeGen/RISCV/xqcibm-insbi.ll
+++ b/llvm/test/CodeGen/RISCV/xqcibm-insbi.ll
@@ -4,259 +4,190 @@
; 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-LABEL: insb_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: 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, 234881024
- %and1 = and i64 %xor1, 1099494850560
- %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
}
-define i64 @insbi_i64_large_mask(i64 %in1) nounwind {
-; RV32I-LABEL: insbi_i64_large_mask:
+
+define i8 @tgt2_insb_neg(i8 %x, i8 %y) {
+; RV32I-LABEL: tgt2_insb_neg:
; RV32I: # %bb.0:
-; RV32I-NEXT: xori a2, a1, 9
-; RV32I-NEXT: andi a2, a2, 15
-; RV32I-NEXT: xor a1, a2, a1
+; RV32I-NEXT: andi a2, a0, -2
+; RV32I-NEXT: xor a0, a0, a1
+; RV32I-NEXT: xor a0, a0, a2
; RV32I-NEXT: ret
;
-; RV32XQCIBM-LABEL: insbi_i64_large_mask:
+; RV32XQCIBM-LABEL: tgt2_insb_neg:
; RV32XQCIBM: # %bb.0:
-; RV32XQCIBM-NEXT: qc.insbi a1, 9, 4, 0
+; RV32XQCIBM-NEXT: andi a2, a0, -2
+; RV32XQCIBM-NEXT: xor a0, a0, a1
+; RV32XQCIBM-NEXT: xor a0, a0, a2
; RV32XQCIBM-NEXT: ret
- %xor1 = xor i64 %in1, 38654705664
- %and1 = and i64 %xor1, 64424509440
- %xor2 = xor i64 %and1, %in1
- ret i64 %xor2
+ %and = and i8 %x, -2
+ %xor1 = xor i8 %and, %y
+ %xor2 = xor i8 %x, %xor1
+ ret i8 %xor2
}
+
More information about the llvm-commits
mailing list