@@ -54,6 +54,8 @@ def SBFIsBigEndian : Predicate<"!CurDAG->getDataLayout().isLittleEndian()">;
54
54
def SBFHasALU32 : Predicate<"Subtarget->getHasAlu32()">;
55
55
def SBFNoALU32 : Predicate<"!Subtarget->getHasAlu32()">;
56
56
def SBFSubtargetSolana : Predicate<"Subtarget->isSolana()">;
57
+ def SBFv2 : Predicate<"Subtarget->isSBFv2()">;
58
+ def NoSBFv2 : Predicate<"!Subtarget->isSBFv2()">;
57
59
58
60
def brtarget : Operand<OtherVT> {
59
61
let PrintMethod = "printBrTargetOperand";
@@ -263,7 +265,7 @@ class ALU_RR<SBFOpClass Class, SBFArithOp Opc,
263
265
let SBFClass = Class;
264
266
}
265
267
266
- multiclass ALU<SBFArithOp Opc, string Mnemonic, SDNode OpNode> {
268
+ multiclass ALU<SBFArithOp Opc, string Mnemonic, SDNode OpNode, bit UseImmPat = 1 > {
267
269
def _rr : ALU_RR<SBF_ALU64, Opc,
268
270
(outs GPR:$dst),
269
271
(ins GPR:$src2, GPR:$src),
@@ -273,7 +275,9 @@ multiclass ALU<SBFArithOp Opc, string Mnemonic, SDNode OpNode> {
273
275
(outs GPR:$dst),
274
276
(ins GPR:$src2, i64imm:$imm),
275
277
Mnemonic # "64 $dst, $imm",
276
- [(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]>;
278
+ !if(UseImmPat,
279
+ [(set GPR:$dst,
280
+ (OpNode GPR:$src2, i64immSExt32:$imm))], [])>;
277
281
def _rr_32 : ALU_RR<SBF_ALU, Opc,
278
282
(outs GPR32:$dst),
279
283
(ins GPR32:$src2, GPR32:$src),
@@ -283,13 +287,15 @@ multiclass ALU<SBFArithOp Opc, string Mnemonic, SDNode OpNode> {
283
287
(outs GPR32:$dst),
284
288
(ins GPR32:$src2, i32imm:$imm),
285
289
Mnemonic # "32 $dst, $imm",
286
- [(set GPR32:$dst, (OpNode GPR32:$src2, i32immSExt32:$imm))]>;
290
+ !if(UseImmPat,
291
+ [(set GPR32:$dst,
292
+ (OpNode GPR32:$src2, i32immSExt32:$imm))], [])>;
287
293
}
288
294
289
295
let Constraints = "$dst = $src2" in {
290
296
let isAsCheapAsAMove = 1 in {
291
297
defm ADD : ALU<SBF_ADD, "add", add>;
292
- defm SUB : ALU<SBF_SUB, "sub", sub>;
298
+ defm SUB : ALU<SBF_SUB, "sub", sub, 0 >;
293
299
defm OR : ALU<SBF_OR, "or", or>;
294
300
defm AND : ALU<SBF_AND, "and", and>;
295
301
defm SLL : ALU<SBF_LSH, "lsh", shl>;
@@ -306,6 +312,19 @@ let Constraints = "$dst = $src2" in {
306
312
}
307
313
}
308
314
315
+ // Special case for SBFv2
316
+ // In SBFv1, `sub reg, imm` is interpreted as reg = reg - imm,
317
+ // but in SBFv2 it means reg = imm - reg
318
+ def : Pat<(sub GPR:$src, i64immSExt32:$imm),
319
+ (SUB_ri GPR:$src, i64immSExt32:$imm)>, Requires<[NoSBFv2]>;
320
+ def : Pat<(sub GPR32:$src, i32immSExt32:$imm),
321
+ (SUB_ri_32 GPR32:$src, i32immSExt32:$imm)>, Requires<[NoSBFv2]>;
322
+
323
+ def : Pat<(sub i64immSExt32:$imm, GPR:$src),
324
+ (SUB_ri GPR:$src, i64immSExt32:$imm)>, Requires<[SBFv2]>;
325
+ def : Pat<(sub i32immSExt32:$imm, GPR32:$src),
326
+ (SUB_ri_32 GPR32:$src, i32immSExt32:$imm)>, Requires<[SBFv2]>;
327
+
309
328
class NEG_RR<SBFOpClass Class, SBFArithOp Opc,
310
329
dag outs, dag ins, string asmstr, list<dag> pattern>
311
330
: TYPE_ALU_JMP<Opc.Value, 0, outs, ins, asmstr, pattern> {
@@ -318,12 +337,21 @@ class NEG_RR<SBFOpClass Class, SBFArithOp Opc,
318
337
let Constraints = "$dst = $src", isAsCheapAsAMove = 1 in {
319
338
def NEG_64: NEG_RR<SBF_ALU64, SBF_NEG, (outs GPR:$dst), (ins GPR:$src),
320
339
"neg64 $dst",
321
- [(set GPR:$dst, (ineg i64:$src)) ]>;
340
+ []>;
322
341
def NEG_32: NEG_RR<SBF_ALU, SBF_NEG, (outs GPR32:$dst), (ins GPR32:$src),
323
342
"neg32 $dst",
324
- [(set GPR32:$dst, (ineg i32:$src)) ]>;
343
+ []>;
325
344
}
326
345
346
+ // Instruction `neg` exists on SBFv1, but not on SBFv2
347
+ // In SBFv2, the negate operation is done with a subtraction
348
+ def : Pat<(ineg i64:$src), (NEG_64 GPR:$src)>, Requires<[NoSBFv2]>;
349
+ def : Pat<(ineg i32:$src), (NEG_32 GPR32:$src)>, Requires<[NoSBFv2]>;
350
+
351
+ def : Pat<(ineg i64:$src), (SUB_ri GPR:$src, 0)>, Requires<[SBFv2]>;
352
+ def : Pat<(ineg i32:$src), (SUB_ri_32 GPR32:$src, 0)>, Requires<[SBFv2]>;
353
+
354
+
327
355
class LD_IMM64<bits<4> Pseudo, string Mnemonic>
328
356
: TYPE_LD_ST<SBF_IMM.Value, SBF_DW.Value,
329
357
(outs GPR:$dst),
0 commit comments