From 84575f1695d661b89ff246b214ae4b88ca253cfc Mon Sep 17 00:00:00 2001 From: Lucas Steuernagel <38472950+LucasSte@users.noreply.github.com> Date: Sat, 16 Dec 2023 00:56:02 -0300 Subject: [PATCH] [SOL] Remove `neg` and change the semantics of `sub` (#73) Following the alterations made in solana-labs/rbpf#489, this PR removes the neg instructions and changes the semantics of sub when one of the operands is an immediate. sub r1, 2 now means r1 = 2 - r1, instead of r1 = r1 - 2. neg r1 is represented as r1 = 0 - r1. This is the second task in solana-labs/solana#34250. --- llvm/lib/Target/SBF/SBFInstrInfo.td | 40 ++++++++-- llvm/lib/Target/SBF/SBFSubtarget.cpp | 7 +- llvm/lib/Target/SBF/SBFSubtarget.h | 9 ++- .../CodeGen/SBF/sub_reversed_immediate.ll | 79 +++++++++++++++++++ 4 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 llvm/test/CodeGen/SBF/sub_reversed_immediate.ll diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index 41a66c375408a9..c91a7fbe9bed50 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,7 +265,7 @@ class ALU_RR { +multiclass ALU { def _rr : ALU_RR { (outs GPR:$dst), (ins GPR:$src2, i64imm:$imm), Mnemonic # "64 $dst, $imm", - [(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]>; + !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, (OpNode GPR32:$src2, i32immSExt32:$imm))]>; + !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; @@ -306,6 +312,19 @@ 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 { @@ -318,12 +337,21 @@ class 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