Index: llvm/trunk/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -118,6 +118,20 @@ unsigned Opcode; ArrayRef Types; + struct MemDesc { + uint64_t Size; + }; + + /// Operations which require memory can use this to place requirements on the + /// memory type for each MMO. + ArrayRef MMODescrs; + + constexpr LegalityQuery(unsigned Opcode, const ArrayRef Types, + const ArrayRef MMODescrs) + : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {} + constexpr LegalityQuery(unsigned Opcode, const ArrayRef Types) + : LegalityQuery(Opcode, Types, {}) {} + raw_ostream &print(raw_ostream &OS) const; }; @@ -157,6 +171,11 @@ LegalityPredicate typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, std::initializer_list> TypesInit); +/// True iff the given types for the given pair of type indexes is one of the +/// specified type pairs. +LegalityPredicate typePairAndMemSizeInSet( + unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, + std::initializer_list> TypesAndMemSizeInit); /// True iff the specified type index is a scalar. LegalityPredicate isScalar(unsigned TypeIdx); /// True iff the specified type index is a scalar that's narrower than the given @@ -168,6 +187,8 @@ /// True iff the specified type index is a scalar whose size is not a power of /// 2. LegalityPredicate sizeNotPow2(unsigned TypeIdx); +/// True iff the specified MMO index has a size that is not a power of 2 +LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx); /// True iff the specified type index is a vector whose element count is not a /// power of 2. LegalityPredicate numElementsNotPow2(unsigned TypeIdx); @@ -322,6 +343,13 @@ LegalizeRuleSet &legalFor(std::initializer_list> Types) { return actionFor(LegalizeAction::Legal, Types); } + /// The instruction is legal when type indexes 0 and 1 along with the memory + /// size is any type and size tuple in the given list. + LegalizeRuleSet &legalForTypesWithMemSize( + std::initializer_list> TypesAndMemSize) { + return legalIf(LegalityPredicates::typePairAndMemSizeInSet( + 0, 1, /*MMOIdx*/ 0, TypesAndMemSize)); + } /// The instruction is legal when type indexes 0 and 1 are both in the given /// list. That is, the type pair is in the cartesian product of the list. LegalizeRuleSet &legalForCartesianProduct(std::initializer_list Types) { @@ -427,6 +455,10 @@ LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) { return actionIf(LegalizeAction::Unsupported, Predicate); } + LegalizeRuleSet &unsupportedIfMemSizeNotPow2() { + return actionIf(LegalizeAction::Unsupported, + LegalityPredicates::memSizeInBytesNotPow2(0)); + } LegalizeRuleSet &customIf(LegalityPredicate Predicate) { return actionIf(LegalizeAction::Custom, Predicate); @@ -510,7 +542,7 @@ return moreElementsIf( [=](const LegalityQuery &Query) { LLT VecTy = Query.Types[TypeIdx]; - return VecTy.getElementType() == EltTy && + return VecTy.isVector() && VecTy.getElementType() == EltTy && VecTy.getNumElements() < MinElements; }, [=](const LegalityQuery &Query) { @@ -525,7 +557,7 @@ return fewerElementsIf( [=](const LegalityQuery &Query) { LLT VecTy = Query.Types[TypeIdx]; - return VecTy.getElementType() == EltTy && + return VecTy.isVector() && VecTy.getElementType() == EltTy && VecTy.getNumElements() > MaxElements; }, [=](const LegalityQuery &Query) { Index: llvm/trunk/lib/CodeGen/GlobalISel/LegalityPredicates.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/LegalityPredicates.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/LegalityPredicates.cpp @@ -41,6 +41,18 @@ }; } +LegalityPredicate LegalityPredicates::typePairAndMemSizeInSet( + unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, + std::initializer_list> TypesAndMemSizeInit) { + SmallVector, 4> TypesAndMemSize = TypesAndMemSizeInit; + return [=](const LegalityQuery &Query) { + std::tuple Match = { + Query.Types[TypeIdx0], Query.Types[TypeIdx1], Query.MMODescrs[MMOIdx].Size}; + return std::find(TypesAndMemSize.begin(), TypesAndMemSize.end(), Match) != + TypesAndMemSize.end(); + }; +} + LegalityPredicate LegalityPredicates::isScalar(unsigned TypeIdx) { return [=](const LegalityQuery &Query) { return Query.Types[TypeIdx].isScalar(); @@ -70,6 +82,12 @@ }; } +LegalityPredicate LegalityPredicates::memSizeInBytesNotPow2(unsigned MMOIdx) { + return [=](const LegalityQuery &Query) { + return !isPowerOf2_32(Query.MMODescrs[MMOIdx].Size /* In Bytes */); + }; +} + LegalityPredicate LegalityPredicates::numElementsNotPow2(unsigned TypeIdx) { return [=](const LegalityQuery &Query) { const LLT &QueryTy = Query.Types[TypeIdx]; Index: llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -272,8 +272,8 @@ MIRBuilder.setInstr(MI); - int64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - int64_t NarrowSize = NarrowTy.getSizeInBits(); + uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + uint64_t NarrowSize = NarrowTy.getSizeInBits(); switch (MI.getOpcode()) { default: @@ -339,8 +339,8 @@ extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); unsigned OpReg = MI.getOperand(0).getReg(); - int64_t OpStart = MI.getOperand(2).getImm(); - int64_t OpSize = MRI.getType(OpReg).getSizeInBits(); + uint64_t OpStart = MI.getOperand(2).getImm(); + uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); for (int i = 0; i < NumParts; ++i) { unsigned SrcStart = i * NarrowSize; @@ -355,7 +355,8 @@ // OpSegStart is where this destination segment would start in OpReg if it // extended infinitely in both directions. - int64_t ExtractOffset, SegSize; + int64_t ExtractOffset; + uint64_t SegSize; if (OpStart < SrcStart) { ExtractOffset = 0; SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart); @@ -391,8 +392,8 @@ extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); unsigned OpReg = MI.getOperand(2).getReg(); - int64_t OpStart = MI.getOperand(3).getImm(); - int64_t OpSize = MRI.getType(OpReg).getSizeInBits(); + uint64_t OpStart = MI.getOperand(3).getImm(); + uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); for (int i = 0; i < NumParts; ++i) { unsigned DstStart = i * NarrowSize; @@ -409,7 +410,8 @@ // OpSegStart is where this destination segment would start in OpReg if it // extended infinitely in both directions. - int64_t ExtractOffset, InsertOffset, SegSize; + int64_t ExtractOffset, InsertOffset; + uint64_t SegSize; if (OpStart < DstStart) { InsertOffset = 0; ExtractOffset = DstStart - OpStart; @@ -443,6 +445,14 @@ // NarrowSize. if (SizeOp0 % NarrowSize != 0) return UnableToLegalize; + + const auto &MMO = **MI.memoperands_begin(); + // This implementation doesn't work for atomics. Give up instead of doing + // something invalid. + if (MMO.getOrdering() != AtomicOrdering::NotAtomic || + MMO.getFailureOrdering() != AtomicOrdering::NotAtomic) + return UnableToLegalize; + int NumParts = SizeOp0 / NarrowSize; LLT OffsetTy = LLT::scalar( MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); @@ -453,12 +463,16 @@ unsigned SrcReg = 0; unsigned Adjustment = i * NarrowSize / 8; + MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand( + MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(), + NarrowSize / 8, i == 0 ? MMO.getAlignment() : NarrowSize / 8, + MMO.getAAInfo(), MMO.getRanges(), MMO.getSyncScopeID(), + MMO.getOrdering(), MMO.getFailureOrdering()); + MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy, Adjustment); - // TODO: This is conservatively correct, but we probably want to split the - // memory operands in the future. - MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin()); + MIRBuilder.buildLoad(DstReg, SrcReg, *SplitMMO); DstRegs.push_back(DstReg); } @@ -472,6 +486,14 @@ // NarrowSize. if (SizeOp0 % NarrowSize != 0) return UnableToLegalize; + + const auto &MMO = **MI.memoperands_begin(); + // This implementation doesn't work for atomics. Give up instead of doing + // something invalid. + if (MMO.getOrdering() != AtomicOrdering::NotAtomic || + MMO.getFailureOrdering() != AtomicOrdering::NotAtomic) + return UnableToLegalize; + int NumParts = SizeOp0 / NarrowSize; LLT OffsetTy = LLT::scalar( MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); @@ -483,12 +505,16 @@ unsigned DstReg = 0; unsigned Adjustment = i * NarrowSize / 8; + MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand( + MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(), + NarrowSize / 8, i == 0 ? MMO.getAlignment() : NarrowSize / 8, + MMO.getAAInfo(), MMO.getRanges(), MMO.getSyncScopeID(), + MMO.getOrdering(), MMO.getFailureOrdering()); + MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy, Adjustment); - // TODO: This is conservatively correct, but we probably want to split the - // memory operands in the future. - MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin()); + MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO); } MI.eraseFromParent(); return Legalized; Index: llvm/trunk/lib/CodeGen/GlobalISel/LegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -42,11 +42,18 @@ cl::Hidden); raw_ostream &LegalityQuery::print(raw_ostream &OS) const { - OS << Opcode << ", {"; + OS << Opcode << ", Tys={"; for (const auto &Type : Types) { OS << Type << ", "; } + OS << "}, Opcode="; + + OS << Opcode << ", MMOs={"; + for (const auto &MMODescr : MMODescrs) { + OS << MMODescr.Size << ", "; + } OS << "}"; + return OS; } @@ -330,7 +337,12 @@ LLT Ty = getTypeFromTypeIdx(MI, MRI, i, TypeIdx); Types.push_back(Ty); } - return getAction({MI.getOpcode(), Types}); + + SmallVector MemDescrs; + for (const auto &MMO : MI.memoperands()) + MemDescrs.push_back({MMO->getSize() /* in bytes */ * 8}); + + return getAction({MI.getOpcode(), Types, MemDescrs}); } bool LegalizerInfo::isLegal(const MachineInstr &MI, Index: llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -136,8 +136,15 @@ .widenScalarToNextPow2(0); getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalFor( - {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}, {p0, p0}, {v2s32, p0}}) + .legalForTypesWithMemSize({{s8, p0, 8}, + {s16, p0, 16}, + {s32, p0, 32}, + {s64, p0, 64}, + {p0, p0, 64}, + {v2s32, p0, 64}}) + // TODO: We could support sum-of-pow2's but the lowering code doesn't know + // how to do that yet. + .unsupportedIfMemSizeNotPow2() .clampScalar(0, s8, s64) .widenScalarToNextPow2(0) .clampNumElements(0, v2s32, v2s32); Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-extracts.mir =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-extracts.mir +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-extracts.mir @@ -12,10 +12,10 @@ ; CHECK-LABEL: name: test_extracts_1 ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 - ; CHECK: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[COPY]](p0) :: (load 16) + ; CHECK: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[COPY]](p0) :: (load 8, align 16) ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 ; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[C]](s64) - ; CHECK: [[LOAD1:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 16) + ; CHECK: [[LOAD1:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 8) ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY [[LOAD]](s64) ; CHECK: G_STORE [[COPY1]](s64), [[COPY]](p0) :: (store 8) ; CHECK: RET_ReallyLR @@ -37,10 +37,10 @@ ; Low extraction wipes takes whole low register. High extraction is real. ; CHECK-LABEL: name: test_extracts_2 ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 - ; CHECK: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[COPY]](p0) :: (load 16) + ; CHECK: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[COPY]](p0) :: (load 8, align 16) ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 ; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[C]](s64) - ; CHECK: [[LOAD1:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 16) + ; CHECK: [[LOAD1:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load 8) ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY [[LOAD]](s64) ; CHECK: [[EXTRACT:%[0-9]+]]:_(s32) = G_EXTRACT [[LOAD1]](s64), 0 ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY [[EXTRACT]](s32) Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir @@ -62,10 +62,10 @@ %13:_(s64) = G_BITCAST %7 $x0 = COPY %13 - ; CHECK: [[LOAD0:%[0-9]+]]:_(s64) = G_LOAD %0(p0) :: (load 16 from %ir.addr) + ; CHECK: [[LOAD0:%[0-9]+]]:_(s64) = G_LOAD %0(p0) :: (load 8 from %ir.addr, align 16) ; CHECK: [[OFFSET1:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 ; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_GEP %0, [[OFFSET1]](s64) - ; CHECK: [[LOAD1:%[0-9]+]]:_(s64) = G_LOAD [[GEP1]](p0) :: (load 16 from %ir.addr) + ; CHECK: [[LOAD1:%[0-9]+]]:_(s64) = G_LOAD [[GEP1]](p0) :: (load 8 from %ir.addr + 8) ; CHECK: %8:_(s128) = G_MERGE_VALUES [[LOAD0]](s64), [[LOAD1]](s64) %8(s128) = G_LOAD %0(p0) :: (load 16 from %ir.addr) %14:_(s64) = G_TRUNC %8 @@ -120,10 +120,10 @@ ; CHECK: G_STORE %0(p0), %0(p0) :: (store 8 into %ir.addr) G_STORE %0(p0), %0(p0) :: (store 8 into %ir.addr) - ; CHECK: G_STORE %5(s64), %0(p0) :: (store 16 into %ir.addr) + ; CHECK: G_STORE %5(s64), %0(p0) :: (store 8 into %ir.addr, align 16) ; CHECK: [[OFFSET1:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 ; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_GEP %0, [[OFFSET1]](s64) - ; CHECK: G_STORE %6(s64), [[GEP1]](p0) :: (store 16 into %ir.addr) + ; CHECK: G_STORE %6(s64), [[GEP1]](p0) :: (store 8 into %ir.addr + 8) %6(s64) = G_PTRTOINT %0(p0) %7(s128) = G_MERGE_VALUES %5, %6 G_STORE %7, %0 :: (store 16 into %ir.addr) Index: llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-legalize-vfp4.mir =================================================================== --- llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-legalize-vfp4.mir +++ llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-legalize-vfp4.mir @@ -95,10 +95,12 @@ ; SOFT-ABI: [[SP1:%[0-9]+]]:_(p0) = COPY $sp ; SOFT-ABI: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; SOFT-ABI: [[FI1:%[0-9]+]]:_(p0) = G_GEP [[SP1]], [[OFF1]](s32) - ; SOFT-ABI: G_STORE [[Y0]](s32), [[FI1]](p0){{.*}}store 8 into stack + + ; FIXME: This ought to be align 8 but ARM's call lowering hardcodes it to 0 + ; SOFT-ABI: G_STORE [[Y0]](s32), [[FI1]](p0){{.*}}store 4 into stack, align 0) ; SOFT-ABI: [[OFF2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 ; SOFT-ABI: [[FI2:%[0-9]+]]:_(p0) = G_GEP [[FI1]], [[OFF2]](s32) - ; SOFT-ABI: G_STORE [[Y1]](s32), [[FI2]](p0){{.*}}store 8 into stack + ; SOFT-ABI: G_STORE [[Y1]](s32), [[FI2]](p0){{.*}}store 4 into stack + 4) ; SOFT-ABI: BL &fma, {{.*}}, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 ; SOFT-ABI-DAG: [[R0:%[0-9]+]]:_(s32) = COPY $r0 ; SOFT-ABI-DAG: [[R1:%[0-9]+]]:_(s32) = COPY $r1 Index: llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-memop-scalar.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-memop-scalar.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-memop-scalar.mir @@ -96,14 +96,14 @@ ; X64: G_STORE [[LOAD]](s64), [[DEF]](p0) :: (store 8) ; X32-LABEL: name: test_memop_s64 ; X32: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; X32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[DEF]](p0) :: (load 8) + ; X32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[DEF]](p0) :: (load 4, align 8) ; X32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 ; X32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[DEF]], [[C]](s32) - ; X32: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[GEP]](p0) :: (load 8) - ; X32: G_STORE [[LOAD]](s32), [[DEF]](p0) :: (store 8) + ; X32: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[GEP]](p0) :: (load 4) + ; X32: G_STORE [[LOAD]](s32), [[DEF]](p0) :: (store 4, align 8) ; X32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 ; X32: [[GEP1:%[0-9]+]]:_(p0) = G_GEP [[DEF]], [[C1]](s32) - ; X32: G_STORE [[LOAD1]](s32), [[GEP1]](p0) :: (store 8) + ; X32: G_STORE [[LOAD1]](s32), [[GEP1]](p0) :: (store 4) %0(p0) = IMPLICIT_DEF %1(s64) = G_LOAD %0(p0) :: (load 8) Index: llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-undef.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-undef.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-undef.mir @@ -14,38 +14,38 @@ ; X64: [[DEF1:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF ; X64: G_STORE [[DEF1]](s8), [[DEF]](p0) :: (store 1) ; X64: [[DEF2:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF - ; X64: G_STORE [[DEF2]](s8), [[DEF]](p0) :: (store 8) + ; X64: G_STORE [[DEF2]](s8), [[DEF]](p0) :: (store 1) ; X64: [[DEF3:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF - ; X64: G_STORE [[DEF3]](s16), [[DEF]](p0) :: (store 16) + ; X64: G_STORE [[DEF3]](s16), [[DEF]](p0) :: (store 2) ; X64: [[DEF4:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF - ; X64: G_STORE [[DEF4]](s32), [[DEF]](p0) :: (store 32) + ; X64: G_STORE [[DEF4]](s32), [[DEF]](p0) :: (store 4) ; X64: [[DEF5:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF - ; X64: G_STORE [[DEF5]](s64), [[DEF]](p0) :: (store 64) + ; X64: G_STORE [[DEF5]](s64), [[DEF]](p0) :: (store 8) ; X32-LABEL: name: test_implicit_def ; X32: [[DEF:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF ; X32: [[DEF1:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF ; X32: G_STORE [[DEF1]](s8), [[DEF]](p0) :: (store 1) ; X32: [[DEF2:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF - ; X32: G_STORE [[DEF2]](s8), [[DEF]](p0) :: (store 8) + ; X32: G_STORE [[DEF2]](s8), [[DEF]](p0) :: (store 1) ; X32: [[DEF3:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF - ; X32: G_STORE [[DEF3]](s16), [[DEF]](p0) :: (store 16) + ; X32: G_STORE [[DEF3]](s16), [[DEF]](p0) :: (store 2) ; X32: [[DEF4:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF - ; X32: G_STORE [[DEF4]](s32), [[DEF]](p0) :: (store 32) + ; X32: G_STORE [[DEF4]](s32), [[DEF]](p0) :: (store 4) ; X32: [[DEF5:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF ; X32: [[DEF6:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF - ; X32: G_STORE [[DEF5]](s32), [[DEF]](p0) :: (store 64) + ; X32: G_STORE [[DEF5]](s32), [[DEF]](p0) :: (store 4, align 8) ; X32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 ; X32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[DEF]], [[C]](s32) - ; X32: G_STORE [[DEF6]](s32), [[GEP]](p0) :: (store 64) + ; X32: G_STORE [[DEF6]](s32), [[GEP]](p0) :: (store 4) %5:_(p0) = G_IMPLICIT_DEF %0:_(s1) = G_IMPLICIT_DEF G_STORE %0, %5 ::(store 1) %1:_(s8) = G_IMPLICIT_DEF - G_STORE %1, %5 ::(store 8) + G_STORE %1, %5 ::(store 1) %2:_(s16) = G_IMPLICIT_DEF - G_STORE %2, %5 ::(store 16) + G_STORE %2, %5 ::(store 2) %3:_(s32) = G_IMPLICIT_DEF - G_STORE %3, %5 ::(store 32) + G_STORE %3, %5 ::(store 4) %4:_(s64) = G_IMPLICIT_DEF - G_STORE %4, %5 ::(store 64) + G_STORE %4, %5 ::(store 8) ...