[globalisel][legalizer] G_LOAD/G_STORE NarrowScalar should not emit G_GEP x, 0.
Summary:
When legalizing G_LOAD/G_STORE using NarrowScalar, we should avoid emitting
%0 = G_CONSTANT ty 0
%1 = G_GEP %x, %0
since it's cheaper to not emit the redundant instructions than it is to fold them
away later.
Reviewers: qcolombet, t.p.northover, ab, rovka, aditya_nandakumar, kristof.beyls
Reviewed By: qcolombet
Subscribers: javed.absar, llvm-commits, igorb
Differential Revision: https://reviews.llvm.org/D32746
llvm-svn: 305340
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index ef5818d..e05b355 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -237,17 +237,18 @@
unsigned NarrowSize = NarrowTy.getSizeInBits();
int NumParts =
MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
- LLT NarrowPtrTy = LLT::pointer(
- MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
+ LLT OffsetTy = LLT::scalar(
+ MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
SmallVector<unsigned, 2> DstRegs;
for (int i = 0; i < NumParts; ++i) {
unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
- unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
- unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
+ unsigned SrcReg = 0;
+ unsigned Adjustment = i * NarrowSize / 8;
- MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
- MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
+ 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());
@@ -263,17 +264,19 @@
unsigned NarrowSize = NarrowTy.getSizeInBits();
int NumParts =
MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
- LLT NarrowPtrTy = LLT::pointer(
- MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
+ LLT OffsetTy = LLT::scalar(
+ MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
SmallVector<unsigned, 2> SrcRegs;
extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
for (int i = 0; i < NumParts; ++i) {
- unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
- unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
- MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
- MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
+ unsigned DstReg = 0;
+ unsigned Adjustment = i * NarrowSize / 8;
+
+ 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());
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 54ef7e5..79d312f 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -191,6 +191,24 @@
.addUse(Op1);
}
+Optional<MachineInstrBuilder>
+MachineIRBuilder::materializeGEP(unsigned &Res, unsigned Op0,
+ const LLT &ValueTy, uint64_t Value) {
+ assert(Res == 0 && "Res is a result argument");
+ assert(ValueTy.isScalar() && "invalid offset type");
+
+ if (Value == 0) {
+ Res = Op0;
+ return None;
+ }
+
+ Res = MRI->createGenericVirtualRegister(MRI->getType(Op0));
+ unsigned TmpReg = MRI->createGenericVirtualRegister(ValueTy);
+
+ buildConstant(TmpReg, Value);
+ return buildGEP(Res, Op0, TmpReg);
+}
+
MachineInstrBuilder MachineIRBuilder::buildPtrMask(unsigned Res, unsigned Op0,
uint32_t NumBits) {
assert(MRI->getType(Res).isPointer() &&