1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 12:43:36 +01:00

[mips] Correct the definitions of the unaligned word memory operation instructions

These instructions lacked the correct predicates, were not marked
as loads and stores and lacked the proper instruction mapping information.

In the case of microMIPS sw(l|r)e (EVA) these instructions were using the load
EVA description.

Reviewers: abeserminji, smaksimovic, atanasyan

Differential Revision: https://reviews.llvm.org/D45626

llvm-svn: 330326
This commit is contained in:
Simon Dardis 2018-04-19 13:33:51 +00:00
parent de3c13378a
commit 1b43caab05
6 changed files with 203 additions and 29 deletions

View File

@ -406,7 +406,7 @@ class POOL32C_LHUE_FM_MM<bits<6> op, bits<4> fmt, bits<3> funct> : MMArch {
let Inst{8-0} = offset;
}
class LWL_FM_MM<bits<4> funct> {
class LWL_FM_MM<bits<4> funct> : MMArch {
bits<5> rt;
bits<21> addr;
@ -419,7 +419,7 @@ class LWL_FM_MM<bits<4> funct> {
let Inst{11-0} = addr{11-0};
}
class POOL32C_STEVA_LDEVA_FM_MM<bits<4> type, bits<3> funct> {
class POOL32C_STEVA_LDEVA_FM_MM<bits<4> type, bits<3> funct> : MMArch {
bits<5> rt;
bits<21> addr;
bits<5> base = addr{20-16};

View File

@ -201,6 +201,9 @@ class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
Itin, FrmI> {
let DecoderMethod = "DecodeMemMMImm12";
string Constraints = "$src = $rt";
let BaseOpcode = opstr;
bit mayLoad = 1;
bit mayStore = 0;
}
class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
@ -209,6 +212,9 @@ class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
!strconcat(opstr, "\t$rt, $addr"),
[(OpNode RO:$rt, addrimm12:$addr)], Itin, FrmI> {
let DecoderMethod = "DecodeMemMMImm12";
let BaseOpcode = opstr;
bit mayLoad = 0;
bit mayStore = 1;
}
/// A register pair used by movep instruction.
@ -820,19 +826,25 @@ let DecoderNamespace = "MicroMips" in {
ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA;
}
}
let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>;
let DecoderNamespace = "MicroMips" in {
let Predicates = [InMicroMips] in
def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>;
/// Load and Store Instructions - unaligned
def LWL_MM : LoadLeftRightMM<"lwl", MipsLWL, GPR32Opnd, mem_mm_12, II_LWL>,
LWL_FM_MM<0x0>;
def LWR_MM : LoadLeftRightMM<"lwr", MipsLWR, GPR32Opnd, mem_mm_12, II_LWR>,
LWL_FM_MM<0x1>;
def SWL_MM : StoreLeftRightMM<"swl", MipsSWL, GPR32Opnd, mem_mm_12, II_SWL>,
LWL_FM_MM<0x8>;
def SWR_MM : StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12, II_SWR>,
LWL_FM_MM<0x9>;
def LWL_MM : MMRel, LoadLeftRightMM<"lwl", MipsLWL, GPR32Opnd, mem_mm_12,
II_LWL>, LWL_FM_MM<0x0>,
ISA_MICROMIPS32_NOT_MIPS32R6;
def LWR_MM : MMRel, LoadLeftRightMM<"lwr", MipsLWR, GPR32Opnd, mem_mm_12,
II_LWR>, LWL_FM_MM<0x1>,
ISA_MICROMIPS32_NOT_MIPS32R6;
def SWL_MM : MMRel, StoreLeftRightMM<"swl", MipsSWL, GPR32Opnd, mem_mm_12,
II_SWL>, LWL_FM_MM<0x8>,
ISA_MICROMIPS32_NOT_MIPS32R6;
def SWR_MM : MMRel, StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12,
II_SWR>, LWL_FM_MM<0x9>,
ISA_MICROMIPS32_NOT_MIPS32R6;
}
let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
/// Load and Store Instructions - multiple
def SWM32_MM : StoreMultMM<"swm32", II_SWM>, LWM_FM_MM<0xd>;
def LWM32_MM : LoadMultMM<"lwm32", II_LWM>, LWM_FM_MM<0x5>;

View File

@ -99,10 +99,12 @@ class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
string Constraints = "$src = $rt";
bit canFoldAsLoad = 1;
InstrItinClass Itinerary = itin;
bit mayLoad = 1;
bit mayStore = 0;
}
class LWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwle", GPR32Opnd, II_LWLE>;
class LWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwre", GPR32Opnd, II_LWRE>;
class LWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwle", GPR32Opnd, II_LWLE>;
class LWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwre", GPR32Opnd, II_LWRE>;
class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
InstrItinClass itin = NoItinerary> {
@ -113,10 +115,12 @@ class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
string DecoderMethod = "DecodeMemEVA";
string BaseOpcode = instr_asm;
InstrItinClass Itinerary = itin;
bit mayLoad = 0;
bit mayStore = 1;
}
class SWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swle", GPR32Opnd, II_SWLE>;
class SWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swre", GPR32Opnd, II_SWRE>;
class SWLE_DESC : STORE_LEFT_RIGHT_EVA_DESC_BASE<"swle", GPR32Opnd, II_SWLE>;
class SWRE_DESC : STORE_LEFT_RIGHT_EVA_DESC_BASE<"swre", GPR32Opnd, II_SWRE>;
// Load-linked EVA, Store-conditional EVA descriptions
class LLE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,

View File

@ -1429,6 +1429,7 @@ class LoadLeftRight<string opstr, SDNode OpNode, RegisterOperand RO,
[(set RO:$rt, (OpNode addr:$addr, RO:$src))], Itin, FrmI> {
let DecoderMethod = "DecodeMem";
string Constraints = "$src = $rt";
let BaseOpcode = opstr;
}
class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO,
@ -1436,6 +1437,7 @@ class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO,
InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(OpNode RO:$rt, addr:$addr)], Itin, FrmI> {
let DecoderMethod = "DecodeMem";
let BaseOpcode = opstr;
}
// COP2 Load/Store
@ -2015,19 +2017,16 @@ def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>;
}
/// load/store left/right
let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
AdditionalPredicates = [NotInMicroMips] in {
def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>,
ISA_MIPS1_NOT_32R6_64R6;
def LWR : LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>,
ISA_MIPS1_NOT_32R6_64R6;
def SWL : StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>,
ISA_MIPS1_NOT_32R6_64R6;
def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>,
ISA_MIPS1_NOT_32R6_64R6;
}
let AdditionalPredicates = [NotInMicroMips] in {
def LWL : MMRel, LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>,
ISA_MIPS1_NOT_32R6_64R6;
def LWR : MMRel, LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>,
ISA_MIPS1_NOT_32R6_64R6;
def SWL : MMRel, StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>,
ISA_MIPS1_NOT_32R6_64R6;
def SWR : MMRel, StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>,
ISA_MIPS1_NOT_32R6_64R6;
// COP2 Memory Instructions
def LWC2 : StdMMR6Rel, LW_FT2<"lwc2", COP2Opnd, II_LWC2, load>, LW_FM<0x32>,
ISA_MIPS1_NOT_32R6_64R6;

View File

@ -0,0 +1,124 @@
# RUN: llc -O0 -march=mips -mcpu=mips32r3 -mattr=+micromips,+eva -start-after=expand-isel-pseudos \
# RUN: -filetype obj %s -o - | llvm-objdump -mattr=+eva -d - | FileCheck %s
# Test that MIPS unaligned load/store instructions can be mapped to their
# corresponding microMIPS instructions.
--- |
define void @g(i32* %a, i32* %b) {
entry:
%0 = load i32, i32* %a, align 1
store i32 %0, i32* %b, align 1
ret void
}
define void @g2(i32* %a, i32* %b) {
entry:
%0 = load i32, i32* %a, align 1
store i32 %0, i32* %b, align 1
ret void
}
...
---
name: g
alignment: 2
exposesReturnsTwice: false
legalized: false
regBankSelected: false
selected: false
failedISel: false
tracksRegLiveness: true
liveins:
- { reg: '$a0', virtual-reg: '%0' }
- { reg: '$a1', virtual-reg: '%1' }
frameInfo:
isFrameAddressTaken: false
isReturnAddressTaken: false
hasStackMap: false
hasPatchPoint: false
stackSize: 0
offsetAdjustment: 0
maxAlignment: 1
adjustsStack: false
hasCalls: false
stackProtector: ''
maxCallFrameSize: 4294967295
hasOpaqueSPAdjustment: false
hasVAStart: false
hasMustTailInVarArgFunc: false
savePoint: ''
restorePoint: ''
fixedStack:
stack:
constants:
body: |
bb.0.entry:
liveins: $a0, $a1
%1:gpr32 = COPY $a1
%0:gpr32 = COPY $a0
%3:gpr32 = IMPLICIT_DEF
%2:gpr32 = LWL %0, 0, %3 :: (load 4 from %ir.a, align 1)
%4:gpr32 = LWR %0, 3, %2 :: (load 4 from %ir.a, align 1)
SWL %4, %1, 0 :: (store 4 into %ir.b, align 1)
SWR %4, %1, 3 :: (store 4 into %ir.b, align 1)
RetRA
...
---
name: g2
alignment: 2
exposesReturnsTwice: false
legalized: false
regBankSelected: false
selected: false
failedISel: false
tracksRegLiveness: true
liveins:
- { reg: '$a0', virtual-reg: '%0' }
- { reg: '$a1', virtual-reg: '%1' }
frameInfo:
isFrameAddressTaken: false
isReturnAddressTaken: false
hasStackMap: false
hasPatchPoint: false
stackSize: 0
offsetAdjustment: 0
maxAlignment: 1
adjustsStack: false
hasCalls: false
stackProtector: ''
maxCallFrameSize: 4294967295
hasOpaqueSPAdjustment: false
hasVAStart: false
hasMustTailInVarArgFunc: false
savePoint: ''
restorePoint: ''
fixedStack:
stack:
constants:
body: |
bb.0.entry:
liveins: $a0, $a1
%1:gpr32 = COPY $a1
%0:gpr32 = COPY $a0
%3:gpr32 = IMPLICIT_DEF
%2:gpr32 = LWLE %0, 0, %3 :: (load 4 from %ir.a, align 1)
%4:gpr32 = LWRE %0, 3, %2 :: (load 4 from %ir.a, align 1)
SWLE %4, %1, 0 :: (store 4 into %ir.b, align 1)
SWRE %4, %1, 3 :: (store 4 into %ir.b, align 1)
RetRA
...
# CHECK-LABEL: g:
# CHECK: 0: 60 24 00 00 lwl $1, 0($4)
# CHECK: 4: 60 24 10 03 lwr $1, 3($4)
# CHECK: 8: 60 25 80 00 swl $1, 0($5)
# CHECK: c: 60 25 90 03 swr $1, 3($5)
# CHECK-LABEL: g2:
# CHECK: 14: 60 24 64 00 lwle $1, 0($4)
# CHECK: 18: 60 24 66 03 lwre $1, 3($4)
# CHECK: 1c: 60 25 a0 00 swle $1, 0($5)
# CHECK: 20: 60 25 a2 03 swre $1, 3($5)

View File

@ -0,0 +1,35 @@
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
; RUN: llc -march=mips -mcpu=mips32r2 -stop-before=expand-isel-pseudos < %s | FileCheck %s --check-prefix=MIPS
; RUN: llc -march=mips -mcpu=mips32r2 -mattr=+micromips -stop-before=expand-isel-pseudos < %s | FileCheck %s --check-prefix=MICROMIPS
; Test that the correct ISA version of the unaligned memory operations is
; selected up front.
define void @g2(i32* %a, i32* %b) {
; MIPS-LABEL: name: g2
; MIPS: bb.0.entry:
; MIPS: liveins: $a0, $a1
; MIPS: [[COPY:%[0-9]+]]:gpr32 = COPY $a1
; MIPS: [[COPY1:%[0-9]+]]:gpr32 = COPY $a0
; MIPS: [[DEF:%[0-9]+]]:gpr32 = IMPLICIT_DEF
; MIPS: [[LWL:%[0-9]+]]:gpr32 = LWL [[COPY1]], 0, [[DEF]] :: (load 4 from %ir.a, align 1)
; MIPS: [[LWR:%[0-9]+]]:gpr32 = LWR [[COPY1]], 3, [[LWL]] :: (load 4 from %ir.a, align 1)
; MIPS: SWL [[LWR]], [[COPY]], 0 :: (store 4 into %ir.b, align 1)
; MIPS: SWR [[LWR]], [[COPY]], 3 :: (store 4 into %ir.b, align 1)
; MIPS: RetRA
; MICROMIPS-LABEL: name: g2
; MICROMIPS: bb.0.entry:
; MICROMIPS: liveins: $a0, $a1
; MICROMIPS: [[COPY:%[0-9]+]]:gpr32 = COPY $a1
; MICROMIPS: [[COPY1:%[0-9]+]]:gpr32 = COPY $a0
; MICROMIPS: [[DEF:%[0-9]+]]:gpr32 = IMPLICIT_DEF
; MICROMIPS: [[LWL_MM:%[0-9]+]]:gpr32 = LWL_MM [[COPY1]], 0, [[DEF]] :: (load 4 from %ir.a, align 1)
; MICROMIPS: [[LWR_MM:%[0-9]+]]:gpr32 = LWR_MM [[COPY1]], 3, [[LWL_MM]] :: (load 4 from %ir.a, align 1)
; MICROMIPS: SWL_MM [[LWR_MM]], [[COPY]], 0 :: (store 4 into %ir.b, align 1)
; MICROMIPS: SWR_MM [[LWR_MM]], [[COPY]], 3 :: (store 4 into %ir.b, align 1)
; MICROMIPS: RetRA
entry:
%0 = load i32, i32* %a, align 1
store i32 %0, i32* %b, align 1
ret void
}