Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SOL] Explicit sign extension #86

Draft
wants to merge 1 commit into
base: solana-rustc/17.0-2023-12-14
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions llvm/lib/Target/SBF/SBFInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ def SBFCallxSrc : Predicate<"Subtarget->getCallXRegSrc()">, AssemblerPredicate<(
def SBFNoCallxSrc : Predicate<"!Subtarget->getCallXRegSrc()">;
def SBFPqrInstr : Predicate<"Subtarget->getHasPqrClass()">;
def SBFNoPqrInstr : Predicate<"!Subtarget->getHasPqrClass()">;
def SBFExplicitSext : Predicate<"Subtarget->getExplicitSignExt()">;
def SBFNoExplicitSext : Predicate<"!Subtarget->getExplicitSignExt()">;

def brtarget : Operand<OtherVT> {
let PrintMethod = "printBrTargetOperand";
Expand Down Expand Up @@ -968,14 +970,34 @@ def : Pat<(SBFWrapper tglobaladdr:$in),
tglobaladdr:$in)>, Requires<[SBFNoLddw]>;


def : Pat<(i64 (sext GPR32:$src)),
(SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>;
let Predicates = [SBFNoExplicitSext] in {
def : Pat<(i64 (sext GPR32:$src)),
(SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>;

def : Pat<(i64 (zext GPR32:$src)), (MOV_32_64 GPR32:$src)>;
def : Pat<(i64 (zext GPR32:$src)), (MOV_32_64 GPR32:$src)>;

// For i64 -> i32 truncation, use the 32-bit subregister directly.
def : Pat<(i32 (trunc GPR:$src)),
(i32 (EXTRACT_SUBREG GPR:$src, sub_32))>;
}

let Predicates = [SBFExplicitSext] in {
def : Pat<(i64 (sext GPR32:$src)),
(MOV_32_64 GPR32:$src)>;

// For zero extending, we use a mask to remove potential
// high bits from 'mov32 reg, reg'.
def : Pat<(i64 (zext GPR32:$src)),
(INSERT_SUBREG (i64 (IMPLICIT_DEF)),
(AND_ri_32 GPR32:$src, 0xffffffff), sub_32)>;

// For truncation, we need a bit mask before placing the value
// in a subregister.
def : Pat<(i32 (trunc GPR:$src)),
(AND_ri_32 (i32 (EXTRACT_SUBREG GPR:$src, sub_32)),
0xffffffff)>;
}

// For i64 -> i32 truncation, use the 32-bit subregister directly.
def : Pat<(i32 (trunc GPR:$src)),
(i32 (EXTRACT_SUBREG GPR:$src, sub_32))>;

// For i32 -> i64 anyext, we don't care about the high bits.
def : Pat<(i64 (anyext GPR32:$src)),
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Target/SBF/SBFMIPeephole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
// instructions generated due to bad RA on subregister.
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/SBFMCTargetDesc.h"
#include "SBF.h"
#include "SBFInstrInfo.h"
#include "SBFTargetMachine.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Support/Debug.h"
#include <set>

Expand Down Expand Up @@ -65,7 +67,9 @@ struct SBFMIPeephole : public MachineFunctionPass {

// Main entry point for this pass.
bool runOnMachineFunction(MachineFunction &MF) override {
if (skipFunction(MF.getFunction()))
const TargetSubtargetInfo &Target = MF.getSubtarget();
if (skipFunction(MF.getFunction()) ||
Target.getFeatureBits()[SBF::FeatureExplicitSignExt])
return false;

initialize(MF);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/SBF/SBFSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void SBFSubtarget::initializeEnvironment(const Triple &TT) {
NoLddw = false;
CallxRegSrc = false;
HasPqrClass = false;
ExplicitSignExt = false;
}

void SBFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/SBF/SBFSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ class SBFSubtarget : public SBFGenSubtargetInfo {
// Whether we have the PQR instruction class
bool HasPqrClass;

// Whether to use explict sign extension
bool ExplicitSignExt;

public:
// This constructor initializes the data members to match that
// of the specified triple.
Expand All @@ -102,6 +105,7 @@ class SBFSubtarget : public SBFGenSubtargetInfo {
bool getNoLddw() const { return NoLddw; }
bool getCallXRegSrc() const { return CallxRegSrc; }
bool getHasPqrClass() const { return HasPqrClass; }
bool getExplicitSignExt() const { return ExplicitSignExt; }

const SBFInstrInfo *getInstrInfo() const override { return &InstrInfo; }
const SBFFrameLowering *getFrameLowering() const override {
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/SBF/SBFTargetFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ def FeatureCallxRegSrc : SubtargetFeature<"callx-reg-src", "CallxRegSrc", "true"
def FeaturePqrInstr : SubtargetFeature<"pqr-instr", "HasPqrClass", "true",
"Enable the PQR instruction class">;

def FeatureExplicitSignExt : SubtargetFeature<"explicit-sext", "ExplicitSignExt", "true",
"Use explicit sign extension">;

class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;

Expand All @@ -56,4 +59,4 @@ def : Proc<"v3", [ALU32]>;
def : Proc<"probe", []>;
def : Proc<"sbfv2", [FeatureSolana, FeatureDynamicFrames, FeatureRelocAbs64, FeatureStaticSyscalls,
FeatureDisableNeg, FeatureReverseSubImm, FeatureDisableLddw, FeatureCallxRegSrc,
FeaturePqrInstr]>;
FeaturePqrInstr, FeatureExplicitSignExt]>;
60 changes: 60 additions & 0 deletions llvm/test/CodeGen/SBF/explicit-sext.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
; RUN: llc -march=sbf -mcpu=sbfv2 -mattr=+alu32 < %s | FileCheck %s

; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
define i64 @zeroext(i32 noundef %a, i32 noundef %b) local_unnamed_addr #0 {
entry:
; CHECK-LABEL: zeroext
%add1 = add i32 %a, %b
%sext1 = zext i32 %add1 to i64
%res = mul i64 %sext1, 3
ret i64 %res;

; Zero extending involves no operation
; CHECK: mov32 w0, w1
; CHECK: add32 w0, w2
; CHECK: and32 w0, -1
; CHECK: mul64 r0, 3
}


; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
define i64 @signext(i32 noundef %a, i32 noundef %b) local_unnamed_addr #0 {
entry:
; CHECK-LABEL: signext
%add1 = add i32 %a, %b
%sext1 = sext i32 %add1 to i64
%res = mul i64 %sext1, 3
ret i64 %res

; Sign extension is a mov32
; CHECK: add32 w1, w2
; CHECK: mov32 r0, w1
; CHECK: mul64 r0, 3
}


; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(none) uwtable(sync)
define i32 @trunc(i64 noundef %a, i64 noundef %b) local_unnamed_addr #0 {
entry:
; CHECK-LABEL: trunc
%add1 = add i64 %a, %b
%sext1 = trunc i64 %add1 to i32
%res = mul i32 %sext1, 3
ret i32 %res

; Truncation needs the and32 bit mask
; CHECK: mov64 r0, r1
; CHECK: and32 w2, -1
; CHECK: and32 w0, -1
; CHECK: add32 w0, w2
; CHECK: mul32 w0, 3
}

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"uwtable", i32 1}
!3 = !{i32 7, !"frame-pointer", i32 1}
!4 = !{!"clang version 16.0.5 (https://github.com/solana-labs/llvm-project.git b33adebdaaa2ac524e019c92b58e77b33cd216fb)"}
Loading