Skip to content

Commit 65e0574

Browse files
authored
[RISCV] Expand mul X, C where C=2^N*(3,5,9)*(3,5,9) (#108100)
This is a three deep expression which is deeper than we've otherwise gone for multiple expansions, but I think it's reasonable to do so. This covers mul by 50, 100, and 200 which are reasonably common naturally arising numbers.
1 parent 9a9f155 commit 65e0574

File tree

2 files changed

+165
-61
lines changed

2 files changed

+165
-61
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14131,6 +14131,32 @@ static SDValue expandMul(SDNode *N, SelectionDAG &DAG,
1413114131
return DAG.getNode(ISD::SUB, DL, VT, Shift1, Shift2);
1413214132
}
1413314133

14134+
if (HasShlAdd) {
14135+
for (uint64_t Divisor : {3, 5, 9}) {
14136+
if (MulAmt % Divisor != 0)
14137+
continue;
14138+
uint64_t MulAmt2 = MulAmt / Divisor;
14139+
// 3/5/9 * 3/5/9 * 2^N - In particular, this covers multiples
14140+
// of 25 which happen to be quite common.
14141+
for (uint64_t Divisor2 : {3, 5, 9}) {
14142+
if (MulAmt2 % Divisor2 != 0)
14143+
continue;
14144+
uint64_t MulAmt3 = MulAmt2 / Divisor2;
14145+
if (isPowerOf2_64(MulAmt3)) {
14146+
SDLoc DL(N);
14147+
SDValue Mul359A =
14148+
DAG.getNode(RISCVISD::SHL_ADD, DL, VT, X,
14149+
DAG.getConstant(Log2_64(Divisor - 1), DL, VT), X);
14150+
SDValue Mul359B = DAG.getNode(
14151+
RISCVISD::SHL_ADD, DL, VT, Mul359A,
14152+
DAG.getConstant(Log2_64(Divisor2 - 1), DL, VT), Mul359A);
14153+
return DAG.getNode(ISD::SHL, DL, VT, Mul359B,
14154+
DAG.getConstant(Log2_64(MulAmt3), DL, VT));
14155+
}
14156+
}
14157+
}
14158+
}
14159+
1413414160
return SDValue();
1413514161
}
1413614162

llvm/test/CodeGen/RISCV/rv64zba.ll

Lines changed: 139 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -570,122 +570,200 @@ define i64 @addmul72(i64 %a, i64 %b) {
570570
}
571571

572572
define i64 @mul50(i64 %a) {
573-
; CHECK-LABEL: mul50:
574-
; CHECK: # %bb.0:
575-
; CHECK-NEXT: li a1, 50
576-
; CHECK-NEXT: mul a0, a0, a1
577-
; CHECK-NEXT: ret
573+
; RV64I-LABEL: mul50:
574+
; RV64I: # %bb.0:
575+
; RV64I-NEXT: li a1, 50
576+
; RV64I-NEXT: mul a0, a0, a1
577+
; RV64I-NEXT: ret
578+
;
579+
; RV64ZBA-LABEL: mul50:
580+
; RV64ZBA: # %bb.0:
581+
; RV64ZBA-NEXT: sh2add a0, a0, a0
582+
; RV64ZBA-NEXT: sh2add a0, a0, a0
583+
; RV64ZBA-NEXT: slli a0, a0, 1
584+
; RV64ZBA-NEXT: ret
578585
%c = mul i64 %a, 50
579586
ret i64 %c
580587
}
581588

582589
define i64 @addmul50(i64 %a, i64 %b) {
583-
; CHECK-LABEL: addmul50:
584-
; CHECK: # %bb.0:
585-
; CHECK-NEXT: li a2, 50
586-
; CHECK-NEXT: mul a0, a0, a2
587-
; CHECK-NEXT: add a0, a0, a1
588-
; CHECK-NEXT: ret
590+
; RV64I-LABEL: addmul50:
591+
; RV64I: # %bb.0:
592+
; RV64I-NEXT: li a2, 50
593+
; RV64I-NEXT: mul a0, a0, a2
594+
; RV64I-NEXT: add a0, a0, a1
595+
; RV64I-NEXT: ret
596+
;
597+
; RV64ZBA-LABEL: addmul50:
598+
; RV64ZBA: # %bb.0:
599+
; RV64ZBA-NEXT: sh2add a0, a0, a0
600+
; RV64ZBA-NEXT: sh2add a0, a0, a0
601+
; RV64ZBA-NEXT: sh1add a0, a0, a1
602+
; RV64ZBA-NEXT: ret
589603
%c = mul i64 %a, 50
590604
%d = add i64 %c, %b
591605
ret i64 %d
592606
}
593607

594608
define i64 @mul100(i64 %a) {
595-
; CHECK-LABEL: mul100:
596-
; CHECK: # %bb.0:
597-
; CHECK-NEXT: li a1, 100
598-
; CHECK-NEXT: mul a0, a0, a1
599-
; CHECK-NEXT: ret
609+
; RV64I-LABEL: mul100:
610+
; RV64I: # %bb.0:
611+
; RV64I-NEXT: li a1, 100
612+
; RV64I-NEXT: mul a0, a0, a1
613+
; RV64I-NEXT: ret
614+
;
615+
; RV64ZBA-LABEL: mul100:
616+
; RV64ZBA: # %bb.0:
617+
; RV64ZBA-NEXT: sh2add a0, a0, a0
618+
; RV64ZBA-NEXT: sh2add a0, a0, a0
619+
; RV64ZBA-NEXT: slli a0, a0, 2
620+
; RV64ZBA-NEXT: ret
600621
%c = mul i64 %a, 100
601622
ret i64 %c
602623
}
603624

604625
define i64 @addmul100(i64 %a, i64 %b) {
605-
; CHECK-LABEL: addmul100:
606-
; CHECK: # %bb.0:
607-
; CHECK-NEXT: li a2, 100
608-
; CHECK-NEXT: mul a0, a0, a2
609-
; CHECK-NEXT: add a0, a0, a1
610-
; CHECK-NEXT: ret
626+
; RV64I-LABEL: addmul100:
627+
; RV64I: # %bb.0:
628+
; RV64I-NEXT: li a2, 100
629+
; RV64I-NEXT: mul a0, a0, a2
630+
; RV64I-NEXT: add a0, a0, a1
631+
; RV64I-NEXT: ret
632+
;
633+
; RV64ZBA-LABEL: addmul100:
634+
; RV64ZBA: # %bb.0:
635+
; RV64ZBA-NEXT: sh2add a0, a0, a0
636+
; RV64ZBA-NEXT: sh2add a0, a0, a0
637+
; RV64ZBA-NEXT: sh2add a0, a0, a1
638+
; RV64ZBA-NEXT: ret
611639
%c = mul i64 %a, 100
612640
%d = add i64 %c, %b
613641
ret i64 %d
614642
}
615643

616644
define i64 @mul162(i64 %a) {
617-
; CHECK-LABEL: mul162:
618-
; CHECK: # %bb.0:
619-
; CHECK-NEXT: li a1, 162
620-
; CHECK-NEXT: mul a0, a0, a1
621-
; CHECK-NEXT: ret
645+
; RV64I-LABEL: mul162:
646+
; RV64I: # %bb.0:
647+
; RV64I-NEXT: li a1, 162
648+
; RV64I-NEXT: mul a0, a0, a1
649+
; RV64I-NEXT: ret
650+
;
651+
; RV64ZBA-LABEL: mul162:
652+
; RV64ZBA: # %bb.0:
653+
; RV64ZBA-NEXT: sh3add a0, a0, a0
654+
; RV64ZBA-NEXT: sh3add a0, a0, a0
655+
; RV64ZBA-NEXT: slli a0, a0, 1
656+
; RV64ZBA-NEXT: ret
622657
%c = mul i64 %a, 162
623658
ret i64 %c
624659
}
625660

626661
define i64 @addmul162(i64 %a, i64 %b) {
627-
; CHECK-LABEL: addmul162:
628-
; CHECK: # %bb.0:
629-
; CHECK-NEXT: li a2, 162
630-
; CHECK-NEXT: mul a0, a0, a2
631-
; CHECK-NEXT: add a0, a0, a1
632-
; CHECK-NEXT: ret
662+
; RV64I-LABEL: addmul162:
663+
; RV64I: # %bb.0:
664+
; RV64I-NEXT: li a2, 162
665+
; RV64I-NEXT: mul a0, a0, a2
666+
; RV64I-NEXT: add a0, a0, a1
667+
; RV64I-NEXT: ret
668+
;
669+
; RV64ZBA-LABEL: addmul162:
670+
; RV64ZBA: # %bb.0:
671+
; RV64ZBA-NEXT: sh3add a0, a0, a0
672+
; RV64ZBA-NEXT: sh3add a0, a0, a0
673+
; RV64ZBA-NEXT: sh1add a0, a0, a1
674+
; RV64ZBA-NEXT: ret
633675
%c = mul i64 %a, 162
634676
%d = add i64 %c, %b
635677
ret i64 %d
636678
}
637679

638680
define i64 @mul180(i64 %a) {
639-
; CHECK-LABEL: mul180:
640-
; CHECK: # %bb.0:
641-
; CHECK-NEXT: li a1, 180
642-
; CHECK-NEXT: mul a0, a0, a1
643-
; CHECK-NEXT: ret
681+
; RV64I-LABEL: mul180:
682+
; RV64I: # %bb.0:
683+
; RV64I-NEXT: li a1, 180
684+
; RV64I-NEXT: mul a0, a0, a1
685+
; RV64I-NEXT: ret
686+
;
687+
; RV64ZBA-LABEL: mul180:
688+
; RV64ZBA: # %bb.0:
689+
; RV64ZBA-NEXT: sh2add a0, a0, a0
690+
; RV64ZBA-NEXT: sh3add a0, a0, a0
691+
; RV64ZBA-NEXT: slli a0, a0, 2
692+
; RV64ZBA-NEXT: ret
644693
%c = mul i64 %a, 180
645694
ret i64 %c
646695
}
647696

648697
define i64 @addmul180(i64 %a, i64 %b) {
649-
; CHECK-LABEL: addmul180:
650-
; CHECK: # %bb.0:
651-
; CHECK-NEXT: li a2, 180
652-
; CHECK-NEXT: mul a0, a0, a2
653-
; CHECK-NEXT: add a0, a0, a1
654-
; CHECK-NEXT: ret
698+
; RV64I-LABEL: addmul180:
699+
; RV64I: # %bb.0:
700+
; RV64I-NEXT: li a2, 180
701+
; RV64I-NEXT: mul a0, a0, a2
702+
; RV64I-NEXT: add a0, a0, a1
703+
; RV64I-NEXT: ret
704+
;
705+
; RV64ZBA-LABEL: addmul180:
706+
; RV64ZBA: # %bb.0:
707+
; RV64ZBA-NEXT: sh2add a0, a0, a0
708+
; RV64ZBA-NEXT: sh3add a0, a0, a0
709+
; RV64ZBA-NEXT: sh2add a0, a0, a1
710+
; RV64ZBA-NEXT: ret
655711
%c = mul i64 %a, 180
656712
%d = add i64 %c, %b
657713
ret i64 %d
658714
}
659715

660716
define i64 @add255mul180(i64 %a) {
661-
; CHECK-LABEL: add255mul180:
662-
; CHECK: # %bb.0:
663-
; CHECK-NEXT: li a1, 180
664-
; CHECK-NEXT: mul a0, a0, a1
665-
; CHECK-NEXT: addi a0, a0, 255
666-
; CHECK-NEXT: ret
717+
; RV64I-LABEL: add255mul180:
718+
; RV64I: # %bb.0:
719+
; RV64I-NEXT: li a1, 180
720+
; RV64I-NEXT: mul a0, a0, a1
721+
; RV64I-NEXT: addi a0, a0, 255
722+
; RV64I-NEXT: ret
723+
;
724+
; RV64ZBA-LABEL: add255mul180:
725+
; RV64ZBA: # %bb.0:
726+
; RV64ZBA-NEXT: sh2add a0, a0, a0
727+
; RV64ZBA-NEXT: sh3add a0, a0, a0
728+
; RV64ZBA-NEXT: slli a0, a0, 2
729+
; RV64ZBA-NEXT: addi a0, a0, 255
730+
; RV64ZBA-NEXT: ret
667731
%c = mul i64 %a, 180
668732
%d = add i64 %c, 255
669733
ret i64 %d
670734
}
671735

672736
define i64 @mul200(i64 %a) {
673-
; CHECK-LABEL: mul200:
674-
; CHECK: # %bb.0:
675-
; CHECK-NEXT: li a1, 200
676-
; CHECK-NEXT: mul a0, a0, a1
677-
; CHECK-NEXT: ret
737+
; RV64I-LABEL: mul200:
738+
; RV64I: # %bb.0:
739+
; RV64I-NEXT: li a1, 200
740+
; RV64I-NEXT: mul a0, a0, a1
741+
; RV64I-NEXT: ret
742+
;
743+
; RV64ZBA-LABEL: mul200:
744+
; RV64ZBA: # %bb.0:
745+
; RV64ZBA-NEXT: sh2add a0, a0, a0
746+
; RV64ZBA-NEXT: sh2add a0, a0, a0
747+
; RV64ZBA-NEXT: slli a0, a0, 3
748+
; RV64ZBA-NEXT: ret
678749
%c = mul i64 %a, 200
679750
ret i64 %c
680751
}
681752

682753
define i64 @addmul200(i64 %a, i64 %b) {
683-
; CHECK-LABEL: addmul200:
684-
; CHECK: # %bb.0:
685-
; CHECK-NEXT: li a2, 200
686-
; CHECK-NEXT: mul a0, a0, a2
687-
; CHECK-NEXT: add a0, a0, a1
688-
; CHECK-NEXT: ret
754+
; RV64I-LABEL: addmul200:
755+
; RV64I: # %bb.0:
756+
; RV64I-NEXT: li a2, 200
757+
; RV64I-NEXT: mul a0, a0, a2
758+
; RV64I-NEXT: add a0, a0, a1
759+
; RV64I-NEXT: ret
760+
;
761+
; RV64ZBA-LABEL: addmul200:
762+
; RV64ZBA: # %bb.0:
763+
; RV64ZBA-NEXT: sh2add a0, a0, a0
764+
; RV64ZBA-NEXT: sh2add a0, a0, a0
765+
; RV64ZBA-NEXT: sh3add a0, a0, a1
766+
; RV64ZBA-NEXT: ret
689767
%c = mul i64 %a, 200
690768
%d = add i64 %c, %b
691769
ret i64 %d

0 commit comments

Comments
 (0)