1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-24 13:33:37 +02:00

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:
Tim Northover 2017-03-07 21:24:33 +00:00
parent 98a3994b3f
commit 1ba2541b03
2 changed files with 39 additions and 15 deletions

View File

@ -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);
}

View File

@ -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
...