diff --git a/llvm/lib/Target/SBF/SBFInstrFormats.td b/llvm/lib/Target/SBF/SBFInstrFormats.td index 2560b4b76363f..bb42a6141e6d0 100644 --- a/llvm/lib/Target/SBF/SBFInstrFormats.td +++ b/llvm/lib/Target/SBF/SBFInstrFormats.td @@ -38,6 +38,7 @@ def SBF_OR : SBFArithOp<0x4>; def SBF_AND : SBFArithOp<0x5>; def SBF_LSH : SBFArithOp<0x6>; def SBF_RSH : SBFArithOp<0x7>; +def SBF_NEG : SBFArithOp<0x8>; def SBF_XOR : SBFArithOp<0xa>; def SBF_MOV : SBFArithOp<0xb>; def SBF_ARSH : SBFArithOp<0xc>; diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index 80d981efb2659..c91a7fbe9bed5 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -54,6 +54,8 @@ def SBFIsBigEndian : Predicate<"!CurDAG->getDataLayout().isLittleEndian()">; def SBFHasALU32 : Predicate<"Subtarget->getHasAlu32()">; def SBFNoALU32 : Predicate<"!Subtarget->getHasAlu32()">; def SBFSubtargetSolana : Predicate<"Subtarget->isSolana()">; +def SBFv2 : Predicate<"Subtarget->isSBFv2()">; +def NoSBFv2 : Predicate<"!Subtarget->isSBFv2()">; def brtarget : Operand { let PrintMethod = "printBrTargetOperand"; @@ -263,12 +265,7 @@ class ALU_RR { - defvar DoSwap = !eq(OpNode, sub); - defvar RegImmPat = !if(DoSwap, (OpNode i64immSExt32:$imm, GPR:$src2), - (OpNode GPR:$src2, i64immSExt32:$imm)); - defvar RegImmPat32 = !if(DoSwap,(OpNode i32immSExt32:$imm, GPR32:$src2), - (OpNode GPR32:$src2, i32immSExt32:$imm)); +multiclass ALU { def _rr : ALU_RR { (outs GPR:$dst), (ins GPR:$src2, i64imm:$imm), Mnemonic # "64 $dst, $imm", - [(set GPR:$dst, RegImmPat)]>; + !if(UseImmPat, + [(set GPR:$dst, + (OpNode GPR:$src2, i64immSExt32:$imm))], [])>; def _rr_32 : ALU_RR { (outs GPR32:$dst), (ins GPR32:$src2, i32imm:$imm), Mnemonic # "32 $dst, $imm", - [(set GPR32:$dst, RegImmPat32)]>; + !if(UseImmPat, + [(set GPR32:$dst, + (OpNode GPR32:$src2, i32immSExt32:$imm))], [])>; } let Constraints = "$dst = $src2" in { let isAsCheapAsAMove = 1 in { defm ADD : ALU; - defm SUB : ALU; + defm SUB : ALU; defm OR : ALU; defm AND : ALU; defm SLL : ALU; @@ -311,6 +312,46 @@ let Constraints = "$dst = $src2" in { } } +// Special case for SBFv2 +// In SBFv1, `sub reg, imm` is interpreted as reg = reg - imm, +// but in SBFv2 it means reg = imm - reg +def : Pat<(sub GPR:$src, i64immSExt32:$imm), + (SUB_ri GPR:$src, i64immSExt32:$imm)>, Requires<[NoSBFv2]>; +def : Pat<(sub GPR32:$src, i32immSExt32:$imm), + (SUB_ri_32 GPR32:$src, i32immSExt32:$imm)>, Requires<[NoSBFv2]>; + +def : Pat<(sub i64immSExt32:$imm, GPR:$src), + (SUB_ri GPR:$src, i64immSExt32:$imm)>, Requires<[SBFv2]>; +def : Pat<(sub i32immSExt32:$imm, GPR32:$src), + (SUB_ri_32 GPR32:$src, i32immSExt32:$imm)>, Requires<[SBFv2]>; + +class NEG_RR pattern> + : TYPE_ALU_JMP { + bits<4> dst; + + let Inst{51-48} = dst; + let SBFClass = Class; +} + +let Constraints = "$dst = $src", isAsCheapAsAMove = 1 in { + def NEG_64: NEG_RR; + def NEG_32: NEG_RR; +} + +// Instruction `neg` exists on SBFv1, but not on SBFv2 +// In SBFv2, the negate operation is done with a subtraction +def : Pat<(ineg i64:$src), (NEG_64 GPR:$src)>, Requires<[NoSBFv2]>; +def : Pat<(ineg i32:$src), (NEG_32 GPR32:$src)>, Requires<[NoSBFv2]>; + +def : Pat<(ineg i64:$src), (SUB_ri GPR:$src, 0)>, Requires<[SBFv2]>; +def : Pat<(ineg i32:$src), (SUB_ri_32 GPR32:$src, 0)>, Requires<[SBFv2]>; + + class LD_IMM64 Pseudo, string Mnemonic> : TYPE_LD_ST; + (XFADDW32 ADDRri:$addr, (NEG_32 GPR32:$val))>; def : Pat<(atomic_load_sub_64 ADDRri:$addr, GPR:$val), - (XFADDD ADDRri:$addr, (SUB_ri GPR:$val, 0))>; + (XFADDD ADDRri:$addr, (NEG_64 GPR:$val))>; let Predicates = [SBFSubtargetSolana], usesCustomInserter = 1, isCodeGenOnly = 1 in { def ATOMIC_FENCE : Pseudo< diff --git a/llvm/lib/Target/SBF/SBFSubtarget.cpp b/llvm/lib/Target/SBF/SBFSubtarget.cpp index e49f6a31c7ba1..deb57c2d539ae 100644 --- a/llvm/lib/Target/SBF/SBFSubtarget.cpp +++ b/llvm/lib/Target/SBF/SBFSubtarget.cpp @@ -42,6 +42,7 @@ void SBFSubtarget::initializeEnvironment(const Triple &TT) { HasDynamicFrames = false; HasSdiv = false; UseDwarfRIS = false; + IsSBFv2 = false; } void SBFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { @@ -64,8 +65,10 @@ void SBFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { HasAlu32 = true; } - if (CPU == "sbfv2" && !HasDynamicFrames) { - report_fatal_error("sbfv2 requires dynamic-frames\n", false); + if (CPU == "sbfv2") { + IsSBFv2 = true; + if (!HasDynamicFrames) + report_fatal_error("sbfv2 requires dynamic-frames\n", false); } } diff --git a/llvm/lib/Target/SBF/SBFSubtarget.h b/llvm/lib/Target/SBF/SBFSubtarget.h index 2334bbb1bb89b..613e0168f45c3 100644 --- a/llvm/lib/Target/SBF/SBFSubtarget.h +++ b/llvm/lib/Target/SBF/SBFSubtarget.h @@ -72,13 +72,17 @@ class SBFSubtarget : public SBFGenSubtargetInfo { // whether we should enable MCAsmInfo DwarfUsesRelocationsAcrossSections bool UseDwarfRIS; + // whether we are targeting SBFv2 + bool IsSBFv2; + public: // This constructor initializes the data members to match that // of the specified triple. SBFSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, const TargetMachine &TM); - SBFSubtarget &initializeSubtargetDependencies(const Triple &TT, StringRef CPU, StringRef FS); + SBFSubtarget &initializeSubtargetDependencies(const Triple &TT, StringRef CPU, + StringRef FS); // ParseSubtargetFeatures - Parses features string setting specified // subtarget options. Definition of function is auto generated by tblgen. @@ -90,6 +94,7 @@ class SBFSubtarget : public SBFGenSubtargetInfo { bool getHasDynamicFrames() const { return HasDynamicFrames; } bool getHasSdiv() const { return HasSdiv; } bool getUseDwarfRIS() const { return UseDwarfRIS; } + bool isSBFv2() const { return IsSBFv2; } const SBFInstrInfo *getInstrInfo() const override { return &InstrInfo; } const SBFFrameLowering *getFrameLowering() const override { @@ -105,6 +110,6 @@ class SBFSubtarget : public SBFGenSubtargetInfo { return &InstrInfo.getRegisterInfo(); } }; -} // End llvm namespace +} // namespace llvm #endif diff --git a/llvm/test/CodeGen/SBF/sub_reversed_immediate.ll b/llvm/test/CodeGen/SBF/sub_reversed_immediate.ll index 3a2059f9602b0..8040eb767b728 100644 --- a/llvm/test/CodeGen/SBF/sub_reversed_immediate.ll +++ b/llvm/test/CodeGen/SBF/sub_reversed_immediate.ll @@ -1,31 +1,68 @@ -; RUN: llc < %s -march=sbf -mattr=+alu32 | FileCheck %s +; RUN: llc < %s -march=sbf -mattr=+alu32 | FileCheck --check-prefix=CHECK-v1 %s +; RUN: llc < %s -march=sbf -mattr=+alu32 -mcpu=sbfv2 | FileCheck --check-prefix=CHECK-v2 %s ; Function Attrs: norecurse nounwind readnone -define dso_local i64 @sub_ri_64(i64 %a) #0 { +define dso_local i64 @sub_imm_minus_reg_64(i64 %a) #0 { entry: -; CHECK-LABEL: sub_ri_64: +; CHECK-LABEL: sub_imm_minus_reg_64: %sub = sub nsw i64 50, %a -; CHECK: sub64 r{{[0-9]+}}, 50 + +; CHECK-v1: mov64 r{{[0-9]+}}, 50 +; CHECK-v1: sub64 r{{[0-9]+}}, r{{[0-9]+}} + +; CHECK-v2: sub64 r{{[0-9]+}}, 50 ret i64 %sub } ; Function Attrs: norecurse nounwind readnone -define dso_local i32 @sub_ri_32(i32 %a) #0 { +define dso_local i64 @sub_reg_minus_imm_64(i64 %a) #0 { entry: -; CHECK-LABEL: sub_ri_32: +; CHECK-LABEL: sub_reg_minus_imm_64: + %t = sub nsw i64 %a, 50 +; CHECK-v1: add64 r{{[0-9]+}}, -50 + +; CHECK-v2: add64 r{{[0-9]+}}, -50 + ret i64 %t +} + + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @sub_imm_minus_reg_32(i32 %a) #0 { +entry: +; CHECK-LABEL: sub_imm_minus_reg_32: %sub = sub nsw i32 50, %a -; CHECK: sub32 w{{[0-9]+}}, 50 + +; CHECK-v1: mov32 w{{[0-9]+}}, 50 +; CHECK-v1: sub32 w{{[0-9]+}}, w{{[0-9]+}} + +; CHECK-v2: sub32 w{{[0-9]+}}, 50 + ret i32 %sub } +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @sub_reg_minus_imm_32(i32 %a) #0 { +entry: +; CHECK-LABEL: sub_reg_minus_imm_32: + %t = sub nsw i32 %a, 50 + +; CHECK-v1: add32 w{{[0-9]+}}, -50 + +; CHECK-v2: add32 w{{[0-9]+}}, -50 + ret i32 %t +} + ; Function Attrs: norecurse nounwind readnone define dso_local i64 @neg_64(i64 %a) #0 { entry: ; CHECK-LABEL: neg_64: %sub = sub nsw i64 0, %a -; CHECK: sub64 r{{[0-9]+}}, 0 + +; CHECK-v1: neg64 r{{[0-9]+}} +; CHECK-v2: sub64 r{{[0-9]+}}, 0 + ret i64 %sub } @@ -34,6 +71,9 @@ define dso_local i32 @neg_32(i32 %a) #0 { entry: ; CHECK-LABEL: neg_32: %sub = sub nsw i32 0, %a -; CHECK: sub32 w{{[0-9]+}}, 0 + +; CHECK-v1: neg32 w{{[0-9]+}} +; CHECK-v2: sub32 w{{[0-9]+}}, 0 + ret i32 %sub } diff --git a/llvm/test/MC/Disassembler/SBF/sbf-alu.txt b/llvm/test/MC/Disassembler/SBF/sbf-alu.txt index b819955ffc038..148512dda5727 100644 --- a/llvm/test/MC/Disassembler/SBF/sbf-alu.txt +++ b/llvm/test/MC/Disassembler/SBF/sbf-alu.txt @@ -224,6 +224,14 @@ +# CHECK-NEW: neg64 r9 +0x87,0x09,0x00,0x00,0x00,0x00,0x00,0x00 + +# CHECK-NEW: neg32 w6 +0x84,0x06,0x00,0x00,0x00,0x00,0x00,0x00 + + + # CHECK-NEW: mov64 r0, r9 0xbf,0x90,0x00,0x00,0x00,0x00,0x00,0x00 diff --git a/llvm/test/MC/SBF/insn-unit-32.s b/llvm/test/MC/SBF/insn-unit-32.s index c5ad1eb0cf72c..198b4dcae7955 100644 --- a/llvm/test/MC/SBF/insn-unit-32.s +++ b/llvm/test/MC/SBF/insn-unit-32.s @@ -3,10 +3,12 @@ # RUN: llvm-objdump --mattr=+alu32 -d -r %t | FileCheck %s // ======== BPF_ALU Class ======== + neg32 w1 // BPF_NEG add32 w0, w1 // BPF_ADD | BPF_X sub32 w1, w2 // BPF_SUB | BPF_X mul32 w2, w3 // BPF_MUL | BPF_X div32 w3, w4 // BPF_DIV | BPF_X +// CHECK: 84 01 00 00 00 00 00 00 neg32 w1 // CHECK: 0c 10 00 00 00 00 00 00 add32 w0, w1 // CHECK: 1c 21 00 00 00 00 00 00 sub32 w1, w2 // CHECK: 2c 32 00 00 00 00 00 00 mul32 w2, w3 diff --git a/llvm/test/MC/SBF/insn-unit.s b/llvm/test/MC/SBF/insn-unit.s index 8c0397af16fce..3d85a9c9394e4 100644 --- a/llvm/test/MC/SBF/insn-unit.s +++ b/llvm/test/MC/SBF/insn-unit.s @@ -107,6 +107,7 @@ // CHECK: 3f 43 00 00 00 00 00 00 div64 r3, r4 Llabel0 : + neg64 r2 // BPF_NEG or64 r4, r5 // BPF_OR | BPF_X and64 r5, r6 // BPF_AND | BPF_X lsh64 r6, r7 // BPF_LSH | BPF_X @@ -115,6 +116,7 @@ Llabel0 : mov64 r9, r10 // BPF_MOV | BPF_X arsh64 r10, r0 // BPF_ARSH | BPF_X // CHECK: : +// CHECK: 87 02 00 00 00 00 00 00 neg64 r2 // CHECK: 4f 54 00 00 00 00 00 00 or64 r4, r5 // CHECK: 5f 65 00 00 00 00 00 00 and64 r5, r6 // CHECK: 6f 76 00 00 00 00 00 00 lsh64 r6, r7 diff --git a/llvm/test/MC/SBF/sbf-alu.s b/llvm/test/MC/SBF/sbf-alu.s index ea35f487cebdb..919e323a22e5b 100644 --- a/llvm/test/MC/SBF/sbf-alu.s +++ b/llvm/test/MC/SBF/sbf-alu.s @@ -294,6 +294,16 @@ arsh32 w5, -123 +# CHECK-OBJ-NEW: neg64 r9 +# CHECK-ASM-NEW: encoding: [0x87,0x09,0x00,0x00,0x00,0x00,0x00,0x00] +neg64 r9 + +# CHECK-OBJ-NEW: neg32 w6 +# CHECK-ASM-NEW: encoding: [0x84,0x06,0x00,0x00,0x00,0x00,0x00,0x00] +neg32 w6 + + + # CHECK-OBJ-NEW: mov64 r0, r9 # CHECK-ASM-NEW: encoding: [0xbf,0x90,0x00,0x00,0x00,0x00,0x00,0x00] mov64 r0, r9