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:
parent
de3c13378a
commit
1b43caab05
@ -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};
|
||||
|
@ -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>;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
124
test/CodeGen/Mips/unaligned-memops-mapping.mir
Normal file
124
test/CodeGen/Mips/unaligned-memops-mapping.mir
Normal 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)
|
35
test/CodeGen/Mips/unaligned-memops.ll
Normal file
35
test/CodeGen/Mips/unaligned-memops.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user