Index: lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1037,13 +1037,6 @@ return Legalized; case TargetOpcode::G_LOAD: - // For some types like i24, we might try to widen to i32. To properly handle - // this we should be using a dedicated extending load, until then avoid - // trying to legalize. - if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) != - WideTy.getSizeInBits()) - return UnableToLegalize; - LLVM_FALLTHROUGH; case TargetOpcode::G_SEXTLOAD: case TargetOpcode::G_ZEXTLOAD: Observer.changingInstr(MI); Index: lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -278,6 +278,10 @@ return false; } }) + .unsupportedIf([=](const LegalityQuery &Query) { + return Query.Opcode == G_LOAD && + alignTo(Query.Types[0].getSizeInBits(), 8) < 32; + }) .clampScalar(0, S32, S64); Index: lib/Target/Mips/MipsInstructionSelector.cpp =================================================================== --- lib/Target/Mips/MipsInstructionSelector.cpp +++ lib/Target/Mips/MipsInstructionSelector.cpp @@ -96,10 +96,15 @@ 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; Index: lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- lib/Target/Mips/MipsLegalizerInfo.cpp +++ lib/Target/Mips/MipsLegalizerInfo.cpp @@ -32,7 +32,11 @@ .lowerFor({{s32, s1}}); getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalForCartesianProduct({p0, s32}, {p0}); + .legalForTypesWithMemSize({{s32, p0, 8}, + {s32, p0, 16}, + {s32, p0, 32}, + {p0, p0, 32}}) + .minScalar(0, s32); getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD}) .legalForTypesWithMemSize({{s32, p0, 8}, Index: test/CodeGen/Mips/GlobalISel/instruction-select/truncStore_and_aExtLoad.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/instruction-select/truncStore_and_aExtLoad.mir @@ -0,0 +1,83 @@ +# 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=MIPS32 +--- | + + define void @load_store_i8(i8* %px, i8* %py) {entry: ret void} + define void @load_store_i16(i16* %px, i16* %py) {entry: ret void} + define void @load_store_i32(i32* %px, i32* %py) {entry: ret void} + +... +--- +name: load_store_i8 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i8 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32: [[LBu:%[0-9]+]]:gpr32 = LBu [[COPY1]], 0 :: (load 1 from %ir.py) + ; MIPS32: SB [[LBu]], [[COPY]], 0 :: (store 1 into %ir.px) + ; MIPS32: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %4:gprb(s32) = G_LOAD %1(p0) :: (load 1 from %ir.py) + %3:gprb(s32) = COPY %4(s32) + G_STORE %3(s32), %0(p0) :: (store 1 into %ir.px) + RetRA + +... +--- +name: load_store_i16 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i16 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32: [[LHu:%[0-9]+]]:gpr32 = LHu [[COPY1]], 0 :: (load 2 from %ir.py) + ; MIPS32: SH [[LHu]], [[COPY]], 0 :: (store 2 into %ir.px) + ; MIPS32: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %4:gprb(s32) = G_LOAD %1(p0) :: (load 2 from %ir.py) + %3:gprb(s32) = COPY %4(s32) + G_STORE %3(s32), %0(p0) :: (store 2 into %ir.px) + RetRA + +... +--- +name: load_store_i32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[COPY1]], 0 :: (load 4 from %ir.py) + ; MIPS32: SW [[LW]], [[COPY]], 0 :: (store 4 into %ir.px) + ; MIPS32: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %2:gprb(s32) = G_LOAD %1(p0) :: (load 4 from %ir.py) + G_STORE %2(s32), %0(p0) :: (store 4 into %ir.px) + RetRA + +... Index: test/CodeGen/Mips/GlobalISel/legalizer/truncStore_and_aExtLoad.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/legalizer/truncStore_and_aExtLoad.mir @@ -0,0 +1,145 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +--- | + + define void @load1_s8_to_load1_s32(i8* %px) {entry: ret void} + define void @load2_s16_to_load2_s32(i16* %px) {entry: ret void} + define void @load_store_i1(i1* %px, i1* %py) {entry: ret void} + define void @load_store_i8(i8* %px, i8* %py) {entry: ret void} + define void @load_store_i16(i16* %px, i16* %py) {entry: ret void} + define void @load_store_i32(i32* %px, i32* %py) {entry: ret void} + +... +--- +name: load1_s8_to_load1_s32 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0 + + ; MIPS32-LABEL: name: load1_s8_to_load1_s32 + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY]](p0) :: (load 1 from %ir.px) + ; MIPS32: $v0 = COPY [[LOAD]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(p0) = COPY $a0 + %2:_(s32) = G_LOAD %0(p0) :: (load 1 from %ir.px) + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: load2_s16_to_load2_s32 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0 + + ; MIPS32-LABEL: name: load2_s16_to_load2_s32 + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY]](p0) :: (load 2 from %ir.px) + ; MIPS32: $v0 = COPY [[LOAD]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(p0) = COPY $a0 + %2:_(s32) = G_LOAD %0(p0) :: (load 2 from %ir.px) + $v0 = COPY %2(s32) + RetRA implicit $v0 + +... +--- +name: load_store_i1 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i1 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY1]](p0) :: (load 1 from %ir.py) + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[LOAD]](s32) + ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; MIPS32: G_STORE [[AND]](s32), [[COPY]](p0) :: (store 1 into %ir.px) + ; MIPS32: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(s1) = G_LOAD %1(p0) :: (load 1 from %ir.py) + G_STORE %2(s1), %0(p0) :: (store 1 into %ir.px) + RetRA + +... +--- +name: load_store_i8 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i8 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY1]](p0) :: (load 1 from %ir.py) + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[LOAD]](s32) + ; MIPS32: G_STORE [[COPY2]](s32), [[COPY]](p0) :: (store 1 into %ir.px) + ; MIPS32: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(s8) = G_LOAD %1(p0) :: (load 1 from %ir.py) + G_STORE %2(s8), %0(p0) :: (store 1 into %ir.px) + RetRA + +... +--- +name: load_store_i16 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i16 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY1]](p0) :: (load 2 from %ir.py) + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY [[LOAD]](s32) + ; MIPS32: G_STORE [[COPY2]](s32), [[COPY]](p0) :: (store 2 into %ir.px) + ; MIPS32: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(s16) = G_LOAD %1(p0) :: (load 2 from %ir.py) + G_STORE %2(s16), %0(p0) :: (store 2 into %ir.px) + RetRA + +... +--- +name: load_store_i32 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY1]](p0) :: (load 4 from %ir.py) + ; MIPS32: G_STORE [[LOAD]](s32), [[COPY]](p0) :: (store 4 into %ir.px) + ; MIPS32: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(s32) = G_LOAD %1(p0) :: (load 4 from %ir.py) + G_STORE %2(s32), %0(p0) :: (store 4 into %ir.px) + RetRA + +... Index: test/CodeGen/Mips/GlobalISel/llvm-ir/truncStore_and_aExtLoad.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/llvm-ir/truncStore_and_aExtLoad.ll @@ -0,0 +1,79 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32 + +define i8 @load1_s8_to_load1_s32(i8* %px) { +; MIPS32-LABEL: load1_s8_to_load1_s32: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lbu $2, 0($4) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %0 = load i8, i8* %px + ret i8 %0 +} + +define i16 @load2_s16_to_load2_s32(i16* %px) { +; MIPS32-LABEL: load2_s16_to_load2_s32: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lhu $2, 0($4) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %0 = load i16, i16* %px + ret i16 %0 +} + +define void @load_store_i1(i1* %px, i1* %py) { +; MIPS32-LABEL: load_store_i1: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lbu $5, 0($5) +; MIPS32-NEXT: lui $1, 0 +; MIPS32-NEXT: ori $1, $1, 1 +; MIPS32-NEXT: and $1, $5, $1 +; MIPS32-NEXT: sb $1, 0($4) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %0 = load i1, i1* %py + store i1 %0, i1* %px + ret void +} + +define void @load_store_i8(i8* %px, i8* %py) { +; MIPS32-LABEL: load_store_i8: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lbu $5, 0($5) +; MIPS32-NEXT: sb $5, 0($4) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %0 = load i8, i8* %py + store i8 %0, i8* %px + ret void +} + +define void @load_store_i16(i16* %px, i16* %py) { +; MIPS32-LABEL: load_store_i16: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lhu $5, 0($5) +; MIPS32-NEXT: sh $5, 0($4) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %0 = load i16, i16* %py + store i16 %0, i16* %px + ret void +} + +define void @load_store_i32(i32* %px, i32* %py) { +; MIPS32-LABEL: load_store_i32: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lw $5, 0($5) +; MIPS32-NEXT: sw $5, 0($4) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %0 = load i32, i32* %py + store i32 %0, i32* %px + ret void +} Index: test/CodeGen/Mips/GlobalISel/regbankselect/truncStore_and_aExtLoad.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/regbankselect/truncStore_and_aExtLoad.mir @@ -0,0 +1,82 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +--- | + + define void @load_store_i8(i8* %px, i8* %py) {entry: ret void} + define void @load_store_i16(i16* %px, i16* %py) {entry: ret void} + define void @load_store_i32(i32* %px, i32* %py) {entry: ret void} + +... +--- +name: load_store_i8 +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i8 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; MIPS32: [[LOAD:%[0-9]+]]:gprb(s32) = G_LOAD [[COPY1]](p0) :: (load 1 from %ir.py) + ; MIPS32: [[COPY2:%[0-9]+]]:gprb(s32) = COPY [[LOAD]](s32) + ; MIPS32: G_STORE [[COPY2]](s32), [[COPY]](p0) :: (store 1 into %ir.px) + ; MIPS32: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %4:_(s32) = G_LOAD %1(p0) :: (load 1 from %ir.py) + %3:_(s32) = COPY %4(s32) + G_STORE %3(s32), %0(p0) :: (store 1 into %ir.px) + RetRA + +... +--- +name: load_store_i16 +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i16 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; MIPS32: [[LOAD:%[0-9]+]]:gprb(s32) = G_LOAD [[COPY1]](p0) :: (load 2 from %ir.py) + ; MIPS32: [[COPY2:%[0-9]+]]:gprb(s32) = COPY [[LOAD]](s32) + ; MIPS32: G_STORE [[COPY2]](s32), [[COPY]](p0) :: (store 2 into %ir.px) + ; MIPS32: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %4:_(s32) = G_LOAD %1(p0) :: (load 2 from %ir.py) + %3:_(s32) = COPY %4(s32) + G_STORE %3(s32), %0(p0) :: (store 2 into %ir.px) + RetRA + +... +--- +name: load_store_i32 +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; MIPS32-LABEL: name: load_store_i32 + ; MIPS32: liveins: $a0, $a1 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; MIPS32: [[LOAD:%[0-9]+]]:gprb(s32) = G_LOAD [[COPY1]](p0) :: (load 4 from %ir.py) + ; MIPS32: G_STORE [[LOAD]](s32), [[COPY]](p0) :: (store 4 into %ir.px) + ; MIPS32: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(s32) = G_LOAD %1(p0) :: (load 4 from %ir.py) + G_STORE %2(s32), %0(p0) :: (store 4 into %ir.px) + RetRA + +...