summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2017-03-07 21:24:33 +0000
committerTim Northover <tnorthover@apple.com>2017-03-07 21:24:33 +0000
commit2eb18d3c4bd7f0014b4b372ab137249f4fff26cf (patch)
tree46a4b4e97289e8978bd16406fa8843018392e83e
parent7f81c3d495b7b4c3c692031becb47e3019690205 (diff)
downloadbcm5719-llvm-2eb18d3c4bd7f0014b4b372ab137249f4fff26cf.tar.gz
bcm5719-llvm-2eb18d3c4bd7f0014b4b372ab137249f4fff26cf.zip
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
-rw-r--r--llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp33
-rw-r--r--llvm/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir21
2 files changed, 39 insertions, 15 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index d1f31607401..6e83270cbef 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/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/llvm/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir
index 86729d64863..917f181099e 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir
+++ b/llvm/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
+...
OpenPOWER on IntegriCloud