Skip to content

Commit 0ae1506

Browse files
authored
[RISCV] Add ISel patterns for Xqciac QC_SHLADD instruction (#148256)
Add a couple of patterns to generate the Xqciac QC_SHLADD shift left and add immediate instruction.
1 parent 6c2e26a commit 0ae1506

File tree

4 files changed

+224
-10
lines changed

4 files changed

+224
-10
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15032,10 +15032,15 @@ static SDValue combineBinOpToReduce(SDNode *N, SelectionDAG &DAG,
1503215032

1503315033
// Optimize (add (shl x, c0), (shl y, c1)) ->
1503415034
// (SLLI (SH*ADD x, y), c0), if c1-c0 equals to [1|2|3].
15035+
// or
15036+
// (SLLI (QC.SHLADD x, y, c1 - c0), c0), if 4 <= (c1-c0) <=31.
1503515037
static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
1503615038
const RISCVSubtarget &Subtarget) {
15037-
// Perform this optimization only in the zba/xandesperf extension.
15038-
if (!Subtarget.hasStdExtZba() && !Subtarget.hasVendorXAndesPerf())
15039+
const bool HasStdExtZba = Subtarget.hasStdExtZba();
15040+
const bool HasVendorXAndesPerf = Subtarget.hasVendorXAndesPerf();
15041+
const bool HasVendorXqciac = Subtarget.hasVendorXqciac();
15042+
// Perform this optimization only in the zba/xandesperf/xqciac extension.
15043+
if (!HasStdExtZba && !HasVendorXAndesPerf && !HasVendorXqciac)
1503915044
return SDValue();
1504015045

1504115046
// Skip for vector types and larger types.
@@ -15060,14 +15065,22 @@ static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
1506015065
if (C0 <= 0 || C1 <= 0)
1506115066
return SDValue();
1506215067

15063-
// Skip if SH1ADD/SH2ADD/SH3ADD are not applicable.
15064-
int64_t Bits = std::min(C0, C1);
1506515068
int64_t Diff = std::abs(C0 - C1);
15066-
if (Diff != 1 && Diff != 2 && Diff != 3)
15069+
bool IsShXaddDiff = Diff == 1 || Diff == 2 || Diff == 3;
15070+
bool HasShXadd = HasStdExtZba || HasVendorXAndesPerf;
15071+
15072+
// Skip if SH1ADD/SH2ADD/SH3ADD are not applicable.
15073+
if ((!IsShXaddDiff && HasShXadd && !HasVendorXqciac) ||
15074+
(IsShXaddDiff && !HasShXadd && HasVendorXqciac))
15075+
return SDValue();
15076+
15077+
// Skip if QC_SHLADD is not applicable.
15078+
if (Diff == 0 || Diff > 31)
1506715079
return SDValue();
1506815080

1506915081
// Build nodes.
1507015082
SDLoc DL(N);
15083+
int64_t Bits = std::min(C0, C1);
1507115084
SDValue NS = (C0 < C1) ? N0->getOperand(0) : N1->getOperand(0);
1507215085
SDValue NL = (C0 > C1) ? N0->getOperand(0) : N1->getOperand(0);
1507315086
SDValue SHADD = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, NL,

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,6 +2823,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
28232823
case RISCVOp::OPERAND_UIMM5_NONZERO:
28242824
Ok = isUInt<5>(Imm) && (Imm != 0);
28252825
break;
2826+
case RISCVOp::OPERAND_UIMM5_GT3:
2827+
Ok = isUInt<5>(Imm) && (Imm > 3);
2828+
break;
28262829
case RISCVOp::OPERAND_UIMM5_PLUS1:
28272830
Ok = (isUInt<5>(Imm) && (Imm != 0)) || (Imm == 32);
28282831
break;

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,10 @@ class SelectQCbi<CondCode Cond, DAGOperand InTyImm, Pseudo OpNode >
13591359
let Predicates = [HasVendorXqciac, IsRV32] in {
13601360
def : Pat<(i32 (add GPRNoX0:$rd, (mul GPRNoX0:$rs1, simm12:$imm12))),
13611361
(QC_MULIADD GPRNoX0:$rd, GPRNoX0:$rs1, simm12:$imm12)>;
1362+
def : Pat<(i32 (add_like_non_imm12 (shl GPRNoX0:$rs1, uimm5gt3:$imm), GPRNoX0:$rs2)),
1363+
(QC_SHLADD GPRNoX0:$rs2, GPRNoX0:$rs1, uimm5gt3:$imm)>;
1364+
def : Pat<(i32 (riscv_shl_add GPRNoX0:$rs1, uimm5gt3:$imm, GPRNoX0:$rs2)),
1365+
(QC_SHLADD GPRNoX0:$rs2, GPRNoX0:$rs1, uimm5gt3:$imm)>;
13621366
} // Predicates = [HasVendorXqciac, IsRV32]
13631367

13641368
/// Simple arithmetic operations

llvm/test/CodeGen/RISCV/xqciac.ll

Lines changed: 199 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ entry:
222222
ret i32 %add
223223
}
224224

225-
; NOTE: This will become qc.shladd once support is added
226225
define dso_local i32 @pow2(i32 %a, i32 %b) local_unnamed_addr #0 {
227226
; RV32IM-LABEL: pow2:
228227
; RV32IM: # %bb.0: # %entry
@@ -232,14 +231,12 @@ define dso_local i32 @pow2(i32 %a, i32 %b) local_unnamed_addr #0 {
232231
;
233232
; RV32IMXQCIAC-LABEL: pow2:
234233
; RV32IMXQCIAC: # %bb.0: # %entry
235-
; RV32IMXQCIAC-NEXT: slli a1, a1, 5
236-
; RV32IMXQCIAC-NEXT: add a0, a0, a1
234+
; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5
237235
; RV32IMXQCIAC-NEXT: ret
238236
;
239237
; RV32IZBAMXQCIAC-LABEL: pow2:
240238
; RV32IZBAMXQCIAC: # %bb.0: # %entry
241-
; RV32IZBAMXQCIAC-NEXT: slli a1, a1, 5
242-
; RV32IZBAMXQCIAC-NEXT: add a0, a0, a1
239+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5
243240
; RV32IZBAMXQCIAC-NEXT: ret
244241
entry:
245242
%mul = mul nsw i32 %b, 32
@@ -269,3 +266,200 @@ entry:
269266
%add = add nsw i32 %mul, %a
270267
ret i32 %add
271268
}
269+
270+
define dso_local i32 @shladd(i32 %a, i32 %b) local_unnamed_addr #0 {
271+
; RV32IM-LABEL: shladd:
272+
; RV32IM: # %bb.0: # %entry
273+
; RV32IM-NEXT: slli a1, a1, 31
274+
; RV32IM-NEXT: add a0, a1, a0
275+
; RV32IM-NEXT: ret
276+
;
277+
; RV32IMXQCIAC-LABEL: shladd:
278+
; RV32IMXQCIAC: # %bb.0: # %entry
279+
; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 31
280+
; RV32IMXQCIAC-NEXT: ret
281+
;
282+
; RV32IZBAMXQCIAC-LABEL: shladd:
283+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
284+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 31
285+
; RV32IZBAMXQCIAC-NEXT: ret
286+
entry:
287+
%shl = shl nsw i32 %b, 31
288+
%add = add nsw i32 %shl, %a
289+
ret i32 %add
290+
}
291+
292+
define dso_local i64 @shladd64(i64 %a, i64 %b) local_unnamed_addr #0 {
293+
; RV32IM-LABEL: shladd64:
294+
; RV32IM: # %bb.0: # %entry
295+
; RV32IM-NEXT: srli a4, a2, 1
296+
; RV32IM-NEXT: slli a3, a3, 31
297+
; RV32IM-NEXT: slli a2, a2, 31
298+
; RV32IM-NEXT: or a3, a3, a4
299+
; RV32IM-NEXT: add a0, a2, a0
300+
; RV32IM-NEXT: sltu a2, a0, a2
301+
; RV32IM-NEXT: add a1, a3, a1
302+
; RV32IM-NEXT: add a1, a1, a2
303+
; RV32IM-NEXT: ret
304+
;
305+
; RV32IMXQCIAC-LABEL: shladd64:
306+
; RV32IMXQCIAC: # %bb.0: # %entry
307+
; RV32IMXQCIAC-NEXT: srli a4, a2, 1
308+
; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a2, 31
309+
; RV32IMXQCIAC-NEXT: slli a2, a2, 31
310+
; RV32IMXQCIAC-NEXT: qc.shladd a3, a4, a3, 31
311+
; RV32IMXQCIAC-NEXT: sltu a2, a0, a2
312+
; RV32IMXQCIAC-NEXT: add a1, a1, a3
313+
; RV32IMXQCIAC-NEXT: add a1, a1, a2
314+
; RV32IMXQCIAC-NEXT: ret
315+
;
316+
; RV32IZBAMXQCIAC-LABEL: shladd64:
317+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
318+
; RV32IZBAMXQCIAC-NEXT: srli a4, a2, 1
319+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a2, 31
320+
; RV32IZBAMXQCIAC-NEXT: slli a2, a2, 31
321+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a3, a4, a3, 31
322+
; RV32IZBAMXQCIAC-NEXT: sltu a2, a0, a2
323+
; RV32IZBAMXQCIAC-NEXT: add a1, a1, a3
324+
; RV32IZBAMXQCIAC-NEXT: add a1, a1, a2
325+
; RV32IZBAMXQCIAC-NEXT: ret
326+
entry:
327+
%shl = shl nsw i64 %b, 31
328+
%add = add nsw i64 %shl, %a
329+
ret i64 %add
330+
}
331+
332+
define dso_local i32 @shladd_ordisjoint(i32 %a, i32 %b) local_unnamed_addr #0 {
333+
; RV32IM-LABEL: shladd_ordisjoint:
334+
; RV32IM: # %bb.0: # %entry
335+
; RV32IM-NEXT: slli a1, a1, 22
336+
; RV32IM-NEXT: or a0, a1, a0
337+
; RV32IM-NEXT: ret
338+
;
339+
; RV32IMXQCIAC-LABEL: shladd_ordisjoint:
340+
; RV32IMXQCIAC: # %bb.0: # %entry
341+
; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 22
342+
; RV32IMXQCIAC-NEXT: ret
343+
;
344+
; RV32IZBAMXQCIAC-LABEL: shladd_ordisjoint:
345+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
346+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 22
347+
; RV32IZBAMXQCIAC-NEXT: ret
348+
entry:
349+
%shl = shl nsw i32 %b, 22
350+
%or = or disjoint i32 %shl, %a
351+
ret i32 %or
352+
}
353+
354+
define dso_local i32 @shladdc1c2(i32 %a, i32 %b) local_unnamed_addr #0 {
355+
; RV32IM-LABEL: shladdc1c2:
356+
; RV32IM: # %bb.0: # %entry
357+
; RV32IM-NEXT: slli a0, a0, 31
358+
; RV32IM-NEXT: slli a1, a1, 26
359+
; RV32IM-NEXT: add a0, a0, a1
360+
; RV32IM-NEXT: ret
361+
;
362+
; RV32IMXQCIAC-LABEL: shladdc1c2:
363+
; RV32IMXQCIAC: # %bb.0: # %entry
364+
; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5
365+
; RV32IMXQCIAC-NEXT: slli a0, a0, 26
366+
; RV32IMXQCIAC-NEXT: ret
367+
;
368+
; RV32IZBAMXQCIAC-LABEL: shladdc1c2:
369+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
370+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5
371+
; RV32IZBAMXQCIAC-NEXT: slli a0, a0, 26
372+
; RV32IZBAMXQCIAC-NEXT: ret
373+
entry:
374+
%shlc1 = shl nsw i32 %a, 31
375+
%shlc2 = shl nsw i32 %b, 26
376+
%add = add nsw i32 %shlc1, %shlc2
377+
ret i32 %add
378+
}
379+
380+
define dso_local i32 @shxaddc1c2(i32 %a, i32 %b) local_unnamed_addr #0 {
381+
; RV32IM-LABEL: shxaddc1c2:
382+
; RV32IM: # %bb.0: # %entry
383+
; RV32IM-NEXT: slli a0, a0, 31
384+
; RV32IM-NEXT: slli a1, a1, 28
385+
; RV32IM-NEXT: add a0, a0, a1
386+
; RV32IM-NEXT: ret
387+
;
388+
; RV32IMXQCIAC-LABEL: shxaddc1c2:
389+
; RV32IMXQCIAC: # %bb.0: # %entry
390+
; RV32IMXQCIAC-NEXT: slli a1, a1, 28
391+
; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31
392+
; RV32IMXQCIAC-NEXT: ret
393+
;
394+
; RV32IZBAMXQCIAC-LABEL: shxaddc1c2:
395+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
396+
; RV32IZBAMXQCIAC-NEXT: sh3add a0, a0, a1
397+
; RV32IZBAMXQCIAC-NEXT: slli a0, a0, 28
398+
; RV32IZBAMXQCIAC-NEXT: ret
399+
entry:
400+
%shlc1 = shl nsw i32 %a, 31
401+
%shlc2 = shl nsw i32 %b, 28
402+
%add = add nsw i32 %shlc1, %shlc2
403+
ret i32 %add
404+
}
405+
406+
define dso_local i64 @shladdc1c264(i64 %a, i64 %b) local_unnamed_addr #0 {
407+
; RV32IM-LABEL: shladdc1c264:
408+
; RV32IM: # %bb.0: # %entry
409+
; RV32IM-NEXT: slli a1, a0, 23
410+
; RV32IM-NEXT: srli a0, a2, 12
411+
; RV32IM-NEXT: slli a3, a3, 20
412+
; RV32IM-NEXT: or a3, a3, a0
413+
; RV32IM-NEXT: slli a0, a2, 20
414+
; RV32IM-NEXT: add a1, a1, a3
415+
; RV32IM-NEXT: ret
416+
;
417+
; RV32IMXQCIAC-LABEL: shladdc1c264:
418+
; RV32IMXQCIAC: # %bb.0: # %entry
419+
; RV32IMXQCIAC-NEXT: srli a1, a2, 12
420+
; RV32IMXQCIAC-NEXT: qc.shladd a1, a1, a3, 20
421+
; RV32IMXQCIAC-NEXT: slli a2, a2, 20
422+
; RV32IMXQCIAC-NEXT: qc.shladd a1, a1, a0, 23
423+
; RV32IMXQCIAC-NEXT: mv a0, a2
424+
; RV32IMXQCIAC-NEXT: ret
425+
;
426+
; RV32IZBAMXQCIAC-LABEL: shladdc1c264:
427+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
428+
; RV32IZBAMXQCIAC-NEXT: srli a1, a2, 12
429+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a1, a3, 20
430+
; RV32IZBAMXQCIAC-NEXT: slli a2, a2, 20
431+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a1, a0, 23
432+
; RV32IZBAMXQCIAC-NEXT: mv a0, a2
433+
; RV32IZBAMXQCIAC-NEXT: ret
434+
entry:
435+
%shlc1 = shl nsw i64 %a, 55
436+
%shlc2 = shl nsw i64 %b, 20
437+
%add = add nsw i64 %shlc1, %shlc2
438+
ret i64 %add
439+
}
440+
441+
define dso_local i32 @shladdc1equalc2(i32 %a, i32 %b) local_unnamed_addr #0 {
442+
; RV32IM-LABEL: shladdc1equalc2:
443+
; RV32IM: # %bb.0: # %entry
444+
; RV32IM-NEXT: slli a0, a0, 12
445+
; RV32IM-NEXT: slli a1, a1, 12
446+
; RV32IM-NEXT: add a0, a0, a1
447+
; RV32IM-NEXT: ret
448+
;
449+
; RV32IMXQCIAC-LABEL: shladdc1equalc2:
450+
; RV32IMXQCIAC: # %bb.0: # %entry
451+
; RV32IMXQCIAC-NEXT: slli a1, a1, 12
452+
; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 12
453+
; RV32IMXQCIAC-NEXT: ret
454+
;
455+
; RV32IZBAMXQCIAC-LABEL: shladdc1equalc2:
456+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
457+
; RV32IZBAMXQCIAC-NEXT: slli a1, a1, 12
458+
; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 12
459+
; RV32IZBAMXQCIAC-NEXT: ret
460+
entry:
461+
%shlc1 = shl nsw i32 %a, 12
462+
%shlc2 = shl nsw i32 %b, 12
463+
%add = add nsw i32 %shlc1, %shlc2
464+
ret i32 %add
465+
}

0 commit comments

Comments
 (0)