Skip to content

Commit b71c9a4

Browse files
svs-quictru
authored andcommitted
[RISCV] Fix issues in ORI to QC.INSBI transformation (llvm#148809)
The transformation done in llvm#147349 was incorrect since we were not passing the input node of the `OR` instruction to the `QC.INSBI` instruction leading to the generated instruction doing the wrong thing. In order to do this we first needed to add the output register to `QC.INSBI` as being both an input and output. The code produced after the above fix will need a copy (mv) to preserve the register input to the OR instruction if it has more than one use making the transformation net neutral ( `6-byte QC.E.ORI/ORAI` vs `2-byte C.MV + 4-byte QC.INSB`I). Avoid doing the transformation if there is more than one use of the input register to the OR instruction. (cherry picked from commit d67d91a)
1 parent 49722f1 commit b71c9a4

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -689,10 +689,16 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInMask(SDNode *Node) {
689689
if (!isShiftedMask_32(C1) || isInt<12>(C1))
690690
return false;
691691

692+
// INSBI will clobber the input register in N0. Bail out if we need a copy to
693+
// preserve this value.
694+
SDValue N0 = Node->getOperand(0);
695+
if (!N0.hasOneUse())
696+
return false;
697+
692698
// If C1 is a shifted mask (but can't be formed as an ORI),
693699
// use a bitfield insert of -1.
694700
// Transform (or x, C1)
695-
// -> (qc.insbi x, width, shift)
701+
// -> (qc.insbi x, -1, width, shift)
696702
const unsigned Leading = llvm::countl_zero((uint32_t)C1);
697703
const unsigned Trailing = llvm::countr_zero((uint32_t)C1);
698704
const unsigned Width = 32 - Leading - Trailing;
@@ -705,7 +711,7 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInMask(SDNode *Node) {
705711
SDLoc DL(Node);
706712
MVT VT = Node->getSimpleValueType(0);
707713

708-
SDValue Ops[] = {CurDAG->getSignedTargetConstant(-1, DL, VT),
714+
SDValue Ops[] = {N0, CurDAG->getSignedTargetConstant(-1, DL, VT),
709715
CurDAG->getTargetConstant(Width, DL, VT),
710716
CurDAG->getTargetConstant(Trailing, DL, VT)};
711717
SDNode *BitIns = CurDAG->getMachineNode(RISCV::QC_INSBI, DL, VT, Ops);

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -845,10 +845,11 @@ let Predicates = [HasVendorXqcibi, IsRV32] in {
845845
let Predicates = [HasVendorXqcibm, IsRV32] in {
846846
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
847847
def QC_INSBRI : QCIRVInstRI<0b1, simm11, "qc.insbri">;
848-
def QC_INSBI : RVInstIBase<0b001, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
849-
(ins simm5:$imm5, uimm5_plus1:$width,
848+
def QC_INSBI : RVInstIBase<0b001, OPC_CUSTOM_0, (outs GPRNoX0:$rd_wb),
849+
(ins GPRNoX0:$rd, simm5:$imm5, uimm5_plus1:$width,
850850
uimm5:$shamt), "qc.insbi",
851851
"$rd, $imm5, $width, $shamt"> {
852+
let Constraints = "$rd = $rd_wb";
852853
bits<5> imm5;
853854
bits<5> shamt;
854855
bits<5> width;

llvm/test/CodeGen/RISCV/xqcibm-cto-clo-brev.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ define i16 @test_cttz_i16(i16 %a) nounwind {
105105
;
106106
; RV32ZBBXQCIBM-LABEL: test_cttz_i16:
107107
; RV32ZBBXQCIBM: # %bb.0:
108+
; RV32ZBBXQCIBM-NEXT: not a0, a0
108109
; RV32ZBBXQCIBM-NEXT: qc.insbi a0, -1, 1, 16
109110
; RV32ZBBXQCIBM-NEXT: ctz a0, a0
110111
; RV32ZBBXQCIBM-NEXT: ret

llvm/test/CodeGen/RISCV/xqcibm-insert.ll

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,29 @@ define i32 @test_insbi_mask(i32 %a) nounwind {
4747
ret i32 %or
4848
}
4949

50+
define i32 @test_insbi_mask_mv(i32 %a, i32 %b) nounwind {
51+
; RV32I-LABEL: test_insbi_mask_mv:
52+
; RV32I: # %bb.0:
53+
; RV32I-NEXT: lui a0, 16
54+
; RV32I-NEXT: addi a0, a0, -1
55+
; RV32I-NEXT: or a0, a1, a0
56+
; RV32I-NEXT: ret
57+
;
58+
; RV32IXQCIBM-LABEL: test_insbi_mask_mv:
59+
; RV32IXQCIBM: # %bb.0:
60+
; RV32IXQCIBM-NEXT: mv a0, a1
61+
; RV32IXQCIBM-NEXT: qc.insbi a0, -1, 16, 0
62+
; RV32IXQCIBM-NEXT: ret
63+
;
64+
; RV32IXQCIBMZBS-LABEL: test_insbi_mask_mv:
65+
; RV32IXQCIBMZBS: # %bb.0:
66+
; RV32IXQCIBMZBS-NEXT: mv a0, a1
67+
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, -1, 16, 0
68+
; RV32IXQCIBMZBS-NEXT: ret
69+
%or = or i32 %b, 65535
70+
ret i32 %or
71+
}
72+
5073
define i32 @test_insbi_shifted_mask(i32 %a) nounwind {
5174
; RV32I-LABEL: test_insbi_shifted_mask:
5275
; RV32I: # %bb.0:
@@ -67,6 +90,36 @@ define i32 @test_insbi_shifted_mask(i32 %a) nounwind {
6790
ret i32 %or
6891
}
6992

93+
define i32 @test_insbi_shifted_mask_multiple_uses(i32 %a) nounwind {
94+
; RV32I-LABEL: test_insbi_shifted_mask_multiple_uses:
95+
; RV32I: # %bb.0:
96+
; RV32I-NEXT: lui a1, 15
97+
; RV32I-NEXT: or a1, a0, a1
98+
; RV32I-NEXT: addi a0, a0, 10
99+
; RV32I-NEXT: xor a0, a1, a0
100+
; RV32I-NEXT: ret
101+
;
102+
; RV32IXQCIBM-LABEL: test_insbi_shifted_mask_multiple_uses:
103+
; RV32IXQCIBM: # %bb.0:
104+
; RV32IXQCIBM-NEXT: lui a1, 15
105+
; RV32IXQCIBM-NEXT: or a1, a1, a0
106+
; RV32IXQCIBM-NEXT: addi a0, a0, 10
107+
; RV32IXQCIBM-NEXT: xor a0, a0, a1
108+
; RV32IXQCIBM-NEXT: ret
109+
;
110+
; RV32IXQCIBMZBS-LABEL: test_insbi_shifted_mask_multiple_uses:
111+
; RV32IXQCIBMZBS: # %bb.0:
112+
; RV32IXQCIBMZBS-NEXT: lui a1, 15
113+
; RV32IXQCIBMZBS-NEXT: or a1, a1, a0
114+
; RV32IXQCIBMZBS-NEXT: addi a0, a0, 10
115+
; RV32IXQCIBMZBS-NEXT: xor a0, a0, a1
116+
; RV32IXQCIBMZBS-NEXT: ret
117+
%or = or i32 %a, 61440
118+
%add = add i32 %a, 10
119+
%xor = xor i32 %or, %add
120+
ret i32 %xor
121+
}
122+
70123
define i32 @test_single_bit_set(i32 %a) nounwind {
71124
; RV32I-LABEL: test_single_bit_set:
72125
; RV32I: # %bb.0:

0 commit comments

Comments
 (0)