Skip to content

[AVR] Simplify eocoding of load/store instructions #118279

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

Merged
merged 1 commit into from
Dec 5, 2024
Merged
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
2 changes: 0 additions & 2 deletions llvm/lib/Target/AVR/AVRInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ class FSTDLDD<bit type, dag outs, dag ins, string asmstr, list<dag> pattern>
//===---------------------------------------------------------------------===//
class FSTLD<bit type, bits<2> mode, dag outs, dag ins, string asmstr,
list<dag> pattern> : AVRInst16<outs, ins, asmstr, pattern> {
bits<2> ptrreg;
bits<5> reg;

let Inst{15 - 13} = 0b100;
Expand All @@ -187,7 +186,6 @@ class FSTLD<bit type, bits<2> mode, dag outs, dag ins, string asmstr,

let Inst{7 - 4} = reg{3 - 0};

let Inst{3 - 2} = ptrreg{1 - 0};
let Inst{1 - 0} = mode{1 - 0};

let DecoderMethod = "decodeLoadStore";
Expand Down
48 changes: 9 additions & 39 deletions llvm/lib/Target/AVR/AVRInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -234,31 +234,6 @@ def imm_port6 : Operand<i8> {
// Addressing mode pattern reg+imm6
def addr : ComplexPattern<iPTR, 2, "SelectAddr", [], [SDNPWantRoot]>;

// AsmOperand class for a pointer register.
// Used with the LD/ST family of instructions.
// See FSTLD in AVRInstrFormats.td
def PtrRegAsmOperand : AsmOperandClass { let Name = "Reg"; }

// A special operand type for the LD/ST instructions.
// It converts the pointer register number into a two-bit field used in the
// instruction.
def LDSTPtrReg : Operand<i16> {
let MIOperandInfo = (ops PTRREGS);
let EncoderMethod = "encodeLDSTPtrReg";

let ParserMatchClass = PtrRegAsmOperand;
}

// A special operand type for the LDD/STD instructions.
// It behaves identically to the LD/ST version, except restricts
// the pointer registers to Y and Z.
def LDDSTDPtrReg : Operand<i16> {
let MIOperandInfo = (ops PTRDISPREGS);
let EncoderMethod = "encodeLDSTPtrReg";

let ParserMatchClass = PtrRegAsmOperand;
}

//===----------------------------------------------------------------------===//
// AVR predicates for subtarget features
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -896,7 +871,7 @@ let canFoldAsLoad = 1, isReMaterializable = 1 in {

// Indirect loads.
let canFoldAsLoad = 1, isReMaterializable = 1 in {
def LDRdPtr : FSTLD<0, 0b00, (outs GPR8:$reg), (ins LDSTPtrReg:$ptrreg),
def LDRdPtr : FSTLD<0, 0b00, (outs GPR8:$reg), (ins PTRREGS:$ptrreg),
"ld\t$reg, $ptrreg",
[(set GPR8:$reg, (load i16:$ptrreg))]>,
Requires<[HasSRAM]>;
Expand All @@ -919,13 +894,8 @@ let canFoldAsLoad = 1, isReMaterializable = 1 in {
// Indirect loads (with postincrement or predecrement).
let mayLoad = 1, hasSideEffects = 0,
Constraints = "$ptrreg = $base_wb,@earlyclobber $reg" in {
def LDRdPtrPi : FSTLD<0, 0b01,
(outs GPR8
: $reg, PTRREGS
: $base_wb),
(ins LDSTPtrReg
: $ptrreg),
"ld\t$reg, $ptrreg+", []>,
def LDRdPtrPi : FSTLD<0, 0b01, (outs GPR8:$reg, PTRREGS:$base_wb),
(ins PTRREGS:$ptrreg), "ld\t$reg, $ptrreg+", []>,
Requires<[HasSRAM]>;

// LDW Rd+1:Rd, P+
Expand All @@ -937,7 +907,7 @@ let mayLoad = 1, hasSideEffects = 0,
Requires<[HasSRAM]>;

def LDRdPtrPd : FSTLD<0, 0b10, (outs GPR8:$reg, PTRREGS:$base_wb),
(ins LDSTPtrReg:$ptrreg), "ld\t$reg, -$ptrreg", []>,
(ins PTRREGS:$ptrreg), "ld\t$reg, -$ptrreg", []>,
Requires<[HasSRAM]>;

// LDW Rd+1:Rd, -P
Expand Down Expand Up @@ -1063,7 +1033,7 @@ def STSWKRr : Pseudo<(outs), (ins i16imm:$dst, DREGS:$src),
// Indirect stores.
// ST P, Rr
// Stores the value of Rr into the location addressed by pointer P.
def STPtrRr : FSTLD<1, 0b00, (outs), (ins LDSTPtrReg:$ptrreg, GPR8:$reg),
def STPtrRr : FSTLD<1, 0b00, (outs), (ins PTRREGS:$ptrreg, GPR8:$reg),
"st\t$ptrreg, $reg", [(store GPR8:$reg, i16:$ptrreg)]>,
Requires<[HasSRAM]>;

Expand All @@ -1087,8 +1057,8 @@ let Constraints = "$ptrreg = $base_wb,@earlyclobber $base_wb" in {
// ST P+, Rr
// Stores the value of Rr into the location addressed by pointer P.
// Post increments P.
def STPtrPiRr : FSTLD<1, 0b01, (outs LDSTPtrReg:$base_wb),
(ins LDSTPtrReg:$ptrreg, GPR8:$reg, i8imm:$offs),
def STPtrPiRr : FSTLD<1, 0b01, (outs PTRREGS:$base_wb),
(ins PTRREGS:$ptrreg, GPR8:$reg, i8imm:$offs),
"st\t$ptrreg+, $reg",
[(set i16:$base_wb, (post_store GPR8:$reg, i16:$ptrreg,
imm:$offs))]>,
Expand All @@ -1112,8 +1082,8 @@ let Constraints = "$ptrreg = $base_wb,@earlyclobber $base_wb" in {
// ST -P, Rr
// Stores the value of Rr into the location addressed by pointer P.
// Pre decrements P.
def STPtrPdRr : FSTLD<1, 0b10, (outs LDSTPtrReg:$base_wb),
(ins LDSTPtrReg:$ptrreg, GPR8:$reg, i8imm:$offs),
def STPtrPdRr : FSTLD<1, 0b10, (outs PTRREGS:$base_wb),
(ins PTRREGS:$ptrreg, GPR8:$reg, i8imm:$offs),
"st\t-$ptrreg, $reg",
[(set i16: $base_wb,
(pre_store GPR8:$reg, i16:$ptrreg, imm:$offs))]>,
Expand Down
50 changes: 22 additions & 28 deletions llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,31 @@ AVRMCCodeEmitter::loadStorePostEncoder(const MCInst &MI, unsigned EncodedValue,

unsigned Opcode = MI.getOpcode();

// check whether either of the registers are the X pointer register.
bool IsRegX = MI.getOperand(0).getReg() == AVR::R27R26 ||
MI.getOperand(1).getReg() == AVR::R27R26;
// Get the index of the pointer register operand.
unsigned Idx = 0;
if (Opcode == AVR::LDRdPtrPd || Opcode == AVR::LDRdPtrPi ||
Opcode == AVR::LDRdPtr)
Idx = 1;

// Check if we need to set the inconsistent bit
bool IsPredec = Opcode == AVR::LDRdPtrPd || Opcode == AVR::STPtrPdRr;
bool IsPostinc = Opcode == AVR::LDRdPtrPi || Opcode == AVR::STPtrPiRr;

// Check if we need to set the inconsistent bit
if (IsRegX || IsPredec || IsPostinc) {
if (MI.getOperand(Idx).getReg() == AVR::R27R26 || IsPredec || IsPostinc)
EncodedValue |= (1 << 12);

// Encode the pointer register.
switch (MI.getOperand(Idx).getReg()) {
case AVR::R27R26:
EncodedValue |= 0xc;
break;
case AVR::R29R28:
EncodedValue |= 0x8;
break;
case AVR::R31R30:
break;
default:
llvm_unreachable("invalid pointer register");
break;
}

return EncodedValue;
Expand Down Expand Up @@ -109,26 +124,6 @@ AVRMCCodeEmitter::encodeRelCondBrTarget(const MCInst &MI, unsigned OpNo,
return target;
}

unsigned AVRMCCodeEmitter::encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
auto MO = MI.getOperand(OpNo);

// The operand should be a pointer register.
assert(MO.isReg());

switch (MO.getReg().id()) {
case AVR::R27R26:
return 0x03; // X: 0b11
case AVR::R29R28:
return 0x02; // Y: 0b10
case AVR::R31R30:
return 0x00; // Z: 0b00
default:
llvm_unreachable("invalid pointer register");
}
}

/// Encodes a `memri` operand.
/// The operand is 7-bits.
/// * The lower 6 bits is the immediate
Expand Down Expand Up @@ -288,8 +283,7 @@ void AVRMCCodeEmitter::encodeInstruction(const MCInst &MI,
}
}

MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII,
MCContext &Ctx) {
MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx) {
return new AVRMCCodeEmitter(MCII, Ctx);
}

Expand Down
5 changes: 0 additions & 5 deletions llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ class AVRMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

/// Encodes the `PTRREGS` operand to a load or store instruction.
unsigned encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

/// Encodes a `register+immediate` operand for `LDD`/`STD`.
unsigned encodeMemri(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
Expand Down
26 changes: 26 additions & 0 deletions llvm/test/CodeGen/AVR/inline-asm/loadstore.ll
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ define i8 @loadz(ptr %0) {
ret i8 %2
}

define i8 @load_ptr_imm() {
; CHECK-LABEL: load_ptr_imm:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldi r26, 210
; CHECK-NEXT: ldi r27, 4
; CHECK-NEXT: ;APP
; CHECK-NEXT: ld r24, X
; CHECK-NEXT: ;NO_APP
; CHECK-NEXT: ret
%1 = tail call i8 asm sideeffect "ld $0, $1", "=r,e"(i16 1234)
ret i8 %1
}

define void @storex(ptr %0, i8 %1) {
; CHECK-LABEL: storex:
; CHECK: ; %bb.0:
Expand Down Expand Up @@ -86,3 +99,16 @@ define void @storez(ptr %0, i8 %1) {
tail call void asm sideeffect "st ${0:a}, $1", "z,r"(ptr %0, i8 %1)
ret void
}

define void @store_ptr_imm(i8 %0) {
; CHECK-LABEL: store_ptr_imm:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldi r26, 210
; CHECK-NEXT: ldi r27, 4
; CHECK-NEXT: ;APP
; CHECK-NEXT: st X, r24
; CHECK-NEXT: ;NO_APP
; CHECK-NEXT: ret
tail call void asm sideeffect "st $0, $1", "e,r"(i16 1234, i8 %0)
ret void
}
Loading