Skip to content

Commit cf12c78

Browse files
committed
[GlobalISel] Translate calls to memcpy et al to G_INTRINSIC_W_SIDE_EFFECTs and legalize later.
I plan on adding memcpy optimizations in the GlobalISel pipeline, but we can't do that unless we delay lowering to actual function calls. This patch changes the translator to generate G_INTRINSIC_W_SIDE_EFFECTS for these functions, and then have each target specify that using the new custom legalizer for intrinsics hook that they want it expanded it a libcall. Differential Revision: https://reviews.llvm.org/D64895 llvm-svn: 366516
1 parent 3d9955c commit cf12c78

File tree

15 files changed

+277
-123
lines changed

15 files changed

+277
-123
lines changed

llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,8 @@ class IRTranslator : public MachineFunctionPass {
213213
bool translateStore(const User &U, MachineIRBuilder &MIRBuilder);
214214

215215
/// Translate an LLVM string intrinsic (memcpy, memset, ...).
216-
bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder,
217-
unsigned ID);
216+
bool translateMemFunc(const CallInst &CI, MachineIRBuilder &MIRBuilder,
217+
Intrinsic::ID ID);
218218

219219
void getStackGuard(Register DstReg, MachineIRBuilder &MIRBuilder);
220220

llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
236236
const CallLowering::ArgInfo &Result,
237237
ArrayRef<CallLowering::ArgInfo> Args);
238238

239+
/// Create a libcall to memcpy et al.
240+
LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder,
241+
MachineRegisterInfo &MRI,
242+
MachineInstr &MI);
243+
239244
} // End namespace llvm.
240245

241246
#endif

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,12 @@ class MachineInstr
16071607
/// to a register def in this instruction and point them to \p Reg instead.
16081608
void changeDebugValuesDefReg(unsigned Reg);
16091609

1610+
/// Returns the Intrinsic::ID for this instruction.
1611+
/// \pre Must have an intrinsic ID operand.
1612+
unsigned getIntrinsicID() const {
1613+
return getOperand(getNumExplicitDefs()).getIntrinsicID();
1614+
}
1615+
16101616
private:
16111617
/// If this instruction is embedded into a MachineFunction, return the
16121618
/// MachineRegisterInfo object for the current function, otherwise

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,54 +1119,46 @@ bool IRTranslator::translateGetElementPtr(const User &U,
11191119
return true;
11201120
}
11211121

1122-
bool IRTranslator::translateMemfunc(const CallInst &CI,
1122+
bool IRTranslator::translateMemFunc(const CallInst &CI,
11231123
MachineIRBuilder &MIRBuilder,
1124-
unsigned ID) {
1124+
Intrinsic::ID ID) {
11251125

11261126
// If the source is undef, then just emit a nop.
1127-
if (isa<UndefValue>(CI.getArgOperand(1))) {
1128-
switch (ID) {
1129-
case Intrinsic::memmove:
1130-
case Intrinsic::memcpy:
1131-
case Intrinsic::memset:
1132-
return true;
1133-
default:
1134-
break;
1135-
}
1136-
}
1137-
1138-
LLT SizeTy = getLLTForType(*CI.getArgOperand(2)->getType(), *DL);
1139-
Type *DstTy = CI.getArgOperand(0)->getType();
1140-
if (cast<PointerType>(DstTy)->getAddressSpace() != 0 ||
1141-
SizeTy.getSizeInBits() != DL->getPointerSizeInBits(0))
1142-
return false;
1127+
if (isa<UndefValue>(CI.getArgOperand(1)))
1128+
return true;
11431129

1144-
SmallVector<CallLowering::ArgInfo, 8> Args;
1145-
for (int i = 0; i < 3; ++i) {
1146-
const auto &Arg = CI.getArgOperand(i);
1147-
Args.emplace_back(getOrCreateVReg(*Arg), Arg->getType());
1130+
ArrayRef<Register> Res;
1131+
auto ICall = MIRBuilder.buildIntrinsic(ID, Res, true);
1132+
for (auto AI = CI.arg_begin(), AE = CI.arg_end(); std::next(AI) != AE; ++AI)
1133+
ICall.addUse(getOrCreateVReg(**AI));
1134+
1135+
unsigned DstAlign = 0, SrcAlign = 0;
1136+
unsigned IsVol =
1137+
cast<ConstantInt>(CI.getArgOperand(CI.getNumArgOperands() - 1))
1138+
->getZExtValue();
1139+
1140+
if (auto *MCI = dyn_cast<MemCpyInst>(&CI)) {
1141+
DstAlign = std::max<unsigned>(MCI->getDestAlignment(), 1);
1142+
SrcAlign = std::max<unsigned>(MCI->getSourceAlignment(), 1);
1143+
} else if (auto *MMI = dyn_cast<MemMoveInst>(&CI)) {
1144+
DstAlign = std::max<unsigned>(MMI->getDestAlignment(), 1);
1145+
SrcAlign = std::max<unsigned>(MMI->getSourceAlignment(), 1);
1146+
} else {
1147+
auto *MSI = cast<MemSetInst>(&CI);
1148+
DstAlign = std::max<unsigned>(MSI->getDestAlignment(), 1);
11481149
}
11491150

1150-
const char *Callee;
1151-
switch (ID) {
1152-
case Intrinsic::memmove:
1153-
case Intrinsic::memcpy: {
1154-
Type *SrcTy = CI.getArgOperand(1)->getType();
1155-
if(cast<PointerType>(SrcTy)->getAddressSpace() != 0)
1156-
return false;
1157-
Callee = ID == Intrinsic::memcpy ? "memcpy" : "memmove";
1158-
break;
1159-
}
1160-
case Intrinsic::memset:
1161-
Callee = "memset";
1162-
break;
1163-
default:
1164-
return false;
1165-
}
1151+
// Create mem operands to store the alignment and volatile info.
1152+
auto VolFlag = IsVol ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone;
1153+
ICall.addMemOperand(MF->getMachineMemOperand(
1154+
MachinePointerInfo(CI.getArgOperand(0)),
1155+
MachineMemOperand::MOStore | VolFlag, 1, DstAlign));
1156+
if (ID != Intrinsic::memset)
1157+
ICall.addMemOperand(MF->getMachineMemOperand(
1158+
MachinePointerInfo(CI.getArgOperand(1)),
1159+
MachineMemOperand::MOLoad | VolFlag, 1, SrcAlign));
11661160

1167-
return CLI->lowerCall(MIRBuilder, CI.getCallingConv(),
1168-
MachineOperand::CreateES(Callee),
1169-
CallLowering::ArgInfo({0}, CI.getType()), Args);
1161+
return true;
11701162
}
11711163

11721164
void IRTranslator::getStackGuard(Register DstReg,
@@ -1433,7 +1425,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
14331425
case Intrinsic::memcpy:
14341426
case Intrinsic::memmove:
14351427
case Intrinsic::memset:
1436-
return translateMemfunc(CI, MIRBuilder, ID);
1428+
return translateMemFunc(CI, MIRBuilder, ID);
14371429
case Intrinsic::eh_typeid_for: {
14381430
GlobalValue *GV = ExtractTypeInfo(CI.getArgOperand(0));
14391431
Register Reg = getOrCreateVReg(CI);

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,55 @@ simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
317317
Args);
318318
}
319319

320+
LegalizerHelper::LegalizeResult
321+
llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
322+
MachineInstr &MI) {
323+
assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
324+
auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
325+
326+
SmallVector<CallLowering::ArgInfo, 3> Args;
327+
for (unsigned i = 1; i < MI.getNumOperands(); i++) {
328+
Register Reg = MI.getOperand(i).getReg();
329+
330+
// Need derive an IR type for call lowering.
331+
LLT OpLLT = MRI.getType(Reg);
332+
Type *OpTy = nullptr;
333+
if (OpLLT.isPointer())
334+
OpTy = Type::getInt8PtrTy(Ctx, OpLLT.getAddressSpace());
335+
else
336+
OpTy = IntegerType::get(Ctx, OpLLT.getSizeInBits());
337+
Args.push_back({Reg, OpTy});
338+
}
339+
340+
auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
341+
auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
342+
Intrinsic::ID ID = MI.getOperand(0).getIntrinsicID();
343+
RTLIB::Libcall RTLibcall;
344+
switch (ID) {
345+
case Intrinsic::memcpy:
346+
RTLibcall = RTLIB::MEMCPY;
347+
break;
348+
case Intrinsic::memset:
349+
RTLibcall = RTLIB::MEMSET;
350+
break;
351+
case Intrinsic::memmove:
352+
RTLibcall = RTLIB::MEMMOVE;
353+
break;
354+
default:
355+
return LegalizerHelper::UnableToLegalize;
356+
}
357+
const char *Name = TLI.getLibcallName(RTLibcall);
358+
359+
MIRBuilder.setInstr(MI);
360+
MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
361+
if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(RTLibcall),
362+
MachineOperand::CreateES(Name),
363+
CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx)), Args))
364+
return LegalizerHelper::UnableToLegalize;
365+
366+
return LegalizerHelper::Legalized;
367+
}
368+
320369
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
321370
Type *FromType) {
322371
auto ToMVT = MVT::getVT(ToType);

llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313

1414
#include "AArch64LegalizerInfo.h"
1515
#include "AArch64Subtarget.h"
16+
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
1617
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
18+
#include "llvm/CodeGen/GlobalISel/Utils.h"
1719
#include "llvm/CodeGen/MachineInstr.h"
1820
#include "llvm/CodeGen/MachineRegisterInfo.h"
1921
#include "llvm/CodeGen/TargetOpcodes.h"
@@ -617,6 +619,24 @@ bool AArch64LegalizerInfo::legalizeCustom(MachineInstr &MI,
617619
llvm_unreachable("expected switch to return");
618620
}
619621

622+
bool AArch64LegalizerInfo::legalizeIntrinsic(
623+
MachineInstr &MI, MachineRegisterInfo &MRI,
624+
MachineIRBuilder &MIRBuilder) const {
625+
switch (MI.getIntrinsicID()) {
626+
case Intrinsic::memcpy:
627+
case Intrinsic::memset:
628+
case Intrinsic::memmove:
629+
if (createMemLibcall(MIRBuilder, MRI, MI) ==
630+
LegalizerHelper::UnableToLegalize)
631+
return false;
632+
MI.eraseFromParent();
633+
return true;
634+
default:
635+
break;
636+
}
637+
return true;
638+
}
639+
620640
bool AArch64LegalizerInfo::legalizeShlAshrLshr(
621641
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder,
622642
GISelChangeObserver &Observer) const {

llvm/lib/Target/AArch64/AArch64LegalizerInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ class AArch64LegalizerInfo : public LegalizerInfo {
3131
MachineIRBuilder &MIRBuilder,
3232
GISelChangeObserver &Observer) const override;
3333

34+
bool legalizeIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
35+
MachineIRBuilder &MIRBuilder) const override;
36+
3437
private:
3538
bool legalizeVaArg(MachineInstr &MI, MachineRegisterInfo &MRI,
3639
MachineIRBuilder &MIRBuilder) const;

llvm/lib/Target/Mips/MipsLegalizerInfo.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,20 @@ bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI,
153153

154154
return false;
155155
}
156+
157+
bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
158+
MachineIRBuilder &MIRBuilder) const {
159+
switch (MI.getIntrinsicID()) {
160+
case Intrinsic::memcpy:
161+
case Intrinsic::memset:
162+
case Intrinsic::memmove:
163+
if (createMemLibcall(MIRBuilder, MRI, MI) ==
164+
LegalizerHelper::UnableToLegalize)
165+
return false;
166+
MI.eraseFromParent();
167+
return true;
168+
default:
169+
break;
170+
}
171+
return true;
172+
}

llvm/lib/Target/Mips/MipsLegalizerInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class MipsLegalizerInfo : public LegalizerInfo {
2828
bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
2929
MachineIRBuilder &MIRBuilder,
3030
GISelChangeObserver &Observer) const override;
31+
32+
bool legalizeIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
33+
MachineIRBuilder &MIRBuilder) const override;
3134
};
3235
} // end namespace llvm
3336
#endif

llvm/lib/Target/X86/X86LegalizerInfo.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "X86LegalizerInfo.h"
1414
#include "X86Subtarget.h"
1515
#include "X86TargetMachine.h"
16+
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
1617
#include "llvm/CodeGen/TargetOpcodes.h"
1718
#include "llvm/CodeGen/ValueTypes.h"
1819
#include "llvm/IR/DerivedTypes.h"
@@ -84,6 +85,24 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
8485
verify(*STI.getInstrInfo());
8586
}
8687

88+
bool X86LegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
89+
MachineRegisterInfo &MRI,
90+
MachineIRBuilder &MIRBuilder) const {
91+
switch (MI.getIntrinsicID()) {
92+
case Intrinsic::memcpy:
93+
case Intrinsic::memset:
94+
case Intrinsic::memmove:
95+
if (createMemLibcall(MIRBuilder, MRI, MI) ==
96+
LegalizerHelper::UnableToLegalize)
97+
return false;
98+
MI.eraseFromParent();
99+
return true;
100+
default:
101+
break;
102+
}
103+
return true;
104+
}
105+
87106
void X86LegalizerInfo::setLegalizerInfo32bit() {
88107

89108
const LLT p0 = LLT::pointer(0, TM.getPointerSizeInBits(0));

0 commit comments

Comments
 (0)