Skip to content

Commit eb81645

Browse files
committed
[RISCV][GISel] Lower G_SADDE
1 parent c71318a commit eb81645

File tree

6 files changed

+437
-3
lines changed

6 files changed

+437
-3
lines changed

llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ class LegalizerHelper {
510510
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI);
511511
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI);
512512
LLVM_ABI LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI);
513+
LLVM_ABI LegalizeResult lowerSADDE(MachineInstr &MI);
513514
LLVM_ABI LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI);
514515
LLVM_ABI LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI);
515516
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI);

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4447,6 +4447,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
44474447
case TargetOpcode::G_SADDO:
44484448
case TargetOpcode::G_SSUBO:
44494449
return lowerSADDO_SSUBO(MI);
4450+
case TargetOpcode::G_SADDE:
4451+
return lowerSADDE(MI);
44504452
case TargetOpcode::G_UMULH:
44514453
case TargetOpcode::G_SMULH:
44524454
return lowerSMULH_UMULH(MI);
@@ -9298,6 +9300,40 @@ LegalizerHelper::lowerSADDO_SSUBO(MachineInstr &MI) {
92989300
return Legalized;
92999301
}
93009302

9303+
LegalizerHelper::LegalizeResult LegalizerHelper::lowerSADDE(MachineInstr &MI) {
9304+
auto [Res, OvOut, LHS, RHS, CarryIn] = MI.getFirst5Regs();
9305+
const LLT Ty = MRI.getType(Res);
9306+
const LLT BoolTy = MRI.getType(OvOut);
9307+
9308+
Register NewRes = MRI.cloneVirtualRegister(Res);
9309+
9310+
// Step 1: tmp = LHS + RHS
9311+
auto Tmp = MIRBuilder.buildAdd(Ty, LHS, RHS);
9312+
9313+
// ov0 = (tmp < lhs) XOR (rhs < 0)
9314+
auto TmpLtLHS = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, Tmp, LHS);
9315+
auto Zero = MIRBuilder.buildConstant(Ty, 0);
9316+
auto RHSLt0 = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, RHS, Zero);
9317+
auto Ov0 = MIRBuilder.buildXor(BoolTy, TmpLtLHS, RHSLt0);
9318+
9319+
// Step 2: sum = tmp + zext(CarryIn)
9320+
auto CarryInZ = MIRBuilder.buildZExt(Ty, CarryIn);
9321+
MIRBuilder.buildAdd(NewRes, Tmp, CarryInZ);
9322+
9323+
// ov1 = CarryIn & (sum < tmp)
9324+
auto SumLtTmp = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, NewRes, Tmp);
9325+
auto Ov1 = MIRBuilder.buildAnd(BoolTy, SumLtTmp, CarryIn);
9326+
9327+
// ov = ov0 | ov1
9328+
auto Ov = MIRBuilder.buildOr(BoolTy, Ov0, Ov1);
9329+
9330+
MIRBuilder.buildCopy(OvOut, Ov);
9331+
MIRBuilder.buildCopy(Res, NewRes);
9332+
9333+
MI.eraseFromParent();
9334+
return Legalized;
9335+
}
9336+
93019337
LegalizerHelper::LegalizeResult
93029338
LegalizerHelper::lowerAddSubSatToMinMax(MachineInstr &MI) {
93039339
auto [Res, LHS, RHS] = MI.getFirst3Regs();

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
151151
getActionDefinitionsBuilder(
152152
{G_UADDE, G_UADDO, G_USUBE, G_USUBO}).lower();
153153

154-
getActionDefinitionsBuilder({G_SADDO, G_SSUBO}).minScalar(0, sXLen).lower();
154+
getActionDefinitionsBuilder({G_SADDO,G_SADDE, G_SSUBO}).minScalar(0, sXLen).lower();
155155

156156
// TODO: Use Vector Single-Width Saturating Instructions for vector types.
157157
getActionDefinitionsBuilder(

llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,9 @@
407407
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
408408
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
409409
# DEBUG-NEXT: G_SADDE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
410-
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
411-
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
410+
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
411+
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
412+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
412413
# DEBUG-NEXT: G_SSUBO (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
413414
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
414415
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -mtriple=riscv32 -run-pass=legalizer %s -o - | FileCheck %s
3+
4+
---
5+
name: sadde_i8
6+
body: |
7+
bb.1:
8+
liveins: $x10, $x11, $x12
9+
10+
; CHECK-LABEL: name: sadde_i8
11+
; CHECK: liveins: $x10, $x11, $x12
12+
; CHECK-NEXT: {{ $}}
13+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
14+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
15+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
16+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
17+
; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32)
18+
; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
19+
; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32)
20+
; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32)
21+
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[ASHR1]]
22+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
23+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C1]]
24+
; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[AND]]
25+
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY [[ADD1]](s32)
26+
; CHECK-NEXT: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32)
27+
; CHECK-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C]](s32)
28+
; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[COPY3]](s32), [[ASHR2]]
29+
; CHECK-NEXT: $x10 = COPY [[COPY3]](s32)
30+
; CHECK-NEXT: $x11 = COPY [[ICMP]](s32)
31+
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
32+
%0:_(s32) = COPY $x10
33+
%1:_(s8) = G_TRUNC %0(s32)
34+
%2:_(s32) = COPY $x11
35+
%3:_(s8) = G_TRUNC %2(s32)
36+
%4:_(s32) = COPY $x12
37+
%5:_(s1) = G_TRUNC %4(s32)
38+
%6:_(s8), %7:_(s1) = G_SADDE %1, %3, %5
39+
%8:_(s32) = G_ANYEXT %6(s8)
40+
%9:_(s32) = G_ANYEXT %7(s1)
41+
$x10 = COPY %8(s32)
42+
$x11 = COPY %9(s32)
43+
PseudoRET implicit $x10, implicit $x11
44+
45+
...
46+
---
47+
name: sadde_i16
48+
body: |
49+
bb.1:
50+
liveins: $x10, $x11, $x12
51+
52+
; CHECK-LABEL: name: sadde_i16
53+
; CHECK: liveins: $x10, $x11, $x12
54+
; CHECK-NEXT: {{ $}}
55+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
56+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
57+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
58+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
59+
; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32)
60+
; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
61+
; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32)
62+
; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32)
63+
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[ASHR1]]
64+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
65+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C1]]
66+
; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[AND]]
67+
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY [[ADD1]](s32)
68+
; CHECK-NEXT: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32)
69+
; CHECK-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C]](s32)
70+
; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[COPY3]](s32), [[ASHR2]]
71+
; CHECK-NEXT: $x10 = COPY [[COPY3]](s32)
72+
; CHECK-NEXT: $x11 = COPY [[ICMP]](s32)
73+
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
74+
%0:_(s32) = COPY $x10
75+
%1:_(s16) = G_TRUNC %0(s32)
76+
%2:_(s32) = COPY $x11
77+
%3:_(s16) = G_TRUNC %2(s32)
78+
%4:_(s32) = COPY $x12
79+
%5:_(s1) = G_TRUNC %4(s32)
80+
%6:_(s16), %7:_(s1) = G_SADDE %1, %3, %5
81+
%8:_(s32) = G_ANYEXT %6(s16)
82+
%9:_(s32) = G_ANYEXT %7(s1)
83+
$x10 = COPY %8(s32)
84+
$x11 = COPY %9(s32)
85+
PseudoRET implicit $x10, implicit $x11
86+
87+
...
88+
---
89+
name: sadde_i32
90+
body: |
91+
bb.1:
92+
liveins: $x10, $x11, $x12
93+
94+
; CHECK-LABEL: name: sadde_i32
95+
; CHECK: liveins: $x10, $x11, $x12
96+
; CHECK-NEXT: {{ $}}
97+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
98+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
99+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
100+
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]]
101+
; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD]](s32), [[COPY]]
102+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
103+
; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY1]](s32), [[C]]
104+
; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ICMP]], [[ICMP1]]
105+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
106+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C1]]
107+
; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[AND]]
108+
; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD1]](s32), [[ADD]]
109+
; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ICMP2]], [[COPY2]]
110+
; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[XOR]], [[AND1]]
111+
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY [[ADD1]](s32)
112+
; CHECK-NEXT: $x10 = COPY [[COPY3]](s32)
113+
; CHECK-NEXT: $x11 = COPY [[OR]](s32)
114+
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
115+
%0:_(s32) = COPY $x10
116+
%1:_(s32) = COPY $x11
117+
%2:_(s32) = COPY $x12
118+
%3:_(s1) = G_TRUNC %2(s32)
119+
%4:_(s32), %5:_(s1) = G_SADDE %0, %1, %3
120+
%6:_(s32) = G_ANYEXT %5(s1)
121+
$x10 = COPY %4(s32)
122+
$x11 = COPY %6(s32)
123+
PseudoRET implicit $x10, implicit $x11
124+
125+
...
126+
---
127+
name: sadde_i64
128+
body: |
129+
bb.1:
130+
liveins: $x10, $x11, $x12, $x13, $x14
131+
132+
; CHECK-LABEL: name: sadde_i64
133+
; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
134+
; CHECK-NEXT: {{ $}}
135+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
136+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
137+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
138+
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13
139+
; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $x14
140+
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY2]]
141+
; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD]](s32), [[COPY]]
142+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
143+
; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY2]](s32), [[C]]
144+
; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ICMP]], [[ICMP1]]
145+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
146+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C1]]
147+
; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[AND]]
148+
; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD1]](s32), [[ADD]]
149+
; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ICMP2]], [[COPY4]]
150+
; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[XOR]], [[AND1]]
151+
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD1]](s32)
152+
; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[COPY1]], [[COPY3]]
153+
; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD2]](s32), [[COPY1]]
154+
; CHECK-NEXT: [[ICMP4:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY3]](s32), [[C]]
155+
; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s32) = G_XOR [[ICMP3]], [[ICMP4]]
156+
; CHECK-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[ADD2]], [[OR]]
157+
; CHECK-NEXT: [[ICMP5:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD3]](s32), [[ADD2]]
158+
; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ICMP5]], [[OR]]
159+
; CHECK-NEXT: [[OR1:%[0-9]+]]:_(s32) = G_OR [[XOR1]], [[AND2]]
160+
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY [[ADD3]](s32)
161+
; CHECK-NEXT: $x10 = COPY [[COPY5]](s32)
162+
; CHECK-NEXT: $x11 = COPY [[COPY6]](s32)
163+
; CHECK-NEXT: $x12 = COPY [[OR1]](s32)
164+
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12
165+
%0:_(s32) = COPY $x10
166+
%1:_(s32) = COPY $x11
167+
%2:_(s32) = COPY $x12
168+
%3:_(s32) = COPY $x13
169+
%4:_(s32) = COPY $x14
170+
%5:_(s1) = G_TRUNC %4(s32)
171+
%6:_(s32), %7:_(s1) = G_SADDE %0, %2, %5
172+
%8:_(s32), %9:_(s1) = G_SADDE %1, %3, %7
173+
%10:_(s32) = G_ANYEXT %9(s1)
174+
$x10 = COPY %6(s32)
175+
$x11 = COPY %8(s32)
176+
$x12 = COPY %10(s32)
177+
178+
PseudoRET implicit $x10, implicit $x11, implicit $x12
179+
...

0 commit comments

Comments
 (0)