From ab4b9c67fb33bc7d2a55edee6997ce64bca95530 Mon Sep 17 00:00:00 2001 From: Ben Shi Date: Mon, 2 Dec 2024 17:38:01 +0800 Subject: [PATCH] [AVR] Simplify eocoding of load/store instructions Fixes https://github.com/llvm/llvm-project/issues/113774 --- llvm/lib/Target/AVR/AVRInstrFormats.td | 2 - llvm/lib/Target/AVR/AVRInstrInfo.td | 48 ++++-------------- .../AVR/MCTargetDesc/AVRMCCodeEmitter.cpp | 50 ++++++++----------- .../AVR/MCTargetDesc/AVRMCCodeEmitter.h | 5 -- llvm/test/CodeGen/AVR/inline-asm/loadstore.ll | 26 ++++++++++ 5 files changed, 57 insertions(+), 74 deletions(-) diff --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td index 06d14a2fb47fe..407e14a079f3e 100644 --- a/llvm/lib/Target/AVR/AVRInstrFormats.td +++ b/llvm/lib/Target/AVR/AVRInstrFormats.td @@ -173,7 +173,6 @@ class FSTDLDD pattern> //===---------------------------------------------------------------------===// class FSTLD mode, dag outs, dag ins, string asmstr, list pattern> : AVRInst16 { - bits<2> ptrreg; bits<5> reg; let Inst{15 - 13} = 0b100; @@ -187,7 +186,6 @@ class FSTLD 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"; diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td index 3973cd30de1ec..61c17090e3fbe 100644 --- a/llvm/lib/Target/AVR/AVRInstrInfo.td +++ b/llvm/lib/Target/AVR/AVRInstrInfo.td @@ -234,31 +234,6 @@ def imm_port6 : Operand { // Addressing mode pattern reg+imm6 def addr : ComplexPattern; -// 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 { - 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 { - let MIOperandInfo = (ops PTRDISPREGS); - let EncoderMethod = "encodeLDSTPtrReg"; - - let ParserMatchClass = PtrRegAsmOperand; -} - //===----------------------------------------------------------------------===// // AVR predicates for subtarget features //===----------------------------------------------------------------------===// @@ -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]>; @@ -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+ @@ -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 @@ -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]>; @@ -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))]>, @@ -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))]>, diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp index 5a0ad8119ddd5..98ddacb31a348 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp @@ -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; @@ -109,26 +124,6 @@ AVRMCCodeEmitter::encodeRelCondBrTarget(const MCInst &MI, unsigned OpNo, return target; } -unsigned AVRMCCodeEmitter::encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &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 @@ -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); } diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.h index a00bbb9ae498b..5b301dfb03ee9 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.h +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.h @@ -52,11 +52,6 @@ class AVRMCCodeEmitter : public MCCodeEmitter { SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; - /// Encodes the `PTRREGS` operand to a load or store instruction. - unsigned encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - /// Encodes a `register+immediate` operand for `LDD`/`STD`. unsigned encodeMemri(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, diff --git a/llvm/test/CodeGen/AVR/inline-asm/loadstore.ll b/llvm/test/CodeGen/AVR/inline-asm/loadstore.ll index 524fef28382fb..5d45ece8f31c9 100644 --- a/llvm/test/CodeGen/AVR/inline-asm/loadstore.ll +++ b/llvm/test/CodeGen/AVR/inline-asm/loadstore.ll @@ -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: @@ -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 +}