Index: llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -49,6 +49,32 @@ const LegalizerInfo &LI; const TargetLowering &TLI; + class SplitTypeOffset { + private: + unsigned Offset; + unsigned TotalSize; + bool isBigEndian; + + public: + SplitTypeOffset(unsigned TotalSize, bool isBigEndian) + : TotalSize(TotalSize), isBigEndian(isBigEndian) { + Offset = isBigEndian ? TotalSize : 0; + } + + unsigned getNextOffset(unsigned Step) { + unsigned result; + if (isBigEndian) { + Offset -= Step; + result = Offset; + } else { + result = Offset; + Offset += Step; + } + assert(result < TotalSize); + return result; + } + }; + public: enum LegalizeResult { /// Instruction was already legal and no change was made to the Index: llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -4098,12 +4098,12 @@ // handled. auto MMO = LdStMI.getMMO(); auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl &ValRegs, - unsigned Offset) -> unsigned { + unsigned NumParts, + SplitTypeOffset Offset) -> SplitTypeOffset { MachineFunction &MF = MIRBuilder.getMF(); unsigned PartSize = PartTy.getSizeInBits(); - for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize; - Offset += PartSize, ++Idx) { - unsigned ByteOffset = Offset / 8; + for (unsigned Idx = 0, E = NumParts; Idx != E; ++Idx) { + unsigned ByteOffset = Offset.getNextOffset(PartSize) / 8; Register NewAddrReg; MIRBuilder.materializePtrAdd(NewAddrReg, AddrReg, OffsetTy, ByteOffset); @@ -4123,11 +4123,13 @@ return Offset; }; - unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0); + bool isBigEndian = MIRBuilder.getDataLayout().isBigEndian(); + SplitTypeOffset HandledOffset = splitTypePieces( + NarrowTy, NarrowRegs, NumParts, SplitTypeOffset(TotalSize, isBigEndian)); // Handle the rest of the register if this isn't an even type breakdown. if (LeftoverTy.isValid()) - splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset); + splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset); if (IsLoad) { insertParts(ValReg, ValTy, NarrowTy, NarrowRegs, Index: llvm/lib/Target/M68k/GISel/M68kLegalizerInfo.cpp =================================================================== --- llvm/lib/Target/M68k/GISel/M68kLegalizerInfo.cpp +++ llvm/lib/Target/M68k/GISel/M68kLegalizerInfo.cpp @@ -18,17 +18,26 @@ #include "llvm/IR/Type.h" using namespace llvm; +using namespace LegalityPredicates; M68kLegalizerInfo::M68kLegalizerInfo(const M68kSubtarget &ST) { using namespace TargetOpcode; + const LLT s8 = LLT::scalar(8); + const LLT s16 = LLT::scalar(16); const LLT s32 = LLT::scalar(32); const LLT p0 = LLT::pointer(0, 32); + getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL, G_UDIV, G_CONSTANT}) + .clampScalar(0, s32, s32) .legalFor({s32}); + getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0}); getActionDefinitionsBuilder({G_STORE, G_LOAD}) + .clampScalar(0, s8, s32) .legalForTypesWithMemDesc({{s32, p0, s32, 4}}) + .legalForTypesWithMemDesc({{s16, p0, s16, 2}}) + .legalForTypesWithMemDesc({{s8, p0, s8, 1}}) .legalForTypesWithMemDesc({{p0, p0, s32, 4}}); getActionDefinitionsBuilder(G_PTR_ADD).legalFor({{p0, s32}}); Index: llvm/test/CodeGen/M68k/GlobalISel/legalizer_load_store.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M68k/GlobalISel/legalizer_load_store.ll @@ -0,0 +1,31 @@ +; RUN: llc -mtriple=m68k -global-isel -stop-after=legalizer %s -o - | FileCheck %s + +define void @test_store_i64(i64* %0) nounwind { +; CHECK-LABEL: name: test_store_i64 +; CHECK: [[FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 +; CHECK-NEXT: [[PTR_Hi:%[0-9]+]]:_(p0) = G_LOAD [[FI]](p0) +; CHECK-NEXT: [[Lo:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 +; CHECK-NEXT: [[Hi:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 +; CHECK-NEXT: [[Offset:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 +; CHECK-NEXT: [[PTR_Lo:%[0-9]+]]:_(p0) = G_PTR_ADD [[PTR_Hi]], [[Offset]](s32) +; CHECK-NEXT: G_STORE [[Lo]](s32), [[PTR_Lo]](p0) +; CHECK-NEXT: G_STORE [[Hi]](s32), [[PTR_Hi]](p0) +; CHECK-NEXT: RTS + store i64 8589934593, i64* %0 + ret void +} + +define i64 @test_load_i64(i64* %0) nounwind { +; CHECK-LABEL: name: test_load_i64 +; CHECK: [[FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 +; CHECK-NEXT: [[PTR_Hi:%[0-9]+]]:_(p0) = G_LOAD [[FI]](p0) +; CHECK-NEXT: [[Offset:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 +; CHECK-NEXT: [[PTR_Lo:%[0-9]+]]:_(p0) = G_PTR_ADD [[PTR_Hi]], [[Offset]](s32) +; CHECK-NEXT: [[Lo:%[0-9]+]]:_(s32) = G_LOAD [[PTR_Lo]] +; CHECK-NEXT: [[Hi:%[0-9]+]]:_(s32) = G_LOAD [[PTR_Hi]] +; CHECK-NEXT: $d1 = COPY [[Lo]] +; CHECK-NEXT: $d0 = COPY [[Hi]] +; RTS implicit $d1, implicit $d0 + %2 = load i64, i64* %0 + ret i64 %2 +} \ No newline at end of file