Skip to content

Commit a992115

Browse files
committed
[LoongArch] Add codegen support for the binary operations
These binary operations include sub/fadd/fsub/fmul/fdiv. Others ops like mul/udiv/sdiv/urem/srem would be added later since they depend on `shift` and `truncate` that have not been supported. Note `add` has been added in a previous patch. Reference: https://llvm.org/docs/LangRef.html#binary-operations Differential Revision: https://reviews.llvm.org/D127199
1 parent 7cb4999 commit a992115

File tree

10 files changed

+481
-33
lines changed

10 files changed

+481
-33
lines changed

llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,23 @@ def FSTGT_S : FP_STORE_3R<0b00111000011101100, "fstgt.s", FPR32>;
106106
def FSTLE_S : FP_STORE_3R<0b00111000011101110, "fstle.s", FPR32>;
107107

108108
} // Predicates = [HasBasicF]
109+
110+
//===----------------------------------------------------------------------===//
111+
// Pseudo-instructions and codegen patterns
112+
//===----------------------------------------------------------------------===//
113+
114+
/// Generic pattern classes
115+
116+
class PatFprFpr<SDPatternOperator OpNode, LAInst Inst, RegisterClass RegTy>
117+
: Pat<(OpNode RegTy:$fj, RegTy:$fk), (Inst $fj, $fk)>;
118+
119+
let Predicates = [HasBasicF] in {
120+
121+
/// Float arithmetic operations
122+
123+
def : PatFprFpr<fadd, FADD_S, FPR32>;
124+
def : PatFprFpr<fsub, FSUB_S, FPR32>;
125+
def : PatFprFpr<fmul, FMUL_S, FPR32>;
126+
def : PatFprFpr<fdiv, FDIV_S, FPR32>;
127+
128+
} // Predicates = [HasBasicF]

llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,17 @@ def MOVGR2FR_D : FP_MOV<0b0000000100010100101010, "movgr2fr.d", FPR64, GPR>;
131131
def MOVFR2GR_D : FP_MOV<0b0000000100010100101110, "movfr2gr.d", GPR, FPR64>;
132132
} // Predicates = [HasBasicD, IsLA64]
133133

134+
//===----------------------------------------------------------------------===//
135+
// Pseudo-instructions and codegen patterns
136+
//===----------------------------------------------------------------------===//
137+
138+
let Predicates = [HasBasicD] in {
139+
140+
/// Float arithmetic operations
141+
142+
def : PatFprFpr<fadd, FADD_D, FPR64>;
143+
def : PatFprFpr<fsub, FSUB_D, FPR64>;
144+
def : PatFprFpr<fmul, FMUL_D, FPR64>;
145+
def : PatFprFpr<fdiv, FDIV_D, FPR64>;
146+
147+
} // Predicates = [HasBasicD]

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
3131
MVT GRLenVT = Subtarget.getGRLenVT();
3232
// Set up the register classes.
3333
addRegisterClass(GRLenVT, &LoongArch::GPRRegClass);
34+
if (Subtarget.hasBasicF())
35+
addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass);
36+
if (Subtarget.hasBasicD())
37+
addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass);
3438

3539
// TODO: add necessary setOperationAction calls later.
3640

@@ -39,6 +43,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
3943

4044
setStackPointerRegisterToSaveRestore(LoongArch::R3);
4145

46+
setBooleanContents(ZeroOrOneBooleanContent);
47+
4248
// Function alignments.
4349
const Align FunctionAlignment(4);
4450
setMinFunctionAlignment(FunctionAlignment);
@@ -64,16 +70,29 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
6470
// Calling Convention Implementation
6571
//===----------------------------------------------------------------------===//
6672
// FIXME: Now, we only support CallingConv::C with fixed arguments which are
67-
// passed with integer registers.
73+
// passed with integer or floating-point registers.
6874
const MCPhysReg ArgGPRs[] = {LoongArch::R4, LoongArch::R5, LoongArch::R6,
6975
LoongArch::R7, LoongArch::R8, LoongArch::R9,
7076
LoongArch::R10, LoongArch::R11};
77+
const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2,
78+
LoongArch::F3, LoongArch::F4, LoongArch::F5,
79+
LoongArch::F6, LoongArch::F7};
80+
const MCPhysReg ArgFPR64s[] = {
81+
LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
82+
LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
7183

7284
// Implements the LoongArch calling convention. Returns true upon failure.
7385
static bool CC_LoongArch(unsigned ValNo, MVT ValVT,
7486
CCValAssign::LocInfo LocInfo, CCState &State) {
7587
// Allocate to a register if possible.
76-
Register Reg = State.AllocateReg(ArgGPRs);
88+
Register Reg;
89+
90+
if (ValVT == MVT::f32)
91+
Reg = State.AllocateReg(ArgFPR32s);
92+
else if (ValVT == MVT::f64)
93+
Reg = State.AllocateReg(ArgFPR64s);
94+
else
95+
Reg = State.AllocateReg(ArgGPRs);
7796
if (Reg) {
7897
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo));
7998
return false;

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -509,35 +509,43 @@ class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
509509
: Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32),
510510
(Inst GPR:$rj, ImmOpnd:$imm)>;
511511

512-
def : PatGprGpr<and, AND>;
513-
def : PatGprGpr<or, OR>;
514-
def : PatGprGpr<xor, XOR>;
515-
516-
/// Branches and jumps
517-
518-
let isBarrier = 1, isReturn = 1, isTerminator = 1 in
519-
def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
520-
PseudoInstExpansion<(JIRL R0, R1, 0)>;
521-
522-
/// LA32 patterns
512+
/// Simple arithmetic operations
523513

524514
let Predicates = [IsLA32] in {
525515
def : PatGprGpr<add, ADD_W>;
526516
def : PatGprImm<add, ADDI_W, simm12>;
517+
def : PatGprGpr<sub, SUB_W>;
527518
} // Predicates = [IsLA32]
528519

529-
/// LA64 patterns
530-
531520
let Predicates = [IsLA64] in {
532-
def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>;
533-
534521
def : PatGprGpr<add, ADD_D>;
535522
def : PatGprGpr_32<add, ADD_W>;
536-
537523
def : PatGprImm<add, ADDI_D, simm12>;
538524
def : PatGprImm_32<add, ADDI_W, simm12>;
525+
def : PatGprGpr<sub, SUB_D>;
526+
def : PatGprGpr_32<sub, SUB_W>;
539527
} // Predicates = [IsLA64]
540528

529+
def : PatGprGpr<and, AND>;
530+
def : PatGprGpr<or, OR>;
531+
def : PatGprGpr<xor, XOR>;
532+
533+
/// sext and zext
534+
535+
let Predicates = [IsLA64] in {
536+
def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>;
537+
} // Predicates = [IsLA64]
538+
539+
/// Setcc
540+
541+
def : PatGprGpr<setult, SLTU>;
542+
543+
/// Branches and jumps
544+
545+
let isBarrier = 1, isReturn = 1, isTerminator = 1 in
546+
def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
547+
PseudoInstExpansion<(JIRL R0, R1, 0)>;
548+
541549
//===----------------------------------------------------------------------===//
542550
// Assembler Pseudo Instructions
543551
//===----------------------------------------------------------------------===//
Lines changed: 181 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,183 @@
1-
; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=CHECK32
2-
; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=CHECK64
3-
4-
define i32 @addRR(i32 %x, i32 %y) {
5-
; CHECK32-LABEL: addRR:
6-
; CHECK32: # %bb.0: # %entry
7-
; CHECK32-NEXT: add.w $a0, $a1, $a0
8-
; CHECK32-NEXT: jirl $zero, $ra, 0
9-
;
10-
; CHECK64-LABEL: addRR:
11-
; CHECK64: # %bb.0: # %entry
12-
; CHECK64-NEXT: add.d $a0, $a1, $a0
13-
; CHECK64-NEXT: jirl $zero, $ra, 0
14-
entry:
15-
%add = add nsw i32 %y, %x
1+
; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32
2+
; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64
3+
4+
;; Exercise the 'add' LLVM IR: https://llvm.org/docs/LangRef.html#add-instruction
5+
6+
define i1 @add_i1(i1 %x, i1 %y) {
7+
; LA32-LABEL: add_i1:
8+
; LA32: # %bb.0:
9+
; LA32-NEXT: add.w $a0, $a0, $a1
10+
; LA32-NEXT: jirl $zero, $ra, 0
11+
;
12+
; LA64-LABEL: add_i1:
13+
; LA64: # %bb.0:
14+
; LA64-NEXT: add.d $a0, $a0, $a1
15+
; LA64-NEXT: jirl $zero, $ra, 0
16+
%add = add i1 %x, %y
17+
ret i1 %add
18+
}
19+
20+
define i8 @add_i8(i8 %x, i8 %y) {
21+
; LA32-LABEL: add_i8:
22+
; LA32: # %bb.0:
23+
; LA32-NEXT: add.w $a0, $a0, $a1
24+
; LA32-NEXT: jirl $zero, $ra, 0
25+
;
26+
; LA64-LABEL: add_i8:
27+
; LA64: # %bb.0:
28+
; LA64-NEXT: add.d $a0, $a0, $a1
29+
; LA64-NEXT: jirl $zero, $ra, 0
30+
%add = add i8 %x, %y
31+
ret i8 %add
32+
}
33+
34+
define i16 @add_i16(i16 %x, i16 %y) {
35+
; LA32-LABEL: add_i16:
36+
; LA32: # %bb.0:
37+
; LA32-NEXT: add.w $a0, $a0, $a1
38+
; LA32-NEXT: jirl $zero, $ra, 0
39+
;
40+
; LA64-LABEL: add_i16:
41+
; LA64: # %bb.0:
42+
; LA64-NEXT: add.d $a0, $a0, $a1
43+
; LA64-NEXT: jirl $zero, $ra, 0
44+
%add = add i16 %x, %y
45+
ret i16 %add
46+
}
47+
48+
define i32 @add_i32(i32 %x, i32 %y) {
49+
; LA32-LABEL: add_i32:
50+
; LA32: # %bb.0:
51+
; LA32-NEXT: add.w $a0, $a0, $a1
52+
; LA32-NEXT: jirl $zero, $ra, 0
53+
;
54+
; LA64-LABEL: add_i32:
55+
; LA64: # %bb.0:
56+
; LA64-NEXT: add.d $a0, $a0, $a1
57+
; LA64-NEXT: jirl $zero, $ra, 0
58+
%add = add i32 %x, %y
59+
ret i32 %add
60+
}
61+
62+
;; Match the pattern:
63+
;; def : PatGprGpr_32<add, ADD_W>;
64+
define signext i32 @add_i32_sext(i32 %x, i32 %y) {
65+
; LA32-LABEL: add_i32_sext:
66+
; LA32: # %bb.0:
67+
; LA32-NEXT: add.w $a0, $a0, $a1
68+
; LA32-NEXT: jirl $zero, $ra, 0
69+
;
70+
; LA64-LABEL: add_i32_sext:
71+
; LA64: # %bb.0:
72+
; LA64-NEXT: add.w $a0, $a0, $a1
73+
; LA64-NEXT: jirl $zero, $ra, 0
74+
%add = add i32 %x, %y
1675
ret i32 %add
1776
}
77+
78+
define i64 @add_i64(i64 %x, i64 %y) {
79+
; LA32-LABEL: add_i64:
80+
; LA32: # %bb.0:
81+
; LA32-NEXT: add.w $a1, $a1, $a3
82+
; LA32-NEXT: add.w $a2, $a0, $a2
83+
; LA32-NEXT: sltu $a0, $a2, $a0
84+
; LA32-NEXT: add.w $a1, $a1, $a0
85+
; LA32-NEXT: move $a0, $a2
86+
; LA32-NEXT: jirl $zero, $ra, 0
87+
;
88+
; LA64-LABEL: add_i64:
89+
; LA64: # %bb.0:
90+
; LA64-NEXT: add.d $a0, $a0, $a1
91+
; LA64-NEXT: jirl $zero, $ra, 0
92+
%add = add i64 %x, %y
93+
ret i64 %add
94+
}
95+
96+
define i1 @add_i1_3(i1 %x) {
97+
; LA32-LABEL: add_i1_3:
98+
; LA32: # %bb.0:
99+
; LA32-NEXT: addi.w $a0, $a0, 1
100+
; LA32-NEXT: jirl $zero, $ra, 0
101+
;
102+
; LA64-LABEL: add_i1_3:
103+
; LA64: # %bb.0:
104+
; LA64-NEXT: addi.d $a0, $a0, 1
105+
; LA64-NEXT: jirl $zero, $ra, 0
106+
%add = add i1 %x, 3
107+
ret i1 %add
108+
}
109+
110+
define i8 @add_i8_3(i8 %x) {
111+
; LA32-LABEL: add_i8_3:
112+
; LA32: # %bb.0:
113+
; LA32-NEXT: addi.w $a0, $a0, 3
114+
; LA32-NEXT: jirl $zero, $ra, 0
115+
;
116+
; LA64-LABEL: add_i8_3:
117+
; LA64: # %bb.0:
118+
; LA64-NEXT: addi.d $a0, $a0, 3
119+
; LA64-NEXT: jirl $zero, $ra, 0
120+
%add = add i8 %x, 3
121+
ret i8 %add
122+
}
123+
124+
define i16 @add_i16_3(i16 %x) {
125+
; LA32-LABEL: add_i16_3:
126+
; LA32: # %bb.0:
127+
; LA32-NEXT: addi.w $a0, $a0, 3
128+
; LA32-NEXT: jirl $zero, $ra, 0
129+
;
130+
; LA64-LABEL: add_i16_3:
131+
; LA64: # %bb.0:
132+
; LA64-NEXT: addi.d $a0, $a0, 3
133+
; LA64-NEXT: jirl $zero, $ra, 0
134+
%add = add i16 %x, 3
135+
ret i16 %add
136+
}
137+
138+
define i32 @add_i32_3(i32 %x) {
139+
; LA32-LABEL: add_i32_3:
140+
; LA32: # %bb.0:
141+
; LA32-NEXT: addi.w $a0, $a0, 3
142+
; LA32-NEXT: jirl $zero, $ra, 0
143+
;
144+
; LA64-LABEL: add_i32_3:
145+
; LA64: # %bb.0:
146+
; LA64-NEXT: addi.d $a0, $a0, 3
147+
; LA64-NEXT: jirl $zero, $ra, 0
148+
%add = add i32 %x, 3
149+
ret i32 %add
150+
}
151+
152+
;; Match the pattern:
153+
;; def : PatGprImm_32<add, ADDI_W, simm12>;
154+
define signext i32 @add_i32_3_sext(i32 %x) {
155+
; LA32-LABEL: add_i32_3_sext:
156+
; LA32: # %bb.0:
157+
; LA32-NEXT: addi.w $a0, $a0, 3
158+
; LA32-NEXT: jirl $zero, $ra, 0
159+
;
160+
; LA64-LABEL: add_i32_3_sext:
161+
; LA64: # %bb.0:
162+
; LA64-NEXT: addi.w $a0, $a0, 3
163+
; LA64-NEXT: jirl $zero, $ra, 0
164+
%add = add i32 %x, 3
165+
ret i32 %add
166+
}
167+
168+
define i64 @add_i64_3(i64 %x) {
169+
; LA32-LABEL: add_i64_3:
170+
; LA32: # %bb.0:
171+
; LA32-NEXT: addi.w $a2, $a0, 3
172+
; LA32-NEXT: sltu $a0, $a2, $a0
173+
; LA32-NEXT: add.w $a1, $a1, $a0
174+
; LA32-NEXT: move $a0, $a2
175+
; LA32-NEXT: jirl $zero, $ra, 0
176+
;
177+
; LA64-LABEL: add_i64_3:
178+
; LA64: # %bb.0:
179+
; LA64-NEXT: addi.d $a0, $a0, 3
180+
; LA64-NEXT: jirl $zero, $ra, 0
181+
%add = add i64 %x, 3
182+
ret i64 %add
183+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: llc --mtriple=loongarch32 --mattr=+d < %s | FileCheck %s --check-prefix=LA32
2+
; RUN: llc --mtriple=loongarch64 --mattr=+d < %s | FileCheck %s --check-prefix=LA64
3+
4+
;; Exercise the 'fadd' LLVM IR: https://llvm.org/docs/LangRef.html#fadd-instruction
5+
6+
define float @fadd_s(float %x, float %y) {
7+
; LA32-LABEL: fadd_s:
8+
; LA32: # %bb.0:
9+
; LA32-NEXT: fadd.s $fa0, $fa0, $fa1
10+
; LA32-NEXT: jirl $zero, $ra, 0
11+
;
12+
; LA64-LABEL: fadd_s:
13+
; LA64: # %bb.0:
14+
; LA64-NEXT: fadd.s $fa0, $fa0, $fa1
15+
; LA64-NEXT: jirl $zero, $ra, 0
16+
%add = fadd float %x, %y
17+
ret float %add
18+
}
19+
20+
define double @fadd_d(double %x, double %y) {
21+
; LA32-LABEL: fadd_d:
22+
; LA32: # %bb.0:
23+
; LA32-NEXT: fadd.d $fa0, $fa0, $fa1
24+
; LA32-NEXT: jirl $zero, $ra, 0
25+
;
26+
; LA64-LABEL: fadd_d:
27+
; LA64: # %bb.0:
28+
; LA64-NEXT: fadd.d $fa0, $fa0, $fa1
29+
; LA64-NEXT: jirl $zero, $ra, 0
30+
%add = fadd double %x, %y
31+
ret double %add
32+
}

0 commit comments

Comments
 (0)