From f6027704522870bb052e511d1062c296b6a0a7ba Mon Sep 17 00:00:00 2001 From: Lucas Ste <38472950+LucasSte@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:03:04 -0300 Subject: [PATCH] [SOL] Create explicit sign extension instruction (#114) * Create explicit sign extension instruction --- llvm/lib/Target/SBF/SBFISelLowering.cpp | 13 ++- llvm/lib/Target/SBF/SBFInstrInfo.cpp | 12 ++- llvm/lib/Target/SBF/SBFInstrInfo.h | 4 +- llvm/lib/Target/SBF/SBFInstrInfo.td | 59 ++++++++--- llvm/lib/Target/SBF/SBFSubtarget.cpp | 1 + llvm/lib/Target/SBF/SBFSubtarget.h | 4 + llvm/lib/Target/SBF/SBFTargetFeatures.td | 5 +- llvm/test/CodeGen/SBF/explicit-sign-ext.ll | 110 +++++++++++++++++++++ llvm/test/MC/SBF/sbf-alu.s | 8 ++ 9 files changed, 196 insertions(+), 20 deletions(-) create mode 100644 llvm/test/CodeGen/SBF/explicit-sign-ext.ll diff --git a/llvm/lib/Target/SBF/SBFISelLowering.cpp b/llvm/lib/Target/SBF/SBFISelLowering.cpp index ab6837fb72167d..6eb5dd3640cf90 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.cpp +++ b/llvm/lib/Target/SBF/SBFISelLowering.cpp @@ -933,24 +933,29 @@ SBFTargetLowering::EmitSubregExt(MachineInstr &MI, MachineBasicBlock *BB, unsigned Reg, bool isSigned) const { const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i64); - int RShiftOp = isSigned ? SBF::SRA_ri : SBF::SRL_ri; MachineFunction *F = BB->getParent(); DebugLoc DL = MI.getDebugLoc(); MachineRegisterInfo &RegInfo = F->getRegInfo(); if (!isSigned) { + unsigned MovOp = + Subtarget->getHasExplicitSignExt() + ? SBF::MOV_rr : SBF::MOV_32_64; Register PromotedReg0 = RegInfo.createVirtualRegister(RC); - BuildMI(BB, DL, TII.get(SBF::MOV_32_64), PromotedReg0).addReg(Reg); + BuildMI(BB, DL, TII.get(MovOp), PromotedReg0).addReg(Reg); return PromotedReg0; } Register PromotedReg0 = RegInfo.createVirtualRegister(RC); + BuildMI(BB, DL, TII.get(SBF::MOV_32_64), PromotedReg0).addReg(Reg); + if (Subtarget->getHasExplicitSignExt()) + return PromotedReg0; + Register PromotedReg1 = RegInfo.createVirtualRegister(RC); Register PromotedReg2 = RegInfo.createVirtualRegister(RC); - BuildMI(BB, DL, TII.get(SBF::MOV_32_64), PromotedReg0).addReg(Reg); BuildMI(BB, DL, TII.get(SBF::SLL_ri), PromotedReg1) .addReg(PromotedReg0).addImm(32); - BuildMI(BB, DL, TII.get(RShiftOp), PromotedReg2) + BuildMI(BB, DL, TII.get(SBF::SRA_ri), PromotedReg2) .addReg(PromotedReg1).addImm(32); return PromotedReg2; diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.cpp b/llvm/lib/Target/SBF/SBFInstrInfo.cpp index b222513ae2f112..9e7cc61e854727 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.cpp +++ b/llvm/lib/Target/SBF/SBFInstrInfo.cpp @@ -28,6 +28,10 @@ using namespace llvm; SBFInstrInfo::SBFInstrInfo() : SBFGenInstrInfo(SBF::ADJCALLSTACKDOWN, SBF::ADJCALLSTACKUP) {} +void SBFInstrInfo::setHasExplicitSignExt(bool HasExplicitSext) { + this->HasExplicitSignExt = HasExplicitSext; +} + void SBFInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, @@ -35,9 +39,13 @@ void SBFInstrInfo::copyPhysReg(MachineBasicBlock &MBB, if (SBF::GPRRegClass.contains(DestReg, SrcReg)) BuildMI(MBB, I, DL, get(SBF::MOV_rr), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)); - else if (SBF::GPR32RegClass.contains(DestReg, SrcReg)) - BuildMI(MBB, I, DL, get(SBF::MOV_rr_32), DestReg) + else if (SBF::GPR32RegClass.contains(DestReg, SrcReg)) { + unsigned OpCode = + HasExplicitSignExt ? SBF::MOV_rr_32_no_sext_v2 + : SBF::MOV_rr_32_no_sext_v1; + BuildMI(MBB, I, DL, get(OpCode), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)); + } else llvm_unreachable("Impossible reg-to-reg copy"); } diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.h b/llvm/lib/Target/SBF/SBFInstrInfo.h index 0711f216386ab2..5c4afdb2a25789 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.h +++ b/llvm/lib/Target/SBF/SBFInstrInfo.h @@ -58,9 +58,11 @@ class SBFInstrInfo : public SBFGenInstrInfo { MachineBasicBlock *FBB, ArrayRef Cond, const DebugLoc &DL, int *BytesAdded = nullptr) const override; + void setHasExplicitSignExt(bool HasExplicitSext); + private: void expandMEMCPY(MachineBasicBlock::iterator) const; - + bool HasExplicitSignExt; }; } diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index bfce5db3197423..03136325cdca08 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -65,6 +65,8 @@ def SBFNoCallxSrc : Predicate<"!Subtarget->getCallXRegSrc()">; def SBFPqrInstr : Predicate<"Subtarget->getHasPqrClass()">; def SBFNoPqrInstr : Predicate<"!Subtarget->getHasPqrClass()">; def SBFHasStoreImm : Predicate<"Subtarget->getHasStoreImm()">; +def SBFExplicitSignExt : Predicate<"Subtarget->getHasExplicitSignExt()">; +def SBFNoExplicitSignExt : Predicate<"!Subtarget->getHasExplicitSignExt()">; def brtarget : Operand { let PrintMethod = "printBrTargetOperand"; @@ -415,16 +417,26 @@ def MOV_ri : MATH_RI; -def MOV_rr_32 : MATH_RR; + def MOV_ri_32 : MATH_RI; + +let Predicates = [SBFExplicitSignExt], DecoderNamespace = "SBFv2" in { + def MOV_rr_32_no_sext_v2 : MATH_RR; +} + +def MOV_rr_32_no_sext_v1 : MATH_RR, Requires<[SBFNoExplicitSignExt]>; } def FI_ri @@ -993,10 +1005,13 @@ let Constraints = "$dst = $src" in { } } -let isCodeGenOnly = 1 in { +let DecoderNamespace = "SBFv2" in { def MOV_32_64 : MATH_RR; +} + +let isCodeGenOnly = 1 in { def MOV_32_64_addr : MATH_RI, Requires<[SBFNoLddw]>; @@ -1023,19 +1038,39 @@ def : Pat<(SBFWrapper tglobaladdr:$in), (HOR_addr (MOV_32_64_addr tglobaladdr:$in), tglobaladdr:$in)>, Requires<[SBFNoLddw]>; +// SBFv2 sign extension +def : Pat<(i64 (sext GPR32:$src)), + (MOV_32_64 GPR32:$src)>, Requires<[SBFExplicitSignExt]>; +// SBFv1 sign extension def : Pat<(i64 (sext GPR32:$src)), - (SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>; + (SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>, + Requires<[SBFNoExplicitSignExt]>; + +// SBFv2 zero extension +def : Pat<(i64 (zext GPR32:$src)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + GPR32:$src, sub_32)>, Requires<[SBFExplicitSignExt]>; -def : Pat<(i64 (zext GPR32:$src)), (MOV_32_64 GPR32:$src)>; +// SBFv1 zero extension +def : Pat<(i64 (zext GPR32:$src)), (MOV_32_64 GPR32:$src)>, + Requires<[SBFNoExplicitSignExt]>; -// For i64 -> i32 truncation, use the 32-bit subregister directly. +// SBFv2 truncation def : Pat<(i32 (trunc GPR:$src)), - (i32 (EXTRACT_SUBREG GPR:$src, sub_32))>; + (AND_ri_32 (i32 (EXTRACT_SUBREG GPR:$src, sub_32)), + (i32 0xffffffff))>, Requires<[SBFExplicitSignExt]>; + +// SBFv1 truncation +def : Pat<(i32 (trunc GPR:$src)), + (i32 (EXTRACT_SUBREG GPR:$src, sub_32))>, Requires<[SBFNoExplicitSignExt]>; + +// SBFv2 anyext +def : Pat<(i64 (anyext GPR32:$src)), + (MOV_32_64 GPR32:$src)>, Requires<[SBFExplicitSignExt]>; -// For i32 -> i64 anyext, we don't care about the high bits. +// SBFv1 anyext def : Pat<(i64 (anyext GPR32:$src)), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>; + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>, Requires<[SBFNoExplicitSignExt]>; class STORE32 Pattern> : TYPE_LD_ST; +def FeatureExplicitSext : SubtargetFeature<"explicit-sext", "HasExplicitSignExt", + "true", "Enable the explicit sign extension instruction mov32">; + class Proc Features> : Processor; @@ -55,4 +58,4 @@ def : Proc<"v2", []>; def : Proc<"v3", [ALU32]>; def : Proc<"sbfv2", [FeatureDynamicFrames, FeatureRelocAbs64, FeatureStaticSyscalls, FeatureDisableNeg, FeatureReverseSubImm, FeatureDisableLddw, FeatureCallxRegSrc, - FeaturePqrInstr, FeatureCallConv]>; \ No newline at end of file + FeaturePqrInstr, FeatureCallConv, FeatureExplicitSext]>; \ No newline at end of file diff --git a/llvm/test/CodeGen/SBF/explicit-sign-ext.ll b/llvm/test/CodeGen/SBF/explicit-sign-ext.ll new file mode 100644 index 00000000000000..16d93bf12b1a36 --- /dev/null +++ b/llvm/test/CodeGen/SBF/explicit-sign-ext.ll @@ -0,0 +1,110 @@ +; RUN: llc -march=sbf -mattr=+alu32 < %s | FileCheck --check-prefixes=CHECK-v1,CHECK %s +; RUN: llc -march=sbf -mattr=+alu32,+explicit-sext < %s | FileCheck --check-prefixes=CHECK-v2,CHECK %s + + +define dso_local i64 @my_sext(i32 %a) local_unnamed_addr #0 { +entry: +; CHECK-LABEL: my_sext + %res = sext i32 %a to i64 + +; CHECK-v1: mov32 r0, w1 +; CHECK-v1: lsh64 r0, 32 +; CHECK-v1: arsh64 r0, 32 + +; CHECK-v2: mov32 r0, w1 + ret i64 %res +} + +define dso_local i64 @my_zext(i32 %a) local_unnamed_addr #0 { +entry: +; CHECK-LABEL: my_zext + %res = zext i32 %a to i64 + +; CHECK-v1: mov32 r0, w1 +; CHECK-v2: mov64 w0, w1 + + ret i64 %res +} + +define dso_local i32 @my_trunc(i64 %a) local_unnamed_addr #0 { +entry: +; CHECK-LABEL: my_trunc + %res = trunc i64 %a to i32 + +; CHECK-v1: mov64 r0, r1 +; CHECK-v2: mov64 r0, r1 +; CHECK-v2: and32 w0, -1 + ret i32 %res +} + +define dso_local i32 @copy_phys(i32 %a) local_unnamed_addr #0 { +entry: +; CHECK-LABEL: copy_phys + %res = add i32 %a, 2 + %b = sub i32 %res, 5 +; CHECK-v1: mov32 w0, w1 +; CHECK-v2: mov64 w0, w1 + ret i32 %b +} + +define dso_local i32 @select_cc_imm(i32 %a, i32 %c, i32 %d) local_unnamed_addr #0 { +entry: +; CHECK-LABEL: select_cc_imm + %cmp = icmp sgt i32 %a, 10 +; CHECK-v1: mov32 w0, w2 +; CHECK-v2: mov64 w0, w2 + +; CHECK-v1: mov32 r1, w1 +; CHECK-v1: lsh64 r1, 32 +; CHECK-v1: arsh64 r1, 32 +; CHECK-v2: mov32 r1, w1 + + %c.d = select i1 %cmp, i32 %c, i32 %d +; CHECK-v1: mov32 w0, w3 +; CHECK-v2: mov64 w0, w3 + + ret i32 %c.d +} + +define dso_local i32 @select_cc_reg(i32 %a, i32 %b, i32 %c, i32 %d) local_unnamed_addr #0 { +entry: +; CHECK-LABEL: select_cc_reg + %cmp = icmp sgt i32 %a, %b +; CHECK-v1: mov32 w0, w3 +; CHECK-v2: mov64 w0, w3 + +; CHECK-v1: mov32 r1, w1 +; CHECK-v1: lsh64 r1, 32 +; CHECK-v1: arsh64 r1, 32 +; CHECK-v2: mov32 r1, w1 + +; CHECK-v1: mov32 r2, w2 +; CHECK-v1: lsh64 r2, 32 +; CHECK-v1: arsh64 r2, 32 +; CHECK-v2: mov32 r2, w2 + + %c.d = select i1 %cmp, i32 %c, i32 %d +; CHECK-v1: mov32 w0, w4 +; CHECK-v2: mov64 w0, w4 + ret i32 %c.d +} + +define dso_local i64 @select_cc_imm_64(i32 %a, i64 %c, i64 %d) local_unnamed_addr #0 { +entry: +; CHECK-LABEL: select_cc_imm_64 +; CHECK-v1: mov64 r0, r2 + %cmp = icmp sgt i32 %a, 10 + %c.d = select i1 %cmp, i64 %c, i64 %d +; CHECK: mov64 r0, r3 + ret i64 %c.d +} + +define dso_local i64 @select_cc_reg_64(i32 %a, i32 %b, i64 %c, i64 %d) local_unnamed_addr #0 { +entry: +; CHECK-LABEL: select_cc_reg_64 +; CHECK: mov64 r0, r3 + %cmp = icmp sgt i32 %a, %b + %c.d = select i1 %cmp, i64 %c, i64 %d +; CHECK: mov64 r0, r4 + ret i64 %c.d +} \ No newline at end of file diff --git a/llvm/test/MC/SBF/sbf-alu.s b/llvm/test/MC/SBF/sbf-alu.s index 7e29513cbf2dad..e45f81211a7877 100644 --- a/llvm/test/MC/SBF/sbf-alu.s +++ b/llvm/test/MC/SBF/sbf-alu.s @@ -291,6 +291,10 @@ mov64 r0, r9 # CHECK-ASM-NEW: encoding: [0xbf,0x23,0x00,0x00,0x00,0x00,0x00,0x00] mov64 r3, r2 +# CHECK-OBJ-NEW: mov64 r3, r2 +# CHECK-ASM-NEW: encoding: [0xbf,0x23,0x00,0x00,0x00,0x00,0x00,0x00] +mov64 w3, w2 + # CHECK-OBJ-NEW: mov64 r3, 0x7b # CHECK-ASM-NEW: encoding: [0xb7,0x03,0x00,0x00,0x7b,0x00,0x00,0x00] mov64 r3, 123 @@ -303,6 +307,10 @@ mov64 r5, -123 # CHECK-ASM-NEW: encoding: [0xbc,0x26,0x00,0x00,0x00,0x00,0x00,0x00] mov32 w6, w2 +# CHECK-OBJ-NEW: mov32 w6, w2 +# CHECK-ASM-NEW: encoding: [0xbc,0x26,0x00,0x00,0x00,0x00,0x00,0x00] +mov32 r6, w2 + # CHECK-OBJ-NEW: mov32 w5, -0x7b # CHECK-ASM-NEW: encoding: [0xb4,0x05,0x00,0x00,0x85,0xff,0xff,0xff] mov32 w5, -123