Index: lib/Target/Mips/MipsInstructionSelector.cpp =================================================================== --- lib/Target/Mips/MipsInstructionSelector.cpp +++ lib/Target/Mips/MipsInstructionSelector.cpp @@ -139,30 +139,49 @@ } /// Returning Opc indicates that we failed to select MIPS instruction opcode. -static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes) { - if (Opc == TargetOpcode::G_STORE) - switch (MemSizeInBytes) { - case 4: - return Mips::SW; - case 2: - return Mips::SH; - case 1: - return Mips::SB; - default: - return Opc; - } - else - // Unspecified extending load is selected into zeroExtending load. +static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes, + unsigned RegBank, bool isFP64) { + bool isStore = Opc == TargetOpcode::G_STORE; + if (RegBank == Mips::GPRBRegBankID) { + if (isStore) + switch (MemSizeInBytes) { + case 4: + return Mips::SW; + case 2: + return Mips::SH; + case 1: + return Mips::SB; + default: + return Opc; + } + else + // Unspecified extending load is selected into zeroExtending load. + switch (MemSizeInBytes) { + case 4: + return Mips::LW; + case 2: + return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu; + case 1: + return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu; + default: + return Opc; + } + } + + if (RegBank == Mips::FPRBRegBankID) { switch (MemSizeInBytes) { case 4: - return Mips::LW; - case 2: - return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu; - case 1: - return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu; + return isStore ? Mips::SWC1 : Mips::LWC1; + case 8: + if (isFP64) + return isStore ? Mips::SDC164 : Mips::LDC164; + else + return isStore ? Mips::SDC1 : Mips::LDC1; default: return Opc; } + } + return Opc; } bool MipsInstructionSelector::select(MachineInstr &I, @@ -262,11 +281,13 @@ const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize(); - if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32) + if (!((DestRegBank == Mips::GPRBRegBankID && OpSize == 32) || + (DestRegBank == Mips::FPRBRegBankID && + (OpSize == 32 || OpSize == 64)))) return false; - const unsigned NewOpc = - selectLoadStoreOpCode(I.getOpcode(), OpMemSizeInBytes); + const unsigned NewOpc = selectLoadStoreOpCode( + I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit()); if (NewOpc == I.getOpcode()) return false; Index: test/CodeGen/Mips/GlobalISel/instruction-select/load.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/instruction-select/load.mir @@ -0,0 +1,94 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP32 +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP64 +--- | + + define void @load_i32(i32* %ptr) {entry: ret void} + define void @load_float(float* %ptr) {entry: ret void} + define void @load_double(double* %ptr) {entry: ret void} + +... +--- +name: load_i32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0 + + ; MIPS32FP32-LABEL: name: load_i32 + ; MIPS32FP32: liveins: $a0 + ; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32FP32: [[LW:%[0-9]+]]:gpr32 = LW [[COPY]], 0 :: (load 4 from %ir.ptr) + ; MIPS32FP32: $v0 = COPY [[LW]] + ; MIPS32FP32: RetRA implicit $v0 + ; MIPS32FP64-LABEL: name: load_i32 + ; MIPS32FP64: liveins: $a0 + ; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32FP64: [[LW:%[0-9]+]]:gpr32 = LW [[COPY]], 0 :: (load 4 from %ir.ptr) + ; MIPS32FP64: $v0 = COPY [[LW]] + ; MIPS32FP64: RetRA implicit $v0 + %0:gprb(p0) = COPY $a0 + %1:gprb(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr) + $v0 = COPY %1(s32) + RetRA implicit $v0 + +... +--- +name: load_float +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0 + + ; MIPS32FP32-LABEL: name: load_float + ; MIPS32FP32: liveins: $a0 + ; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32FP32: [[LWC1_:%[0-9]+]]:fgr32 = LWC1 [[COPY]], 0 :: (load 4 from %ir.ptr) + ; MIPS32FP32: $f0 = COPY [[LWC1_]] + ; MIPS32FP32: RetRA implicit $f0 + ; MIPS32FP64-LABEL: name: load_float + ; MIPS32FP64: liveins: $a0 + ; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32FP64: [[LWC1_:%[0-9]+]]:fgr32 = LWC1 [[COPY]], 0 :: (load 4 from %ir.ptr) + ; MIPS32FP64: $f0 = COPY [[LWC1_]] + ; MIPS32FP64: RetRA implicit $f0 + %0:gprb(p0) = COPY $a0 + %1:fprb(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr) + $f0 = COPY %1(s32) + RetRA implicit $f0 + +... +--- +name: load_double +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0 + + ; MIPS32FP32-LABEL: name: load_double + ; MIPS32FP32: liveins: $a0 + ; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32FP32: [[LDC1_:%[0-9]+]]:afgr64 = LDC1 [[COPY]], 0 :: (load 8 from %ir.ptr) + ; MIPS32FP32: $d0 = COPY [[LDC1_]] + ; MIPS32FP32: RetRA implicit $d0 + ; MIPS32FP64-LABEL: name: load_double + ; MIPS32FP64: liveins: $a0 + ; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32FP64: [[LDC164_:%[0-9]+]]:fgr64 = LDC164 [[COPY]], 0 :: (load 8 from %ir.ptr) + ; MIPS32FP64: $d0 = COPY [[LDC164_]] + ; MIPS32FP64: RetRA implicit $d0 + %0:gprb(p0) = COPY $a0 + %1:fprb(s64) = G_LOAD %0(p0) :: (load 8 from %ir.ptr) + $d0 = COPY %1(s64) + RetRA implicit $d0 + +... Index: test/CodeGen/Mips/GlobalISel/instruction-select/store.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/instruction-select/store.mir @@ -0,0 +1,94 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP32 +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP64 +--- | + + define void @store_i32(i32* %ptr) { entry: ret void } + define void @store_float(float* %ptr) { entry: ret void } + define void @store_double(double* %ptr) { entry: ret void } + +... +--- +name: store_i32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32FP32-LABEL: name: store_i32 + ; MIPS32FP32: liveins: $a0, $a1 + ; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32FP32: SW [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr) + ; MIPS32FP32: RetRA + ; MIPS32FP64-LABEL: name: store_i32 + ; MIPS32FP64: liveins: $a0, $a1 + ; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32FP64: SW [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr) + ; MIPS32FP64: RetRA + %0:gprb(s32) = COPY $a0 + %1:gprb(p0) = COPY $a1 + G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr) + RetRA + +... +--- +name: store_float +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a1, $f12 + + ; MIPS32FP32-LABEL: name: store_float + ; MIPS32FP32: liveins: $a1, $f12 + ; MIPS32FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12 + ; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32FP32: SWC1 [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr) + ; MIPS32FP32: RetRA + ; MIPS32FP64-LABEL: name: store_float + ; MIPS32FP64: liveins: $a1, $f12 + ; MIPS32FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12 + ; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32FP64: SWC1 [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr) + ; MIPS32FP64: RetRA + %0:fprb(s32) = COPY $f12 + %1:gprb(p0) = COPY $a1 + G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr) + RetRA + +... +--- +name: store_double +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a2, $d6 + + ; MIPS32FP32-LABEL: name: store_double + ; MIPS32FP32: liveins: $a2, $d6 + ; MIPS32FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6 + ; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a2 + ; MIPS32FP32: SDC1 [[COPY]], [[COPY1]], 0 :: (store 8 into %ir.ptr) + ; MIPS32FP32: RetRA + ; MIPS32FP64-LABEL: name: store_double + ; MIPS32FP64: liveins: $a2, $d6 + ; MIPS32FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6 + ; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a2 + ; MIPS32FP64: SDC164 [[COPY]], [[COPY1]], 0 :: (store 8 into %ir.ptr) + ; MIPS32FP64: RetRA + %0:fprb(s64) = COPY $d6 + %1:gprb(p0) = COPY $a2 + G_STORE %0(s64), %1(p0) :: (store 8 into %ir.ptr) + RetRA + +... Index: test/CodeGen/Mips/GlobalISel/llvm-ir/load.ll =================================================================== --- test/CodeGen/Mips/GlobalISel/llvm-ir/load.ll +++ test/CodeGen/Mips/GlobalISel/llvm-ir/load.ll @@ -25,3 +25,25 @@ %0 = load i64, i64* %ptr ret i64 %0 } + +define float @load_float(float* %ptr) { +; MIPS32-LABEL: load_float: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lwc1 $f0, 0($4) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %0 = load float, float* %ptr + ret float %0 +} + +define double @load_double(double* %ptr) { +; MIPS32-LABEL: load_double: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: ldc1 $f0, 0($4) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %0 = load double, double* %ptr + ret double %0 +} Index: test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll =================================================================== --- test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll +++ test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll @@ -25,3 +25,25 @@ store i64 %val, i64* %ptr ret void } + +define void @store_float(float %val, float* %ptr) { +; MIPS32-LABEL: store_float: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: swc1 $f12, 0($5) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + store float %val, float* %ptr + ret void +} + +define void @store_double(double %val, double* %ptr) { +; MIPS32-LABEL: store_double: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: sdc1 $f12, 0($6) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + store double %val, double* %ptr + ret void +}