forked from OSchip/llvm-project
GlobalISel: fix legalization of G_INSERT
We were calculating incorrect extract/insert offsets by trying to be too tricksy with min/max. It's clearer to just split the logic up into "register starts before this segment" vs "after". llvm-svn: 297226
This commit is contained in:
parent
7f81c3d495
commit
2eb18d3c4b
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
...
|
||||
|
|
Loading…
Reference in New Issue