From 3ad06bc50cdcb63b20088244528b5cc54bd2e898 Mon Sep 17 00:00:00 2001 From: Lucas Steuernagel <38472950+LucasSte@users.noreply.github.com> Date: Sat, 23 Dec 2023 13:52:19 -0300 Subject: [PATCH] [SOL] Remove `lddw` instruction (#74) * Remove lddw instruction * Add suggestions --- .../SBF/MCTargetDesc/SBFMCCodeEmitter.cpp | 12 ++- llvm/lib/Target/SBF/SBFInstrFormats.td | 1 + llvm/lib/Target/SBF/SBFInstrInfo.td | 60 ++++++++++++- llvm/test/CodeGen/SBF/cc_args.ll | 88 +++++++++++-------- llvm/test/CodeGen/SBF/objdump_cond_op.ll | 9 +- llvm/test/CodeGen/SBF/objdump_imm_hex.ll | 23 ++++- llvm/test/CodeGen/SBF/objdump_static_var.ll | 6 +- llvm/test/MC/Disassembler/SBF/sbf-alu.txt | 2 + llvm/test/MC/SBF/insn-unit.s | 2 + llvm/test/MC/SBF/sbf-alu.s | 3 + 10 files changed, 153 insertions(+), 53 deletions(-) diff --git a/llvm/lib/Target/SBF/MCTargetDesc/SBFMCCodeEmitter.cpp b/llvm/lib/Target/SBF/MCTargetDesc/SBFMCCodeEmitter.cpp index 24880f0bdc1e43..5c5da990ec7454 100644 --- a/llvm/lib/Target/SBF/MCTargetDesc/SBFMCCodeEmitter.cpp +++ b/llvm/lib/Target/SBF/MCTargetDesc/SBFMCCodeEmitter.cpp @@ -93,17 +93,21 @@ unsigned SBFMCCodeEmitter::getMachineOpValue(const MCInst &MI, if (MI.getOpcode() == SBF::JAL) // func call name Fixups.push_back(MCFixup::create(0, Expr, FK_PCRel_4)); - else if (MI.getOpcode() == SBF::LD_imm64) + else if (MI.getOpcode() == SBF::LD_imm64 || + MI.getOpcode() == SBF::MOV_32_64_addr) Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_8)); - else + // In SBFv2, LD_imm64 is replaced by MOV_32_64_addr and HOR_addr when loading + // addresses. These two instructions always appear together, so if a + // relocation is necessary, we only insert it for one of them, in this case + // MOV_32_64. + else if (MI.getOpcode() != SBF::HOR_addr) // bb label Fixups.push_back(MCFixup::create(0, Expr, FK_PCRel_2)); return 0; } -static uint8_t SwapBits(uint8_t Val) -{ +static uint8_t SwapBits(uint8_t Val) { return (Val & 0x0F) << 4 | (Val & 0xF0) >> 4; } diff --git a/llvm/lib/Target/SBF/SBFInstrFormats.td b/llvm/lib/Target/SBF/SBFInstrFormats.td index bb42a6141e6d0e..8bb8281c421857 100644 --- a/llvm/lib/Target/SBF/SBFInstrFormats.td +++ b/llvm/lib/Target/SBF/SBFInstrFormats.td @@ -44,6 +44,7 @@ def SBF_MOV : SBFArithOp<0xb>; def SBF_ARSH : SBFArithOp<0xc>; def SBF_END : SBFArithOp<0xd>; def SBF_SDIV : SBFArithOp<0xe>; +def SBF_HOR : SBFArithOp<0xf>; def SBF_XCHG : SBFArithOp<0xe>; def SBF_CMPXCHG : SBFArithOp<0xf>; diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index f2e5888fdb05a4..2acc18db400563 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -71,6 +71,21 @@ def i64immSExt32 : PatLeaf<(i64 imm), def i32immSExt32 : PatLeaf<(i32 imm), [{return isInt<32>(N->getSExtValue()); }]>; +// Fetch the upper 32-bits of a 64-bit integer. +def Upper32 : SDNodeXFormgetSExtValue() >> 32; + return CurDAG->getTargetConstant(value, SDLoc(N), + N->getValueType(0)); +}]>; + +// Fetch the lower 32-bits of a 64-bit integer. +def Lower32 : SDNodeXFormgetSExtValue() & 0x00000000ffffffff; + return CurDAG->getTargetConstant(value, SDLoc(N), + N->getValueType(0)); +}]>; + + // Addressing modes. def ADDRri : ComplexPattern; def FIri : ComplexPattern; @@ -302,6 +317,22 @@ let Constraints = "$dst = $src2" in { defm SRL : ALU; defm XOR : ALU; defm SRA : ALU; + + let Predicates = [SBFv2] in { + def HOR : ALU_RI; + let DecoderNamespace = "AddrLoad" in { + def HOR_addr : ALU_RI; + + } + } } defm MUL : ALU; @@ -370,7 +401,7 @@ class LD_IMM64 Pseudo, string Mnemonic> } let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def LD_imm64 : LD_IMM64<0, "lddw">; +def LD_imm64 : LD_IMM64<0, "lddw">, Requires<[NoSBFv2]>; def MOV_rr : ALU_RR; } -// load 64-bit global addr into register -def : Pat<(SBFWrapper tglobaladdr:$in), (LD_imm64 tglobaladdr:$in)>; - // 0xffffFFFF doesn't fit into simm32, optimize common case def : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)), (SRL_ri (SLL_ri (i64 GPR:$src), 32), 32)>; @@ -902,8 +930,32 @@ let isCodeGenOnly = 1 in { def MOV_32_64 : ALU_RR; + let Predicates = [SBFv2] in { + def MOV_32_64_imm : ALU_RI; + def MOV_32_64_addr : ALU_RI; + } } +// In SBFv2, a CopyToReg of a 64-bit value is split in two instructions: +// mov32 r1, 0x55667788 +// hor r1, 0x11223344 +// These instructions copy the value 0x1122334455667788 to a register. +def : Pat<(i64 imm:$imm), + (HOR (MOV_32_64_imm (i32 (Lower32 $imm))), + (i32 (Upper32 $imm)))>, Requires<[SBFv2]>; + +// load 64-bit global address into register. +def : Pat<(SBFWrapper tglobaladdr:$in), (LD_imm64 tglobaladdr:$in)>, + Requires<[NoSBFv2]>; +def : Pat<(SBFWrapper tglobaladdr:$in), + (HOR_addr (MOV_32_64_addr tglobaladdr:$in), + tglobaladdr:$in)>, Requires<[SBFv2]>; + + def : Pat<(i64 (sext GPR32:$src)), (SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>; diff --git a/llvm/test/CodeGen/SBF/cc_args.ll b/llvm/test/CodeGen/SBF/cc_args.ll index 3b7f46eb74409e..13cee14aa0373f 100644 --- a/llvm/test/CodeGen/SBF/cc_args.ll +++ b/llvm/test/CodeGen/SBF/cc_args.ll @@ -1,36 +1,52 @@ -; RUN: llc < %s -march=sbf -show-mc-encoding | FileCheck %s +; RUN: llc < %s -march=sbf -show-mc-encoding | FileCheck --check-prefix=CHECK-v1 %s +; RUN: llc < %s -march=sbf -mcpu=sbfv2 -show-mc-encoding | FileCheck --check-prefix=CHECK-v2 %s define void @test() #0 { entry: -; CHECK: test: +; CHECK-LABEL: test: -; CHECK: mov64 r1, 123 # encoding: [0xb7,0x01,0x00,0x00,0x7b,0x00,0x00,0x00] -; CHECK: call f_i16 +; CHECK-v1: mov64 r1, 123 # encoding: [0xb7,0x01,0x00,0x00,0x7b,0x00,0x00,0x00] +; CHECK-v2: mov64 r1, 123 +; CHECK-v1: call f_i16 call void @f_i16(i16 123) -; CHECK: mov64 r1, 12345678 # encoding: [0xb7,0x01,0x00,0x00,0x4e,0x61,0xbc,0x00] -; CHECK: call f_i32 +; CHECK-v1: mov64 r1, 12345678 # encoding: [0xb7,0x01,0x00,0x00,0x4e,0x61,0xbc,0x00] +; CHECK-v2: mov64 r1, 12345678 +; CHECK-v1: call f_i32 call void @f_i32(i32 12345678) -; CHECK: lddw r1, 72623859790382856 # encoding: [0x18,0x01,0x00,0x00,0x08,0x07,0x06,0x05,0x00,0x00,0x00,0x00,0x04,0x03,0x02,0x01] -; CHECK: call f_i64 +; 72623859790382856 = 0x0102030405060708 +; 84281096 = 0x05060708 +; 16909060 = 0x01020304 + +; CHECK-v2: mov32 r1, 84281096 # encoding: [0xb4,0x01,0x00,0x00,0x08,0x07,0x06,0x05] +; CHECK-v2: hor64 r1, 16909060 # encoding: [0xf7,0x01,0x00,0x00,0x04,0x03,0x02,0x01] + +; CHECK-v1: lddw r1, 72623859790382856 # encoding: [0x18,0x01,0x00,0x00,0x08,0x07,0x06,0x05,0x00,0x00,0x00,0x00,0x04,0x03,0x02,0x01] +; CHECK-v1: call f_i64 call void @f_i64(i64 72623859790382856) -; CHECK: mov64 r1, 1234 -; CHECK: mov64 r2, 5678 -; CHECK: call f_i32_i32 +; CHECK-v1: mov64 r1, 1234 +; CHECK-v1: mov64 r2, 5678 +; CHECK-v1: call f_i32_i32 call void @f_i32_i32(i32 1234, i32 5678) -; CHECK: mov64 r1, 2 -; CHECK: mov64 r2, 3 -; CHECK: mov64 r3, 4 -; CHECK: call f_i16_i32_i16 +; CHECK-v1: mov64 r1, 2 +; CHECK-v1: mov64 r2, 3 +; CHECK-v1: mov64 r3, 4 +; CHECK-v1: call f_i16_i32_i16 call void @f_i16_i32_i16(i16 2, i32 3, i16 4) -; CHECK: mov64 r1, 5 -; CHECK: lddw r2, 7262385979038285 -; CHECK: mov64 r3, 6 -; CHECK: call f_i16_i64_i16 +; 7262385979038285 = 0x0019CD1A00809A4D +; 8428109 = 0x00809A4D +; 1690906 = 0x0019CD1A +; CHECK-v2: mov32 r2, 8428109 +; CHECK-v2: hor64 r2, 1690906 + +; CHECK-v1: mov64 r1, 5 +; CHECK-v1: lddw r2, 7262385979038285 +; CHECK-v1: mov64 r3, 6 +; CHECK-v1: call f_i16_i64_i16 call void @f_i16_i64_i16(i16 5, i64 7262385979038285, i16 6) ret void @@ -41,53 +57,53 @@ entry: @g_i64 = common global i64 0, align 4 define void @f_i16(i16 %a) #0 { -; CHECK: f_i16: -; CHECK: stxh [r2 + 0], r1 # encoding: [0x6b,0x12,0x00,0x00,0x00,0x00,0x00,0x00] +; CHECK-v1: f_i16: +; CHECK-v1: stxh [r2 + 0], r1 # encoding: [0x6b,0x12,0x00,0x00,0x00,0x00,0x00,0x00] store volatile i16 %a, i16* @g_i16, align 2 ret void } define void @f_i32(i32 %a) #0 { -; CHECK: f_i32: -; CHECK: stxw [r2 + 0], r1 # encoding: [0x63,0x12,0x00,0x00,0x00,0x00,0x00,0x00] +; CHECK-v1: f_i32: +; CHECK-v1: stxw [r2 + 0], r1 # encoding: [0x63,0x12,0x00,0x00,0x00,0x00,0x00,0x00] store volatile i32 %a, i32* @g_i32, align 2 ret void } define void @f_i64(i64 %a) #0 { -; CHECK: f_i64: -; CHECK: stxdw [r2 + 0], r1 # encoding: [0x7b,0x12,0x00,0x00,0x00,0x00,0x00,0x00] +; CHECK-v1: f_i64: +; CHECK-v1: stxdw [r2 + 0], r1 # encoding: [0x7b,0x12,0x00,0x00,0x00,0x00,0x00,0x00] store volatile i64 %a, i64* @g_i64, align 2 ret void } define void @f_i32_i32(i32 %a, i32 %b) #0 { -; CHECK: f_i32_i32: -; CHECK: stxw [r3 + 0], r1 +; CHECK-v1: f_i32_i32: +; CHECK-v1: stxw [r3 + 0], r1 store volatile i32 %a, i32* @g_i32, align 4 -; CHECK: stxw [r3 + 0], r2 +; CHECK-v1: stxw [r3 + 0], r2 store volatile i32 %b, i32* @g_i32, align 4 ret void } define void @f_i16_i32_i16(i16 %a, i32 %b, i16 %c) #0 { -; CHECK: f_i16_i32_i16: -; CHECK: stxh [r4 + 0], r1 +; CHECK-v1: f_i16_i32_i16: +; CHECK-v1: stxh [r4 + 0], r1 store volatile i16 %a, i16* @g_i16, align 2 -; CHECK: stxw [r1 + 0], r2 +; CHECK-v1: stxw [r1 + 0], r2 store volatile i32 %b, i32* @g_i32, align 4 -; CHECK: stxh [r4 + 0], r3 +; CHECK-v1: stxh [r4 + 0], r3 store volatile i16 %c, i16* @g_i16, align 2 ret void } define void @f_i16_i64_i16(i16 %a, i64 %b, i16 %c) #0 { -; CHECK: f_i16_i64_i16: -; CHECK: stxh [r4 + 0], r1 +; CHECK-v1: f_i16_i64_i16: +; CHECK-v1: stxh [r4 + 0], r1 store volatile i16 %a, i16* @g_i16, align 2 -; CHECK: stxdw [r1 + 0], r2 # encoding: [0x7b,0x21,0x00,0x00,0x00,0x00,0x00,0x00] +; CHECK-v1: stxdw [r1 + 0], r2 # encoding: [0x7b,0x21,0x00,0x00,0x00,0x00,0x00,0x00] store volatile i64 %b, i64* @g_i64, align 8 -; CHECK: stxh [r4 + 0], r3 +; CHECK-v1: stxh [r4 + 0], r3 store volatile i16 %c, i16* @g_i16, align 2 ret void } diff --git a/llvm/test/CodeGen/SBF/objdump_cond_op.ll b/llvm/test/CodeGen/SBF/objdump_cond_op.ll index 4415b3d64cc8c7..dc32f30c01a8b5 100644 --- a/llvm/test/CodeGen/SBF/objdump_cond_op.ll +++ b/llvm/test/CodeGen/SBF/objdump_cond_op.ll @@ -34,7 +34,8 @@ define i32 @test(i32, i32) local_unnamed_addr #0 { %10 = load i32, i32* @gbl, align 4 br i1 %9, label %15, label %11 -; CHECK: lddw r1, 0x0 +; CHECK: mov32 w1, 0x0 +; CHECK: hor64 r1, 0x0 ; CHECK: ldxw r0, [r1 + 0x0] ; CHECK: mul64 r0, r0 ; CHECK: lsh64 r0, 0x1 @@ -45,7 +46,8 @@ define i32 @test(i32, i32) local_unnamed_addr #0 { br label %13 ; CHECK-LABEL: : -; CHECK: lddw r3, 0x0 +; CHECK: mov32 w3, 0x0 +; CHECK: hor64 r3, 0x0 ; CHECK: ldxw r0, [r3 + 0x0] ; CHECK: lsh64 r2, 0x20 ; CHECK: rsh64 r2, 0x20 @@ -57,7 +59,8 @@ define i32 @test(i32, i32) local_unnamed_addr #0 { store i32 %14, i32* @gbl, align 4 br label %15 ; CHECK-LABEL: : -; CHECK: lddw r1, 0x0 +; CHECK: mov32 w1, 0x0 +; CHECK: hor64 r1, 0x0 ; CHECK: stxw [r1 + 0x0], r0 ;