From 6b5b13e1271b2375b181a15cabfafe3c59722d34 Mon Sep 17 00:00:00 2001 From: Lucas Steuernagel Date: Sat, 8 Nov 2025 11:59:32 -0300 Subject: [PATCH] Implment JMP32 instruction class --- .../SBF/Disassembler/SBFDisassembler.cpp | 5 +- llvm/lib/Target/SBF/SBFISelLowering.cpp | 27 ++- llvm/lib/Target/SBF/SBFISelLowering.h | 2 + llvm/lib/Target/SBF/SBFInstrFormats.td | 1 + llvm/lib/Target/SBF/SBFInstrInfo.cpp | 121 ++++------ llvm/lib/Target/SBF/SBFInstrInfo.td | 78 ++++++- llvm/lib/Target/SBF/SBFSubtarget.cpp | 1 + llvm/lib/Target/SBF/SBFSubtarget.h | 5 + llvm/lib/Target/SBF/SBFTargetFeatures.td | 4 +- llvm/test/CodeGen/SBF/jmp32_branch.ll | 212 ++++++++++++++++++ llvm/test/CodeGen/SBF/jmp32_select.ll | 165 ++++++++++++++ llvm/test/MC/Disassembler/SBF/sbf-jmp.txt | 42 ++++ llvm/test/MC/Disassembler/SBF/sbf-pqr.txt | 2 +- llvm/test/MC/SBF/insn-unit-32.s | 48 ++++ llvm/test/MC/SBF/sbf-jmp-32.s | 67 ++++++ llvm/test/MC/SBF/sbf-pqr.s | 4 +- 16 files changed, 680 insertions(+), 104 deletions(-) create mode 100644 llvm/test/CodeGen/SBF/jmp32_branch.ll create mode 100644 llvm/test/CodeGen/SBF/jmp32_select.ll create mode 100644 llvm/test/MC/SBF/sbf-jmp-32.s diff --git a/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp b/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp index 49fd5376ed235..58b8ced8fe82e 100644 --- a/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp +++ b/llvm/lib/Target/SBF/Disassembler/SBFDisassembler.cpp @@ -40,7 +40,7 @@ class SBFDisassembler : public MCDisassembler { SBF_STX = 0x3, SBF_ALU = 0x4, SBF_JMP = 0x5, - SBF_PQR = 0x6, + SBF_PQR_OR_JMP32 = 0x6, SBF_ALU64 = 0x7 }; @@ -215,6 +215,9 @@ DecodeStatus SBFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, Result = decodeInstruction(DecoderTableSBFv264, Instr, Insn, Address, this, STI); + } else if (InstClass == SBF_PQR_OR_JMP32 && !STI.hasFeature(SBF::FeaturePqrInstr)) { + Result = decodeInstruction(DecoderTableSBFv364, + Instr, Insn, Address, this, STI); } else Result = diff --git a/llvm/lib/Target/SBF/SBFISelLowering.cpp b/llvm/lib/Target/SBF/SBFISelLowering.cpp index f6b7878069919..62bad884bfa44 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.cpp +++ b/llvm/lib/Target/SBF/SBFISelLowering.cpp @@ -120,10 +120,12 @@ SBFTargetLowering::SBFTargetLowering(const TargetMachine &TM, if (STI.getHasAlu32()) { setOperationAction(ISD::BSWAP, MVT::i32, Promote); setOperationAction(ISD::BR_CC, MVT::i32, Custom); - setOperationAction(ISD::CTTZ, MVT::i32, Expand); - setOperationAction(ISD::CTLZ, MVT::i32, Expand); - setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); - setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); + if (!STI.getHasJmp32()) { + setOperationAction(ISD::CTTZ, MVT::i32, Expand); + setOperationAction(ISD::CTLZ, MVT::i32, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); + } } setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); @@ -168,6 +170,7 @@ SBFTargetLowering::SBFTargetLowering(const TargetMachine &TM, // CPU/Feature control HasAlu32 = STI.getHasAlu32(); + HasJmp32 = STI.getHasJmp32(); SBFRegisterInfo::FrameLength = 4096; } @@ -695,6 +698,11 @@ SDValue SBFTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDValue Dest = Op.getOperand(4); SDLoc DL(Op); + if (getHasJmp32()) { + return DAG.getNode(SBFISD::BR_CC, DL, Op.getValueType(), Chain, LHS, RHS, + DAG.getConstant(CC, DL, LHS.getValueType()), Dest); + } + bool IsSignedCmp = (CC == ISD::SETGT || CC == ISD::SETGE || CC == ISD::SETLT || @@ -1005,7 +1013,10 @@ SBFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, switch (CC) { #define SET_NEWCC(X, Y) \ case ISD::X: \ - NewCC = isSelectRROp ? SBF::Y##_rr : SBF::Y##_ri; \ + if (is32BitCmp && HasJmp32) \ + NewCC = isSelectRROp ? SBF::Y##_rr_32 : SBF::Y##_ri_32; \ + else \ + NewCC = isSelectRROp ? SBF::Y##_rr : SBF::Y##_ri; \ break SET_NEWCC(SETGT, JSGT); SET_NEWCC(SETUGT, JUGT); @@ -1027,17 +1038,17 @@ SBFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, CC == ISD::SETLT || CC == ISD::SETLE); - // SBF at the moment only has 64-bit comparison. Any 32-bit comparison needs + // When JMP32 is not available, any 32-bit comparison needs // to be promoted. If we are comparing against an immediate value, we must // sign extend the registers. Likewise for signed comparisons. Unsigned // comparisons will zero extent registers. - if (is32BitCmp) + if (is32BitCmp && !HasJmp32) LHS = EmitSubregExt(MI, BB, LHS, isSignedCmp || !isSelectRROp); if (isSelectRROp) { Register RHS = MI.getOperand(2).getReg(); - if (is32BitCmp) + if (is32BitCmp && !HasJmp32) RHS = EmitSubregExt(MI, BB, RHS, isSignedCmp); BuildMI(BB, DL, TII.get(NewCC)).addReg(LHS).addReg(RHS).addMBB(Copy1MBB); diff --git a/llvm/lib/Target/SBF/SBFISelLowering.h b/llvm/lib/Target/SBF/SBFISelLowering.h index 4a01c3f3ea556..b5843c1413647 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.h +++ b/llvm/lib/Target/SBF/SBFISelLowering.h @@ -62,6 +62,7 @@ class SBFTargetLowering : public TargetLowering { MachineBasicBlock *BB) const override; bool getHasAlu32() const { return HasAlu32; } + bool getHasJmp32() const { return HasJmp32; } EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override; @@ -71,6 +72,7 @@ class SBFTargetLowering : public TargetLowering { private: // Control Instruction Selection Features bool HasAlu32; + bool HasJmp32; SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/SBF/SBFInstrFormats.td b/llvm/lib/Target/SBF/SBFInstrFormats.td index 8821ed39b3375..0327593552e4f 100644 --- a/llvm/lib/Target/SBF/SBFInstrFormats.td +++ b/llvm/lib/Target/SBF/SBFInstrFormats.td @@ -17,6 +17,7 @@ def SBF_STX : SBFOpClass<0x3>; def SBF_ALU : SBFOpClass<0x4>; def SBF_JMP : SBFOpClass<0x5>; def SBF_PQR : SBFOpClass<0x6>; +def SBF_JMP32 : SBFOpClass<0x6>; def SBF_ALU64 : SBFOpClass<0x7>; def SBF_LD_V2 : SBFOpClass<0x4>; diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.cpp b/llvm/lib/Target/SBF/SBFInstrInfo.cpp index ef98d0c9bceff..bcb2537e19782 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.cpp +++ b/llvm/lib/Target/SBF/SBFInstrInfo.cpp @@ -28,26 +28,22 @@ static inline bool isUncondBranchOpcode(int Opc) { return Opc == SBF::JMP; } static inline bool isCondBranchOpcode(int Opc) { switch (Opc) { - case SBF::JEQ_ri: - case SBF::JEQ_rr: - case SBF::JUGT_ri: - case SBF::JUGT_rr: - case SBF::JUGE_ri: - case SBF::JUGE_rr: - case SBF::JNE_ri: - case SBF::JNE_rr: - case SBF::JSGT_ri: - case SBF::JSGT_rr: - case SBF::JSGE_ri: - case SBF::JSGE_rr: - case SBF::JULT_ri: - case SBF::JULT_rr: - case SBF::JULE_ri: - case SBF::JULE_rr: - case SBF::JSLT_ri: - case SBF::JSLT_rr: - case SBF::JSLE_ri: - case SBF::JSLE_rr: +#define BRANCH_INSTR(X) \ + case SBF::X##_ri: \ + case SBF::X##_rr: \ + case SBF::X##_ri_32: \ + case SBF::X##_rr_32: \ + + BRANCH_INSTR(JEQ) + BRANCH_INSTR(JNE) + BRANCH_INSTR(JUGT) + BRANCH_INSTR(JUGE) + BRANCH_INSTR(JSGT) + BRANCH_INSTR(JSGE) + BRANCH_INSTR(JULT) + BRANCH_INSTR(JULE) + BRANCH_INSTR(JSLT) + BRANCH_INSTR(JSLE) return true; default: return false; @@ -388,66 +384,31 @@ bool SBFInstrInfo::reverseBranchCondition( switch (Cond[0].getImm()) { default: llvm_unreachable("Unknown conditional branch!"); - case SBF::JEQ_ri: - Cond[0].setImm(SBF::JNE_ri); - break; - case SBF::JEQ_rr: - Cond[0].setImm(SBF::JNE_rr); - break; - case SBF::JUGT_ri: - Cond[0].setImm(SBF::JULE_ri); - break; - case SBF::JUGT_rr: - Cond[0].setImm(SBF::JULE_rr); - break; - case SBF::JUGE_ri: - Cond[0].setImm(SBF::JULT_ri); - break; - case SBF::JUGE_rr: - Cond[0].setImm(SBF::JULT_rr); - break; - case SBF::JNE_ri: - Cond[0].setImm(SBF::JEQ_ri); - break; - case SBF::JNE_rr: - Cond[0].setImm(SBF::JEQ_rr); - break; - case SBF::JSGT_ri: - Cond[0].setImm(SBF::JSLE_ri); - break; - case SBF::JSGT_rr: - Cond[0].setImm(SBF::JSLE_rr); - break; - case SBF::JSGE_ri: - Cond[0].setImm(SBF::JSLT_ri); - break; - case SBF::JSGE_rr: - Cond[0].setImm(SBF::JSLT_rr); - break; - case SBF::JULT_ri: - Cond[0].setImm(SBF::JUGE_ri); - break; - case SBF::JULT_rr: - Cond[0].setImm(SBF::JUGE_rr); - break; - case SBF::JULE_ri: - Cond[0].setImm(SBF::JUGT_ri); - break; - case SBF::JULE_rr: - Cond[0].setImm(SBF::JUGT_rr); - break; - case SBF::JSLT_ri: - Cond[0].setImm(SBF::JSGE_ri); - break; - case SBF::JSLT_rr: - Cond[0].setImm(SBF::JSGE_rr); - break; - case SBF::JSLE_ri: - Cond[0].setImm(SBF::JSGT_ri); - break; - case SBF::JSLE_rr: - Cond[0].setImm(SBF::JSGT_rr); - break; + +#define REVERSE_X_FOR_Y(X, Y) \ + case SBF::X##_ri: \ + Cond[0].setImm(SBF::Y##_ri); \ + break; \ + case SBF::X##_rr: \ + Cond[0].setImm(SBF::Y##_rr); \ + break; \ + case SBF::X##_ri_32: \ + Cond[0].setImm(SBF::Y##_ri_32); \ + break; \ + case SBF::X##_rr_32: \ + Cond[0].setImm(SBF::Y##_rr_32); \ + break; \ + + REVERSE_X_FOR_Y(JEQ, JNE) + REVERSE_X_FOR_Y(JNE, JEQ) + REVERSE_X_FOR_Y(JUGT, JULE) + REVERSE_X_FOR_Y(JUGE, JULT) + REVERSE_X_FOR_Y(JSGT, JSLE) + REVERSE_X_FOR_Y(JSGE, JSLT) + REVERSE_X_FOR_Y(JULT, JUGE) + REVERSE_X_FOR_Y(JULE, JUGT) + REVERSE_X_FOR_Y(JSLT, JSGE) + REVERSE_X_FOR_Y(JSLE, JSGT) } return false; diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index 53f40a1b9daeb..833a0dda543ca 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -133,6 +133,26 @@ def SBF_CC_LTU : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETULT);}]>; def SBF_CC_LEU : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETULE);}]>; +def SBF_CC_EQ_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETEQ);}]>; +def SBF_CC_NE_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETNE);}]>; +def SBF_CC_GE_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETGE);}]>; +def SBF_CC_GT_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETGT);}]>; +def SBF_CC_GTU_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETUGT);}]>; +def SBF_CC_GEU_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETUGE);}]>; +def SBF_CC_LE_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETLE);}]>; +def SBF_CC_LT_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETLT);}]>; +def SBF_CC_LTU_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETULT);}]>; +def SBF_CC_LEU_32 : PatLeaf<(i32 imm), + [{return (N->getZExtValue() == ISD::SETULE);}]>; // For arithmetic and jump instructions the 8-bit 'code' // field is divided into three parts: @@ -217,23 +237,59 @@ class JMP_RI let SBFClass = SBF_JMP; } -multiclass J { +class JMP_RR_32 + : TYPE_ALU_JMP { + bits<4> dst; + bits<4> src; + bits<16> BrDst; + + let Inst{55-52} = src; + let Inst{51-48} = dst; + let Inst{47-32} = BrDst; + let SBFClass = SBF_JMP32; +} + +class JMP_RI_32 + : TYPE_ALU_JMP { + bits<4> dst; + bits<16> BrDst; + bits<32> imm; + + let Inst{51-48} = dst; + let Inst{47-32} = BrDst; + let Inst{31-0} = imm; + let SBFClass = SBF_JMP32; +} + +multiclass J { def _rr : JMP_RR; def _ri : JMP_RI; + let DecoderNamespace = "SBFv3" in { + def _rr_32 : JMP_RR_32; + def _ri_32 : JMP_RI_32; + } } let isBranch = 1, isTerminator = 1, hasDelaySlot=0 in { // cmp+goto instructions -defm JEQ : J; -defm JUGT : J; -defm JUGE : J; -defm JNE : J; -defm JSGT : J; -defm JSGE : J; -defm JULT : J; -defm JULE : J; -defm JSLT : J; -defm JSLE : J; +defm JEQ : J; +defm JUGT : J; +defm JUGE : J; +defm JNE : J; +defm JSGT : J; +defm JSGE : J; +defm JULT : J; +defm JULE : J; +defm JSLT : J; +defm JSLE : J; } // ALU instructions diff --git a/llvm/lib/Target/SBF/SBFSubtarget.cpp b/llvm/lib/Target/SBF/SBFSubtarget.cpp index d5fa78ce851bc..24c73ce53432a 100644 --- a/llvm/lib/Target/SBF/SBFSubtarget.cpp +++ b/llvm/lib/Target/SBF/SBFSubtarget.cpp @@ -56,6 +56,7 @@ void SBFSubtarget::initializeEnvironment(const Triple &TT) { NewMemEncoding = false; HasStaticSyscalls = false; IsAbiV2 = false; + HasJmp32 = false; } void SBFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { diff --git a/llvm/lib/Target/SBF/SBFSubtarget.h b/llvm/lib/Target/SBF/SBFSubtarget.h index 73805fa416954..1d65b48727d34 100644 --- a/llvm/lib/Target/SBF/SBFSubtarget.h +++ b/llvm/lib/Target/SBF/SBFSubtarget.h @@ -88,6 +88,10 @@ class SBFSubtarget : public SBFGenSubtargetInfo { // Whether we are using AbiV2 bool IsAbiV2; + // Whether we support JMP32 + // JMP32 support depends on ALU32 being enabled + bool HasJmp32; + std::unique_ptr CallLoweringInfo; std::unique_ptr InstSelector; std::unique_ptr Legalizer; @@ -117,6 +121,7 @@ class SBFSubtarget : public SBFGenSubtargetInfo { bool getHasExplicitSignExt() const { return HasExplicitSignExt; } bool getNewMemEncoding() const { return NewMemEncoding; } bool getHasStaticSyscalls() const { return HasStaticSyscalls; } + bool getHasJmp32() const { return HasJmp32; } const SBFInstrInfo *getInstrInfo() const override { return &InstrInfo; } const SBFFrameLowering *getFrameLowering() const override { return &FrameLowering; diff --git a/llvm/lib/Target/SBF/SBFTargetFeatures.td b/llvm/lib/Target/SBF/SBFTargetFeatures.td index 644e24e1bf4d4..1727605947bf5 100644 --- a/llvm/lib/Target/SBF/SBFTargetFeatures.td +++ b/llvm/lib/Target/SBF/SBFTargetFeatures.td @@ -50,8 +50,10 @@ def FeatureNewMemEncoding : SubtargetFeature<"mem-encoding", "NewMemEncoding", "true", "Enable the new encoding for memory instructions">; def FeatureAbiV2 : SubtargetFeature<"abi-v2", "IsAbiV2", - "true", "Enables AbiV2 in SBF (no-op in LLVM)">; + "true", "Enable AbiV2 in SBF (no-op in LLVM)">; +def FeatureJmp32 : SubtargetFeature<"jmp-32", "HasJmp32", "true", + "Enable the JMP32 instruction class">; class Proc Features> : Processor; diff --git a/llvm/test/CodeGen/SBF/jmp32_branch.ll b/llvm/test/CodeGen/SBF/jmp32_branch.ll new file mode 100644 index 0000000000000..ef68abf245c6a --- /dev/null +++ b/llvm/test/CodeGen/SBF/jmp32_branch.ll @@ -0,0 +1,212 @@ +; RUN: llc -march=sbf -mattr=+alu32,+jmp-32 < %s | FileCheck %s + +define i32 @test_jne(i32 %a, i32 %b) { +; CHECK-LABEL: test_jne + entry: + %cmp1 = icmp eq i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jne32 w0, w2, + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp eq i32 %a, 98 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jne32 w0, 98 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_jeq(i32 %a, i32 %b) { +; CHECK-LABEL: test_jeq + entry: + %cmp1 = icmp ne i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jeq32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp ne i32 %a, 98 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jeq32 w0, 98 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_jugt(i32 %a, i32 %b) { +; CHECK-LABEL: test_jugt + entry: + %cmp1 = icmp ule i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jgt32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp ult i32 %a, 98 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jgt32 w0, 97 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_jult(i32 %a, i32 %b) { +; CHECK-LABEL: test_jult + entry: + %cmp1 = icmp uge i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jlt32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp ugt i32 %a, 98 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jlt32 w0, 99 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_jsgt(i32 %a, i32 %b) { +; CHECK-LABEL: test_jsgt + entry: + %cmp1 = icmp sle i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jsgt32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp slt i32 %a, 98 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jsgt32 w0, 97 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_jslt(i32 %a, i32 %b) { +; CHECK-LABEL: test_jslt + entry: + %cmp1 = icmp sge i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jslt32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp sgt i32 %a, 98 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jslt32 w0, 99 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_juge(i32 %a, i32 %b) { +; CHECK-LABEL: test_juge + entry: + %cmp1 = icmp ult i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jge32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp ult i32 %a, 0 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jge32 w0, 0 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_jule(i32 %a, i32 %b) { +; CHECK-LABEL: test_jule + entry: + %cmp1 = icmp ugt i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jle32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp ugt i32 %a, -1 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jle32 w0, -1 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_jsge(i32 %a, i32 %b) { +; CHECK-LABEL: test_jsge + entry: + %cmp1 = icmp slt i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jsge32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp slt i32 %a, -2147483648 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jsge32 w0, -2147483648 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + +define i32 @test_jsle(i32 %a, i32 %b) { +; CHECK-LABEL: test_jsle + entry: + %cmp1 = icmp sgt i32 %a, %b + br i1 %cmp1, label %ret_now, label %cmp_imm +; CHECK: jsle32 w0, w2 + ret_now: + %res1 = add i32 %a, %b + ret i32 %res1 + cmp_imm: + %cmp2 = icmp slt i32 %a, 0 + br i1 %cmp2, label %do_sub, label %do_mul +; CHECK: jsle32 w0, -1 + do_sub: + %res2 = sub i32 %a, %b + ret i32 %res2 + do_mul: + %res3 = mul i32 %a, %b + ret i32 %res3 +} + diff --git a/llvm/test/CodeGen/SBF/jmp32_select.ll b/llvm/test/CodeGen/SBF/jmp32_select.ll new file mode 100644 index 0000000000000..e80588d568820 --- /dev/null +++ b/llvm/test/CodeGen/SBF/jmp32_select.ll @@ -0,0 +1,165 @@ +; RUN: llc -march=sbf -mattr=+alu32,+jmp-32 < %s | FileCheck %s + +define i32 @test_jne_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jne_reg + %cmp1 = icmp ne i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jne32 w1, w2 + ret i32 %res +} + +define i32 @test_jne_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jne_imm + %cmp1 = icmp ne i32 %a, 78 + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jne32 w1, 78 + ret i32 %res +} + +define i32 @test_jeq_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jeq_reg + %cmp1 = icmp eq i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jeq32 w1, w2 + ret i32 %res +} + +define i32 @test_jeq_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jeq_imm + %cmp1 = icmp eq i32 %a, 78 + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jeq32 w1, 78 + ret i32 %res +} + +define i32 @test_jugt_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jugt_reg + %cmp1 = icmp ugt i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jgt32 w1, w2 + ret i32 %res +} + +define i32 @test_jugt_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABRL: test_jugt_imm + %cmp1 = icmp ugt i32 %a, 78 + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jgt32 w1, 78 + ret i32 %res +} + +define i32 @test_juge_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_juge_reg + %cmp1 = icmp uge i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jge32 w1, w2 + ret i32 %res +} + +define i32 @test_juge_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; uge is always converted to jgt +; CHECK: test_juge_imm + %cmp1 = icmp uge i32 %a, 2 + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jgt32 w1, 1 + ret i32 %res +} + +define i32 @test_jsgt_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABRL: test_jsgt_reg + %cmp1 = icmp sgt i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jsgt32 w1, w2 + ret i32 %res +} + +define i32 @test_jsgt_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jsgt_imm + %cmp1 = icmp sgt i32 %a, 78 + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jsgt32 w1, 78 + ret i32 %res +} + +define i32 @test_jsge_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jsge_reg + %cmp1 = icmp sge i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jsge32 w1, w2 + ret i32 %res +} + +define i32 @test_jsge_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; sge is always converted to jsgt +; CHECK-LABEL: test_jsge_imm + %cmp1 = icmp sge i32 %a, 5 + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jsgt32 w1, 4 + ret i32 %res +} + +define i32 @test_jult_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jult_reg + %cmp1 = icmp ult i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jlt32 w1, w2 + ret i32 %res +} + +define i32 @test_jult_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jult_imm + %cmp1 = icmp ult i32 %a, 78 + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jlt32 w1, 78 + ret i32 %res +} + +define i32 @test_jule_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jule_reg + %cmp1 = icmp ule i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jle32 w1, w2 + ret i32 %res +} + +define i32 @test_jule_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; ule is always converted to jlt +; CHECK-LABEL: test_jule_imm + %cmp1 = icmp ule i32 %a, 20 + %res1 = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jlt32 w1, 21 + ret i32 %res1 +} + +define i32 @test_jslt_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jslt_reg + %cmp1 = icmp slt i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jslt32 w1, w2 + ret i32 %res +} + +define i32 @test_jslt_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jslt_imm + %cmp1 = icmp slt i32 %a, 20 + %res1 = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jslt32 w1, 20 + ret i32 %res1 +} + +define i32 @test_jsle_reg(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: test_jsle_reg + %cmp1 = icmp sle i32 %a, %b + %res = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jsle32 w1, w2 + ret i32 %res +} + +define i32 @test_jsle_imm(i32 %a, i32 %b, i32 %c, i32 %d) { +; sle is always converted to jslt +; CHECK-LABEL: test_jsle_imm + %cmp1 = icmp sle i32 %a, 20 + %res1 = select i1 %cmp1, i32 %c, i32 %d +; CHECK: jslt32 w1, 21 + ret i32 %res1 +} \ No newline at end of file diff --git a/llvm/test/MC/Disassembler/SBF/sbf-jmp.txt b/llvm/test/MC/Disassembler/SBF/sbf-jmp.txt index cdd850b619b1f..8423f5938e4d0 100644 --- a/llvm/test/MC/Disassembler/SBF/sbf-jmp.txt +++ b/llvm/test/MC/Disassembler/SBF/sbf-jmp.txt @@ -118,3 +118,45 @@ # CHECK-NEW: exit 0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + +# CHECK-NEW: jeq32 w6, w2, +8 +# CHECK-NEW: jne32 w6, w2, +8 +# CHECK-NEW: jgt32 w6, w2, +8 +# CHECK-NEW: jge32 w6, w2, +8 +# CHECK-NEW: jlt32 w6, w2, +8 +# CHECK-NEW: jle32 w6, w2, +8 +# CHECK-NEW: jsgt32 w6, w2, +8 +# CHECK-NEW: jsge32 w6, w2, +8 +# CHECK-NEW: jslt32 w6, w2, +8 +# CHECK-NEW: jsle32 w6, w2, +8 +0x1e,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0x5e,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0x2e,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0x3e,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0xae,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0xbe,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0x6e,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0x7e,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0xce,0x26,0x08,0x00,0x00,0x00,0x00,0x00 +0xde,0x26,0x08,0x00,0x00,0x00,0x00,0x00 + +# CHECK-NEW: jeq32 w5, -123, +8 +# CHECK-NEW: jne32 w5, -123, +8 +# CHECK-NEW: jgt32 w5, -123, +8 +# CHECK-NEW: jge32 w5, -123, +8 +# CHECK-NEW: jlt32 w5, -123, +8 +# CHECK-NEW: jle32 w5, -123, +8 +# CHECK-NEW: jsgt32 w5, -123, +8 +# CHECK-NEW: jsge32 w5, -123, +8 +# CHECK-NEW: jslt32 w5, -123, +8 +# CHECK-NEW: jsle32 w5, -123, +8 +0x16,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0x56,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0x26,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0x36,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0xa6,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0xb6,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0x66,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0x76,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0xc6,0x05,0x08,0x00,0x85,0xff,0xff,0xff +0xd6,0x05,0x08,0x00,0x85,0xff,0xff,0xff \ No newline at end of file diff --git a/llvm/test/MC/Disassembler/SBF/sbf-pqr.txt b/llvm/test/MC/Disassembler/SBF/sbf-pqr.txt index 5123ef093b9a5..5cf4a1fe7e459 100644 --- a/llvm/test/MC/Disassembler/SBF/sbf-pqr.txt +++ b/llvm/test/MC/Disassembler/SBF/sbf-pqr.txt @@ -1,4 +1,4 @@ -# RUN: llvm-mc --disassemble %s -triple=sbf-solana-solana \ +# RUN: llvm-mc --disassemble %s --triple=sbpfv2-solana-solana \ # RUN: | FileCheck %s --check-prefix=CHECK diff --git a/llvm/test/MC/SBF/insn-unit-32.s b/llvm/test/MC/SBF/insn-unit-32.s index a3ebffc61328c..0a2f37a59f25e 100644 --- a/llvm/test/MC/SBF/insn-unit-32.s +++ b/llvm/test/MC/SBF/insn-unit-32.s @@ -54,3 +54,51 @@ // CHECK: b4 09 00 00 01 00 00 00 mov32 w9, 0x1 // CHECK: b4 09 00 00 ff ff ff ff mov32 w9, -0x1 // CHECK: c4 0a 00 00 40 00 00 00 arsh32 w10, 0x40 + + + jeq32 w0, w1, Llabel0 // BPF_JEQ | BPF_X + jne32 w3, w4, Llabel0 // BPF_JNE | BPF_X +// CHECK: 1e 10 0b 00 00 00 00 00 jeq32 w0, w1, +0xb +// CHECK: 5e 43 0a 00 00 00 00 00 jne32 w3, w4, +0xa + + jgt32 w1, w2, Llabel0 // BPF_JGT | BPF_X + jge32 w2, w3, Llabel0 // BPF_JGE | BPF_X + jsgt32 w4, w5, Llabel0 // BPF_JSGT | BPF_X + jsge32 w5, w6, Llabel0 // BPF_JSGE | BPF_X +// CHECK: 2e 21 09 00 00 00 00 00 jgt32 w1, w2, +0x9 +// CHECK: 3e 32 08 00 00 00 00 00 jge32 w2, w3, +0x8 +// CHECK: 6e 54 07 00 00 00 00 00 jsgt32 w4, w5, +0x7 +// CHECK: 7e 65 06 00 00 00 00 00 jsge32 w5, w6, +0x6 + + jlt32 w6, w7, Llabel0 // BPF_JLT | BPF_X + jle32 w7, w8, Llabel0 // BPF_JLE | BPF_X + jslt32 w8, w9, Llabel0 // BPF_JSLT | BPF_X + jsle32 w9, w10, Llabel0 // BPF_JSLE | BPF_X +// CHECK: ae 76 05 00 00 00 00 00 jlt32 w6, w7, +0x5 +// CHECK: be 87 04 00 00 00 00 00 jle32 w7, w8, +0x4 +// CHECK: ce 98 03 00 00 00 00 00 jslt32 w8, w9, +0x3 +// CHECK: de a9 02 00 00 00 00 00 jsle32 w9, w10, +0x2 + + jeq32 w0, 0, Llabel0 // BPF_JEQ | BPF_K + jne32 w3, -1, Llabel0 // BPF_JNE | BPF_K +// CHECK: 16 00 01 00 00 00 00 00 jeq32 w0, 0x0, +0x1 +// CHECK: 56 03 00 00 ff ff ff ff jne32 w3, -0x1, +0x0 + +Llabel0: + jgt32 w1, 64, Llabel0 // BPF_JGT | BPF_K + jge32 w2, 0xffffffff, Llabel0 // BPF_JGE | BPF_K + jsgt32 w4, 0xffffffff, Llabel0 // BPF_JSGT | BPF_K + jsge32 w5, 0x7fffffff, Llabel0 // BPF_JSGE | BPF_K +// CHECK: 26 01 ff ff 40 00 00 00 jgt32 w1, 0x40, -0x1 +// CHECK: 36 02 fe ff ff ff ff ff jge32 w2, -0x1, -0x2 +// CHECK: 66 04 fd ff ff ff ff ff jsgt32 w4, -0x1, -0x3 +// CHECK: 76 05 fc ff ff ff ff 7f jsge32 w5, 0x7fffffff, -0x4 + + jlt32 w6, 0xff, Llabel0 // BPF_JLT | BPF_K + jle32 w7, 0xffff, Llabel0 // BPF_JLE | BPF_K + jslt32 w8, 0, Llabel0 // BPF_JSLT | BPF_K + jsle32 w9, -1, Llabel0 // BPF_JSLE | BPF_K +// CHECK: a6 06 fb ff ff 00 00 00 jlt32 w6, 0xff, -0x5 +// CHECK: b6 07 fa ff ff ff 00 00 jle32 w7, 0xffff, -0x6 +// CHECK: c6 08 f9 ff 00 00 00 00 jslt32 w8, 0x0, -0x7 +// CHECK: d6 09 f8 ff ff ff ff ff jsle32 w9, -0x1, -0x8 \ No newline at end of file diff --git a/llvm/test/MC/SBF/sbf-jmp-32.s b/llvm/test/MC/SBF/sbf-jmp-32.s new file mode 100644 index 0000000000000..a5ede0c6e7927 --- /dev/null +++ b/llvm/test/MC/SBF/sbf-jmp-32.s @@ -0,0 +1,67 @@ +# RUN: llvm-mc %s -triple=sbf-solana-solana --mattr=+alu32,+jmp-32 --show-encoding \ +# RUN: | FileCheck %s --check-prefix=CHECK-ASM-NEW +# RUN: llvm-mc %s -triple=sbf-solana-solana --mattr=+alu32,+jmp32 -filetype=obj \ +# RUN: | llvm-objdump -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-OBJ-NEW %s + +# CHECK-OBJ-NEW: jeq32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jne32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jgt32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jge32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jlt32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jle32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jsgt32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jsge32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jslt32 w6, w2, +0x8 +# CHECK-OBJ-NEW: jsle32 w6, w2, +0x8 +# CHECK-ASM-NEW: encoding: [0x1e,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x5e,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x2e,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x3e,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0xae,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0xbe,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x6e,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0x7e,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0xce,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +# CHECK-ASM-NEW: encoding: [0xde,0x26,0x08,0x00,0x00,0x00,0x00,0x00] +jeq32 w6, w2, +8 +jne32 w6, w2, +8 +jgt32 w6, w2, +8 +jge32 w6, w2, +8 +jlt32 w6, w2, +8 +jle32 w6, w2, +8 +jsgt32 w6, w2, +8 +jsge32 w6, w2, +8 +jslt32 w6, w2, +8 +jsle32 w6, w2, +8 + +# CHECK-OBJ-NEW: jeq32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jne32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jgt32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jge32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jlt32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jle32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jsgt32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jsge32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jslt32 w5, -0x7b, +0x8 +# CHECK-OBJ-NEW: jsle32 w5, -0x7b, +0x8 +# CHECK-ASM-NEW: encoding: [0x16,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0x56,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0x26,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0x36,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0xa6,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0xb6,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0x66,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0x76,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0xc6,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +# CHECK-ASM-NEW: encoding: [0xd6,0x05,0x08,0x00,0x85,0xff,0xff,0xff] +jeq32 w5, -123, +8 +jne32 w5, -123, +8 +jgt32 w5, -123, +8 +jge32 w5, -123, +8 +jlt32 w5, -123, +8 +jle32 w5, -123, +8 +jsgt32 w5, -123, +8 +jsge32 w5, -123, +8 +jslt32 w5, -123, +8 +jsle32 w5, -123, +8 \ No newline at end of file diff --git a/llvm/test/MC/SBF/sbf-pqr.s b/llvm/test/MC/SBF/sbf-pqr.s index d2d1a65a25f8b..7257caeb5cf58 100644 --- a/llvm/test/MC/SBF/sbf-pqr.s +++ b/llvm/test/MC/SBF/sbf-pqr.s @@ -1,6 +1,6 @@ -# RUN: llvm-mc %s -triple=sbf-solana-solana --mcpu=sbfv2 --show-encoding \ +# RUN: llvm-mc %s -triple=sbf-solana-solana --mcpu=v2 --show-encoding \ # RUN: | FileCheck %s --check-prefix=CHECK-ASM-NEW -# RUN: llvm-mc %s -triple=sbf-solana-solana --mcpu=sbfv2 -filetype=obj \ +# RUN: llvm-mc %s -triple=sbf-solana-solana --mcpu=v2 -filetype=obj \ # RUN: | llvm-objdump -d -r --mattr=+alu32 - \ # RUN: | FileCheck --check-prefix=CHECK-OBJ-NEW %s