From 5d61c8b225ec6ab599e0f1ae1cfa702ad7a515f0 Mon Sep 17 00:00:00 2001 From: Simon Dardis Date: Thu, 19 Apr 2018 13:33:51 +0000 Subject: [PATCH] [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 --- llvm/lib/Target/Mips/MicroMipsInstrFormats.td | 4 +- llvm/lib/Target/Mips/MicroMipsInstrInfo.td | 34 ++++-- llvm/lib/Target/Mips/MipsEVAInstrInfo.td | 12 +- llvm/lib/Target/Mips/MipsInstrInfo.td | 15 ++- .../test/CodeGen/Mips/unaligned-memops-mapping.mir | 124 +++++++++++++++++++++ llvm/test/CodeGen/Mips/unaligned-memops.ll | 35 ++++++ 6 files changed, 199 insertions(+), 25 deletions(-) create mode 100644 llvm/test/CodeGen/Mips/unaligned-memops-mapping.mir create mode 100644 llvm/test/CodeGen/Mips/unaligned-memops.ll diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td index 0b2b117..d948176 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td @@ -406,7 +406,7 @@ class POOL32C_LHUE_FM_MM op, bits<4> fmt, bits<3> funct> : MMArch { let Inst{8-0} = offset; } -class LWL_FM_MM funct> { +class LWL_FM_MM funct> : MMArch { bits<5> rt; bits<21> addr; @@ -419,7 +419,7 @@ class LWL_FM_MM funct> { let Inst{11-0} = addr{11-0}; } -class POOL32C_STEVA_LDEVA_FM_MM type, bits<3> funct> { +class POOL32C_STEVA_LDEVA_FM_MM type, bits<3> funct> : MMArch { bits<5> rt; bits<21> addr; bits<5> base = addr{20-16}; diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index 150af02..1730d74 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -201,6 +201,9 @@ class LoadLeftRightMM { let DecoderMethod = "DecodeMemMMImm12"; string Constraints = "$src = $rt"; + let BaseOpcode = opstr; + bit mayLoad = 1; + bit mayStore = 0; } class StoreLeftRightMM { 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>; diff --git a/llvm/lib/Target/Mips/MipsEVAInstrInfo.td b/llvm/lib/Target/Mips/MipsEVAInstrInfo.td index 59254f2..ff54b1f 100644 --- a/llvm/lib/Target/Mips/MipsEVAInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsEVAInstrInfo.td @@ -99,10 +99,12 @@ class LOAD_LEFT_RIGHT_EVA_DESC_BASE; -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 { @@ -113,10 +115,12 @@ class STORE_LEFT_RIGHT_EVA_DESC_BASE; -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 { let DecoderMethod = "DecodeMem"; string Constraints = "$src = $rt"; + let BaseOpcode = opstr; } class StoreLeftRight { 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 = [], // FIXME: Lack of HasStdEnc is probably a bug - AdditionalPredicates = [NotInMicroMips] in { -def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>, +let AdditionalPredicates = [NotInMicroMips] in { +def LWL : MMRel, 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>, +def LWR : MMRel, 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>, +def SWL : MMRel, 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>, +def SWR : MMRel, StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, ISA_MIPS1_NOT_32R6_64R6; -} -let AdditionalPredicates = [NotInMicroMips] in { // COP2 Memory Instructions def LWC2 : StdMMR6Rel, LW_FT2<"lwc2", COP2Opnd, II_LWC2, load>, LW_FM<0x32>, ISA_MIPS1_NOT_32R6_64R6; diff --git a/llvm/test/CodeGen/Mips/unaligned-memops-mapping.mir b/llvm/test/CodeGen/Mips/unaligned-memops-mapping.mir new file mode 100644 index 0000000..438a7e1 --- /dev/null +++ b/llvm/test/CodeGen/Mips/unaligned-memops-mapping.mir @@ -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) diff --git a/llvm/test/CodeGen/Mips/unaligned-memops.ll b/llvm/test/CodeGen/Mips/unaligned-memops.ll new file mode 100644 index 0000000..af290a7 --- /dev/null +++ b/llvm/test/CodeGen/Mips/unaligned-memops.ll @@ -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 +} -- 2.7.4