diff --git a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index d1f31607401..6e83270cbef 100644 --- a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -195,24 +195,29 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, continue; } - int64_t OpSegStart = DstStart - OpStart; - int64_t OpSegSize = - std::min(NarrowSize - OpSegStart, OpSegStart + OpSize); - unsigned OpSegReg = OpReg; - if (OpSegSize != OpSize) { + // OpSegStart is where this destination segment would start in OpReg if it + // extended infinitely in both directions. + int64_t ExtractOffset, InsertOffset, SegSize; + if (OpStart < DstStart) { + InsertOffset = 0; + ExtractOffset = DstStart - OpStart; + SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart); + } else { + InsertOffset = OpStart - DstStart; + ExtractOffset = 0; + SegSize = + std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart); + } + + unsigned SegReg = OpReg; + if (ExtractOffset != 0 || SegSize != OpSize) { // A genuine extract is needed. - OpSegReg = MRI.createGenericVirtualRegister(LLT::scalar(OpSegSize)); - MIRBuilder.buildExtract(OpSegReg, OpReg, - std::max(OpSegStart, (int64_t)0)); + SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); + MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset); } unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); - MIRBuilder.buildInstr(TargetOpcode::G_INSERT) - .addDef(DstReg) - .addUse(SrcRegs[i]) - .addUse(OpSegReg) - .addImm(std::max((int64_t)0, -OpSegStart)); - + MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset); DstRegs.push_back(DstReg); } diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir b/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir index 86729d64863..917f181099e 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir @@ -8,6 +8,7 @@ define void @test_inserts_3() { ret void } define void @test_inserts_4() { ret void } define void @test_inserts_5() { ret void } + define void @test_inserts_6() { ret void } ... --- @@ -69,7 +70,7 @@ body: | ; CHECK-LABEL: name: test_inserts_3 ; CHECK: [[LO:%[0-9]+]](s64) = G_LOAD ; CHECK: [[HI:%[0-9]+]](s64) = G_LOAD - ; CHECK: [[NEWLO:%[0-9]+]](s64) = G_INSERT [[LO]], %0(p0), 0 + ; CHECK: [[NEWLO:%[0-9]+]](s64) = G_PTRTOINT %0(p0) ; CHECK: G_STORE [[NEWLO]](s64) ; CHECK: G_STORE [[HI]] %0:_(p0) = COPY %x0 @@ -120,3 +121,21 @@ body: | %4:_(s128) = G_INSERT %3, %2, 32 RET_ReallyLR ... + +--- +name: test_inserts_6 +body: | + bb.0: + liveins: %x0, %x1, %x2 + + + ; CHECK-LABEL: name: test_inserts_6 + ; CHECK: [[VAL_LO:%[0-9]+]](s64) = G_INSERT %0, %2(s32), 32 + ; CHECK: %4(s128) = G_MERGE_VALUES [[VAL_LO]](s64), %1(s64) + %0:_(s64) = COPY %x0 + %1:_(s64) = COPY %x1 + %2:_(s32) = COPY %w2 + %3:_(s128) = G_MERGE_VALUES %0, %1 + %4:_(s128) = G_INSERT %3, %2, 32 + RET_ReallyLR +...