Skip to content

Commit 35dfd1b

Browse files
committed
[SystemZ] Improve codegen for certain SADDO-immediate cases
When performing an add-with-overflow with an immediate in the range -2G ... -4G, code currently loads the immediate into a register, which generally takes two instructions. In this particular case, it is preferable to load the negated immediate into a register instead, which always only requires one instruction, and then perform a subtract. llvm-svn: 357597
1 parent ff33972 commit 35dfd1b

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

llvm/lib/Target/SystemZ/SystemZInstrInfo.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,14 @@ let AddedComplexity = 1 in {
10291029
(AGFI GR64:$src1, imm64sx32n:$src2)>;
10301030
}
10311031

1032+
// And vice versa in one special case, where we need to load a
1033+
// constant into a register in any case, but the negated constant
1034+
// requires fewer instructions to load.
1035+
def : Pat<(z_saddo GR64:$src1, imm64lh16n:$src2),
1036+
(SGR GR64:$src1, (LLILH imm64lh16n:$src2))>;
1037+
def : Pat<(z_saddo GR64:$src1, imm64lf32n:$src2),
1038+
(SGR GR64:$src1, (LLILF imm64lf32n:$src2))>;
1039+
10321040
// Subtraction producing a carry.
10331041
let Defs = [CC] in {
10341042
// Subtraction of a register.

llvm/lib/Target/SystemZ/SystemZOperands.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,17 @@ def HF32 : SDNodeXForm<imm, [{
188188
return CurDAG->getTargetConstant(Value, SDLoc(N), MVT::i64);
189189
}]>;
190190

191+
// Negated variants.
192+
def NEGLH16 : SDNodeXForm<imm, [{
193+
uint64_t Value = (-N->getZExtValue() & 0x00000000FFFF0000ULL) >> 16;
194+
return CurDAG->getTargetConstant(Value, SDLoc(N), MVT::i64);
195+
}]>;
196+
197+
def NEGLF32 : SDNodeXForm<imm, [{
198+
uint64_t Value = -N->getZExtValue() & 0x00000000FFFFFFFFULL;
199+
return CurDAG->getTargetConstant(Value, SDLoc(N), MVT::i64);
200+
}]>;
201+
191202
// Truncate an immediate to a 8-bit signed quantity.
192203
def SIMM8 : SDNodeXForm<imm, [{
193204
return CurDAG->getTargetConstant(int8_t(N->getZExtValue()), SDLoc(N),
@@ -430,6 +441,15 @@ def imm64hf32c : Immediate<i64, [{
430441
return SystemZ::isImmHF(uint64_t(~N->getZExtValue()));
431442
}], HF32, "U32Imm">;
432443

444+
// Negated immediates that fit LF32 or LH16.
445+
def imm64lh16n : Immediate<i64, [{
446+
return SystemZ::isImmLH(uint64_t(-N->getZExtValue()));
447+
}], NEGLH16, "U16Imm">;
448+
449+
def imm64lf32n : Immediate<i64, [{
450+
return SystemZ::isImmLF(uint64_t(-N->getZExtValue()));
451+
}], NEGLF32, "U32Imm">;
452+
433453
// Short immediates.
434454
def imm64sx8 : Immediate<i64, [{
435455
return isInt<8>(N->getSExtValue());

llvm/test/CodeGen/SystemZ/int-sadd-07.ll

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,26 +151,77 @@ define zeroext i1 @f9(i64 %dummy, i64 %a, i64 *%res) {
151151
ret i1 %obit
152152
}
153153

154-
; Check the next value down, which must use register addition instead.
154+
; Check the next value down, which can use register subtraction instead.
155155
define zeroext i1 @f10(i64 %dummy, i64 %a, i64 *%res) {
156156
; CHECK-LABEL: f10:
157+
; CHECK: llilf [[REG1:%r[0-9]+]], 2147483649
158+
; CHECK: sgr %r3, [[REG1]]
159+
; CHECK-DAG: stg %r3, 0(%r4)
160+
; CHECK-DAG: ipm [[REG:%r[0-5]]]
161+
; CHECK-DAG: afi [[REG]], 1342177280
162+
; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
163+
; CHECK: br %r14
164+
%t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 -2147483649)
165+
%val = extractvalue {i64, i1} %t, 0
166+
%obit = extractvalue {i64, i1} %t, 1
167+
store i64 %val, i64 *%res
168+
ret i1 %obit
169+
}
170+
171+
; We may be able to use LLILH instead of LLILF.
172+
define zeroext i1 @f11(i64 %dummy, i64 %a, i64 *%res) {
173+
; CHECK-LABEL: f11:
174+
; CHECK: llilh [[REG1:%r[0-9]+]], 32769
175+
; CHECK: sgr %r3, [[REG1]]
176+
; CHECK-DAG: stg %r3, 0(%r4)
177+
; CHECK-DAG: ipm [[REG:%r[0-5]]]
178+
; CHECK-DAG: afi [[REG]], 1342177280
179+
; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
180+
; CHECK: br %r14
181+
%t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 -2147549184)
182+
%val = extractvalue {i64, i1} %t, 0
183+
%obit = extractvalue {i64, i1} %t, 1
184+
store i64 %val, i64 *%res
185+
ret i1 %obit
186+
}
187+
188+
; Check low end of the LLILF/SGR range.
189+
define zeroext i1 @f12(i64 %dummy, i64 %a, i64 *%res) {
190+
; CHECK-LABEL: f12:
191+
; CHECK: llilf [[REG1:%r[0-9]+]], 4294967295
192+
; CHECK: sgr %r3, [[REG1]]
193+
; CHECK-DAG: stg %r3, 0(%r4)
194+
; CHECK-DAG: ipm [[REG:%r[0-5]]]
195+
; CHECK-DAG: afi [[REG]], 1342177280
196+
; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
197+
; CHECK: br %r14
198+
%t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 -4294967295)
199+
%val = extractvalue {i64, i1} %t, 0
200+
%obit = extractvalue {i64, i1} %t, 1
201+
store i64 %val, i64 *%res
202+
ret i1 %obit
203+
}
204+
205+
; Check the next value down, which must use register addition instead.
206+
define zeroext i1 @f13(i64 %dummy, i64 %a, i64 *%res) {
207+
; CHECK-LABEL: f13:
157208
; CHECK: llihf [[REG1:%r[0-9]+]], 4294967295
158209
; CHECK: agr [[REG1]], %r3
159210
; CHECK-DAG: stg [[REG1]], 0(%r4)
160211
; CHECK-DAG: ipm [[REG:%r[0-5]]]
161212
; CHECK-DAG: afi [[REG]], 1342177280
162213
; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
163214
; CHECK: br %r14
164-
%t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 -2147483649)
215+
%t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 -4294967296)
165216
%val = extractvalue {i64, i1} %t, 0
166217
%obit = extractvalue {i64, i1} %t, 1
167218
store i64 %val, i64 *%res
168219
ret i1 %obit
169220
}
170221

171222
; Check using the overflow result for a branch.
172-
define void @f11(i64 %dummy, i64 %a, i64 *%res) {
173-
; CHECK-LABEL: f11:
223+
define void @f14(i64 %dummy, i64 %a, i64 *%res) {
224+
; CHECK-LABEL: f14:
174225
; CHECK: aghi %r3, 1
175226
; CHECK: stg %r3, 0(%r4)
176227
; CHECK: {{jgo foo@PLT|bnor %r14}}
@@ -190,8 +241,8 @@ exit:
190241
}
191242

192243
; ... and the same with the inverted direction.
193-
define void @f12(i64 %dummy, i64 %a, i64 *%res) {
194-
; CHECK-LABEL: f12:
244+
define void @f15(i64 %dummy, i64 %a, i64 *%res) {
245+
; CHECK-LABEL: f15:
195246
; CHECK: aghi %r3, 1
196247
; CHECK: stg %r3, 0(%r4)
197248
; CHECK: {{jgno foo@PLT|bor %r14}}

0 commit comments

Comments
 (0)