[llvm] r356200 - [ARC] Add more load/store variants.
Pete Couperus via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 14 13:50:54 PDT 2019
Author: petecoup
Date: Thu Mar 14 13:50:54 2019
New Revision: 356200
URL: http://llvm.org/viewvc/llvm-project?rev=356200&view=rev
Log:
[ARC] Add more load/store variants.
On ARC ISA, general format of load instruction is this:
LD<zz><.x><.aa><.di> a, [b,c]
And general format of store is this:
ST<zz><.aa><.di> c, [b,s9]
Where:
<zz> is data size field and can be one of
<empty> (bits 00) - Word (32-bit), default behavior
B (bits 01) - Byte
H (bits 10) - Half-word (16-bit)
<.x> is data extend mode:
<empty> (bit 0) - If size is not Word(32-bit), then data is zero extended
X (bit 1) - If size is not Word(32-bit), then data is sign extended
<.aa> is address write-back mode:
<empty> (bits 00) - no write-back
.AW (bits 01) - Preincrement, base register updated pre memory transaction
.AB (bits 10) - Postincrement, base register updated post memory transaction
<.di> is cache bypass mode:
<empty> (bit 0) - Cached memory access, default mode
.DI (bit 1) - Non-cached data memory access
This patch adds these load/store instruction variants to the ARC backend.
Patch By Denis Antrushin! <denis at synopsys.com>
Differential Revision: https://reviews.llvm.org/D58980
Modified:
llvm/trunk/lib/Target/ARC/ARCInstrFormats.td
llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp
llvm/trunk/lib/Target/ARC/ARCInstrInfo.h
llvm/trunk/lib/Target/ARC/ARCInstrInfo.td
llvm/trunk/test/MC/Disassembler/ARC/ldst.txt
Modified: llvm/trunk/lib/Target/ARC/ARCInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCInstrFormats.td?rev=356200&r1=356199&r2=356200&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCInstrFormats.td (original)
+++ llvm/trunk/lib/Target/ARC/ARCInstrFormats.td Thu Mar 14 13:50:54 2019
@@ -55,6 +55,44 @@ def GPR32Reduced : Operand<iAny> {
let DecoderMethod = "DecodeGBR32ShortRegister";
}
+// Helper classes for load/store instructions
+class DataSizeMode<bits<2> mode, string instSfx, string asmSfx> {
+ bits<2> Value = mode;
+ string InstSuffix = instSfx;
+ string AsmSuffix = asmSfx;
+}
+class ExtMode<bit mode, string instSfx, string asmSfx> {
+ bit Value = mode;
+ string InstSuffix = instSfx;
+ string AsmSuffix = asmSfx;
+}
+
+class AddrMode<bits<2> mode, string instSfx, string asmSfx> {
+ bits<2> Value = mode;
+ string InstSuffix = instSfx;
+ string AsmSuffix = asmSfx;
+}
+
+class CacheMode<bit mode, string instSfx, string asmSfx> {
+ bit Value = mode;
+ string InstSuffix = instSfx;
+ string AsmSuffix = asmSfx;
+}
+
+def ByteSM : DataSizeMode<0b01, "B", "b">;
+def HalfSM : DataSizeMode<0b10, "H", "h">;
+def WordSM : DataSizeMode<0b00, "", "">;
+
+def NoEM : ExtMode<0, "", "">;
+def SignedEM : ExtMode<1, "_X", ".x">;
+
+def NoAM : AddrMode<0b00, "", "">;
+def PreIncAM : AddrMode<0b01, "_AW", ".aw">;
+def PostIncAM : AddrMode<0b10, "_AB", ".ab">;
+
+def NoCC : CacheMode<0b0, "", "">;
+def UncachedCC : CacheMode<0b1, "_DI", ".di">;
+
class InstARC<int sz, dag outs, dag ins, string asmstr, list<dag> pattern>
: Instruction, Encoding64 {
@@ -64,6 +102,18 @@ class InstARC<int sz, dag outs, dag ins,
let AsmString = asmstr;
let Pattern = pattern;
let Size = sz;
+
+ // Load/Store instruction properties
+ DataSizeMode ZZ = WordSM;
+ ExtMode X = NoEM;
+ AddrMode AA = NoAM;
+ CacheMode DI = NoCC;
+
+ // Field used for relation models
+ string BaseOpcode = "";
+
+ //TSFlags
+ let TSFlags{1-0} = AA.Value;
}
// ARC pseudo instructions format
@@ -354,6 +404,8 @@ class F32_LD_RS9<bit x, bits<2> aa, bit
let Inst{8-7} = zz;
let Inst{6} = x;
let Inst{5-0} = A;
+
+ let BaseOpcode = "ld_rs9";
}
class F32_LD_ADDR<bit x, bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
@@ -363,6 +415,8 @@ class F32_LD_ADDR<bit x, bits<2> aa, bit
let B = addr{14-9};
let S9 = addr{8-0};
+
+ let BaseOpcode = "ld_rs9";
}
@@ -387,6 +441,8 @@ class F32_LD_LIMM<bit x, bit di, bits<2>
let Inst{6} = x;
let Inst{5-0} = A;
let DecoderMethod = "DecodeLdLImmInstruction";
+
+ let BaseOpcode = "ld_limm";
}
// Register + LImm load. The 32-bit immediate address is in Inst[63-32].
@@ -415,6 +471,8 @@ class F32_LD_RLIMM<bit x, bits<2> aa, bi
let Inst{11-6} = LImmReg;
let Inst{5-0} = A;
let DecoderMethod = "DecodeLdRLImmInstruction";
+
+ let BaseOpcode = "ld_rlimm";
}
// Register + S9 Store. (B + S9)
@@ -437,6 +495,8 @@ class F32_ST_RS9<bits<2> aa, bit di, bit
let Inst{4-3} = aa;
let Inst{2-1} = zz;
let Inst{0} = 0;
+
+ let BaseOpcode = "st_rs9";
}
class F32_ST_ADDR<bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
@@ -446,6 +506,8 @@ class F32_ST_ADDR<bits<2> aa, bit di, bi
let B = addr{14-9};
let S9 = addr{8-0};
+
+ let BaseOpcode = "st_rs9";
}
// LImm Store.
@@ -469,6 +531,8 @@ class F32_ST_LIMM<bit di, bits<2> zz, da
let Inst{2-1} = zz;
let Inst{0} = 0;
let DecoderMethod = "DecodeStLImmInstruction";
+
+ let BaseOpcode = "st_limm";
}
// Compact Move/Load.
Modified: llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp?rev=356200&r1=356199&r2=356200&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp Thu Mar 14 13:50:54 2019
@@ -27,6 +27,19 @@ using namespace llvm;
#include "ARCGenInstrInfo.inc"
#define DEBUG_TYPE "arc-inst-info"
+
+enum AddrIncType {
+ NoAddInc = 0,
+ PreInc = 1,
+ PostInc = 2,
+ Scaled = 3
+};
+
+enum TSFlagsConstants {
+ TSF_AddrModeOff = 0,
+ TSF_AddModeMask = 3
+};
+
// Pin the vtable to this file.
void ARCInstrInfo::anchor() {}
@@ -395,3 +408,35 @@ unsigned ARCInstrInfo::getInstSizeInByte
}
return MI.getDesc().getSize();
}
+
+bool ARCInstrInfo::isPostIncrement(const MachineInstr &MI) const {
+ const MCInstrDesc &MID = MI.getDesc();
+ const uint64_t F = MID.TSFlags;
+ return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PostInc;
+}
+
+bool ARCInstrInfo::isPreIncrement(const MachineInstr &MI) const {
+ const MCInstrDesc &MID = MI.getDesc();
+ const uint64_t F = MID.TSFlags;
+ return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PreInc;
+}
+
+bool ARCInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI,
+ unsigned &BasePos,
+ unsigned &OffsetPos) const {
+ if (!MI.mayLoad() && !MI.mayStore())
+ return false;
+
+ BasePos = 1;
+ OffsetPos = 2;
+
+ if (isPostIncrement(MI) || isPreIncrement(MI)) {
+ BasePos++;
+ OffsetPos++;
+ }
+
+ if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm())
+ return false;
+
+ return true;
+}
Modified: llvm/trunk/lib/Target/ARC/ARCInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCInstrInfo.h?rev=356200&r1=356199&r2=356200&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCInstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.h Thu Mar 14 13:50:54 2019
@@ -81,6 +81,16 @@ public:
bool
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
+
+ bool isPostIncrement(const MachineInstr &MI) const override;
+
+ // ARC-specific
+ bool isPreIncrement(const MachineInstr &MI) const;
+
+ virtual bool getBaseAndOffsetPosition(const MachineInstr &MI,
+ unsigned &BasePos,
+ unsigned &OffsetPos) const override;
+
// Emit code before MBBI to load immediate value into physical register Reg.
// Returns an iterator to the new instruction.
MachineBasicBlock::iterator loadImmediate(MachineBasicBlock &MBB,
Modified: llvm/trunk/lib/Target/ARC/ARCInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCInstrInfo.td?rev=356200&r1=356199&r2=356200&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.td Thu Mar 14 13:50:54 2019
@@ -787,50 +787,47 @@ let isReturn = 1, isTerminator = 1 in {
// Load/Store instructions.
//----------------------------------------------------------------------------
+// Filter class for load/store mappings
+class ArcLdStRel;
+
// Load instruction variants:
// Control bits: x, aa, di, zz
// x - sign extend.
// aa - incrementing mode. (N/A for LIMM).
// di - uncached.
// zz - data size.
-multiclass ArcLdInst<bits<2> zz, string asmop> {
- let mayLoad = 1 in {
- def _rs9 : F32_LD_ADDR<0, 0b00, 0, zz,
- (outs GPR32:$A), (ins MEMrs9:$addr),
- !strconcat(asmop, "\t$A, [$addr]"), []>;
-
- def _limm : F32_LD_LIMM<0, 0, zz,
- (outs GPR32:$A), (ins MEMii:$addr),
- !strconcat(asmop, "\t$A, [$addr]"), []>;
-
- def _rlimm : F32_LD_RLIMM<0, 0b00, 0, zz,
- (outs GPR32:$A), (ins MEMrlimm:$addr),
- !strconcat(asmop, "\t$A, [$addr]"), []>;
-
- def _X_rs9 : F32_LD_ADDR<1, 0b00, 0, zz,
- (outs GPR32:$A), (ins MEMrs9:$addr),
- !strconcat(asmop, ".x\t$A, [$addr]"), []>;
-
- def _X_limm : F32_LD_LIMM<1, 0, zz,
- (outs GPR32:$A), (ins MEMii:$addr),
- !strconcat(asmop, ".x\t$A, [$addr]"), []>;
-
- def _X_rlimm : F32_LD_RLIMM<1, 0b00, 0, zz,
- (outs GPR32:$A), (ins MEMrlimm:$addr),
- !strconcat(asmop, ".x\t$A, [$addr]"), []>;
-
- def _AB_rs9 : F32_LD_RS9<0, 0b10, 0, zz,
- (outs GPR32:$addrout, GPR32:$A),
- (ins GPR32:$B, immS<9>:$S9),
- !strconcat(asmop, ".ab\t$A, [$B,$S9]"), []>
- { let Constraints = "$addrout = $B"; }
+multiclass ArcLdInst<DataSizeMode zz, ExtMode x, CacheMode di, string asmop> {
+ let mayLoad = 1, ZZ = zz, X = x, DI = di in {
+ def _rs9: F32_LD_ADDR<x.Value, NoAM.Value, di.Value, zz.Value,
+ (outs GPR32:$A), (ins MEMrs9:$addr),
+ !strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
+
+ def _limm: F32_LD_LIMM<x.Value, di.Value, zz.Value,
+ (outs GPR32:$A), (ins MEMii:$addr),
+ !strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
+
+ def _rlimm: F32_LD_RLIMM<x.Value, NoAM.Value, di.Value, zz.Value,
+ (outs GPR32:$A), (ins MEMrlimm:$addr),
+ !strconcat(asmop, "\t$A, [$addr]"), []>, ArcLdStRel;
+
+ foreach aa = [PreIncAM, PostIncAM] in {
+ def aa.InstSuffix#_rs9: F32_LD_RS9<x.Value, aa.Value, di.Value, zz.Value,
+ (outs GPR32:$A, GPR32:$addrout),
+ (ins GPR32:$B, immS<9>:$S9),
+ asmop#aa.AsmSuffix#"\t$A, [$B,$S9]", []>, ArcLdStRel
+ { let Constraints = "$addrout = $B"; let AA = aa; }
+ }
+ }
+}
+
+foreach di = [NoCC, UncachedCC] in {
+ defm LD#di.InstSuffix : ArcLdInst<WordSM, NoEM, di, "ld"#di.AsmSuffix>;
+ foreach zz = [ByteSM, HalfSM] in {
+ foreach x = [NoEM, SignedEM] in {
+ defm LD#zz.InstSuffix#x.InstSuffix#di.InstSuffix : ArcLdInst<zz, x, di, "ld"#zz.AsmSuffix#x.AsmSuffix#di.AsmSuffix>;
+ }
}
}
-
-// Load instruction definitions.
-defm LD : ArcLdInst<0b00, "ld">;
-defm LDH : ArcLdInst<0b10, "ldh">;
-defm LDB : ArcLdInst<0b01, "ldb">;
// Load instruction patterns.
// 32-bit loads.
@@ -872,25 +869,32 @@ def : Pat<(sextloadi8 AddrModeS9:$addr),
// aa - incrementing mode. (N/A for LIMM).
// di - uncached.
// zz - data size.
-multiclass ArcStInst<bits<2> zz, string asmop> {
- let mayStore = 1 in {
- def _rs9 : F32_ST_ADDR<0b00, 0, zz, (outs), (ins GPR32:$C, MEMrs9:$addr),
- !strconcat(asmop, "\t$C, [$addr]"), []>;
-
- def _limm : F32_ST_LIMM<0, zz, (outs), (ins GPR32:$C, MEMii:$addr),
- !strconcat(asmop, "\t$C, [$addr]"), []>;
-
- def _AW_rs9 : F32_ST_RS9<0b01, 0, zz, (outs GPR32:$addrout),
- (ins GPR32:$C, GPR32:$B, immS<9>:$S9),
- !strconcat(asmop, ".aw\t$C, [$B,$S9]"), []>
- { let Constraints = "$addrout = $B"; }
+multiclass ArcStInst<DataSizeMode zz, CacheMode di, string asmop> {
+ let mayStore = 1, ZZ = zz, DI = di in {
+ def _rs9: F32_ST_ADDR<NoAM.Value, di.Value, zz.Value,
+ (outs), (ins GPR32:$C, MEMrs9:$addr),
+ !strconcat(asmop, "\t$C, [$addr]"), []>, ArcLdStRel;
+
+ def _limm: F32_ST_LIMM<di.Value, zz.Value,
+ (outs), (ins GPR32:$C, MEMii:$addr),
+ !strconcat(asmop, "\t$C, [$addr]"), []>, ArcLdStRel;
+
+
+ foreach aa = [PreIncAM, PostIncAM] in {
+ def aa.InstSuffix#_rs9: F32_ST_RS9<aa.Value, di.Value, zz.Value,
+ (outs GPR32:$addrout),
+ (ins GPR32:$C, GPR32:$B, immS<9>:$S9),
+ asmop#aa.AsmSuffix#"\t$C, [$B,$S9]", []>, ArcLdStRel
+ { let Constraints = "$addrout = $B"; let AA = aa; }
+ }
}
}
-// Store instruction definitions.
-defm ST : ArcStInst<0b00, "st">;
-defm STH : ArcStInst<0b10, "sth">;
-defm STB : ArcStInst<0b01, "stb">;
+foreach di = [NoCC, UncachedCC] in {
+ foreach zz = [ByteSM, HalfSM, WordSM] in {
+ defm ST#zz.InstSuffix#di.InstSuffix : ArcStInst<zz, di, "st"#zz.AsmSuffix#di.AsmSuffix>;
+ }
+}
// Store instruction patterns.
// 32-bit stores
@@ -911,3 +915,10 @@ def : Pat<(truncstorei8 i32:$C, AddrMode
def : Pat<(truncstorei8 i32:$C, AddrModeImm:$addr),
(STB_limm i32:$C, AddrModeImm:$addr)>;
+def getPostIncOpcode : InstrMapping {
+ let FilterClass = "ArcLdStRel";
+ let RowFields = [ "BaseOpcode", "ZZ", "DI", "X"];
+ let ColFields = [ "AA" ];
+ let KeyCol = [ "NoAM" ];
+ let ValueCols = [["PostIncAM"]];
+}
Modified: llvm/trunk/test/MC/Disassembler/ARC/ldst.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARC/ldst.txt?rev=356200&r1=356199&r2=356200&view=diff
==============================================================================
--- llvm/trunk/test/MC/Disassembler/ARC/ldst.txt (original)
+++ llvm/trunk/test/MC/Disassembler/ARC/ldst.txt Thu Mar 14 13:50:54 2019
@@ -45,3 +45,50 @@
# CHECK: st %r7, [63920]
0x00 0x1e 0xc0 0x71 0x00 0x00 0xb0 0xf9
+# CHECK: ldb.ab %r1, [%r0,1]
+0x01 0x10 0x81 0x04
+
+# CHECK: stb.ab %r2, [%r0,1]
+0x01 0x18 0x92 0x00
+
+# CHECK: ldh.ab %r3, [%r0,12]
+0x0C 0x10 0x03 0x05
+
+# CHECK: sth.ab %r4, [%r0,18]
+0x12 0x18 0x14 0x01
+
+# CHECK: ld.ab %r5, [%r2,128]
+0x80 0x12 0x05 0x04
+
+# CHECK: st.ab %r6, [%r2,64]
+0x40 0x1A 0x90 0x01
+
+# CHECK: ldb.aw %r7, [%r0,1]
+0x01 0x10 0x87 0x02
+
+# CHECK: stb.aw %r8, [%r0,1]
+0x01 0x18 0x0A 0x02
+
+# CHECK: ldh.aw %r3, [%r0,12]
+0x0C 0x10 0x03 0x03
+
+# CHECK: sth.aw %r3, [%r0,18]
+0x12 0x18 0xCC 0x00
+
+# CHECK: ld.aw %r6, [%r2,128]
+0x80 0x12 0x06 0x02
+
+# CHECK: st.aw %r6, [%r2,64]
+0x40 0x1A 0x88 0x01
+
+# CHECK: ld.aw %r6, [%r2,128]
+0x80 0x12 0x06 0x02
+
+# CHECK: st.aw %r6, [%r2,64]
+0x40 0x1A 0x88 0x01
+
+# CHECK: ldb.x.di.aw %r0, [%r8,8]
+0x08 0x10 0xC0 0x1A
+
+# CHECK: stb.di.ab %r0, [%r9,64]
+0x40 0x19 0x32 0x10
More information about the llvm-commits
mailing list