10699ef39SMatt Arsenault //===-- AMDGPULowerIntrinsics.cpp -----------------------------------------===//
20699ef39SMatt Arsenault //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60699ef39SMatt Arsenault //
70699ef39SMatt Arsenault //===----------------------------------------------------------------------===//
80699ef39SMatt Arsenault
90699ef39SMatt Arsenault #include "AMDGPU.h"
10c90347d7SStanislav Mekhanoshin #include "AMDGPUSubtarget.h"
119cd1cdf8SSean Fertile #include "llvm/Analysis/TargetTransformInfo.h"
126a87e9b0Sdfukalov #include "llvm/CodeGen/TargetPassConfig.h"
130699ef39SMatt Arsenault #include "llvm/IR/Constants.h"
140699ef39SMatt Arsenault #include "llvm/IR/Instructions.h"
150699ef39SMatt Arsenault #include "llvm/IR/IntrinsicInst.h"
166a87e9b0Sdfukalov #include "llvm/IR/IntrinsicsR600.h"
170699ef39SMatt Arsenault #include "llvm/IR/Module.h"
18560d7e04Sdfukalov #include "llvm/Support/CommandLine.h"
196a87e9b0Sdfukalov #include "llvm/Target/TargetMachine.h"
200699ef39SMatt Arsenault #include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
210699ef39SMatt Arsenault
220699ef39SMatt Arsenault #define DEBUG_TYPE "amdgpu-lower-intrinsics"
230699ef39SMatt Arsenault
240699ef39SMatt Arsenault using namespace llvm;
250699ef39SMatt Arsenault
260699ef39SMatt Arsenault namespace {
270699ef39SMatt Arsenault
287d3aace3SMatt Arsenault static int MaxStaticSize;
297d3aace3SMatt Arsenault
307d3aace3SMatt Arsenault static cl::opt<int, true> MemIntrinsicExpandSizeThresholdOpt(
317d3aace3SMatt Arsenault "amdgpu-mem-intrinsic-expand-size",
327d3aace3SMatt Arsenault cl::desc("Set minimum mem intrinsic size to expand in IR"),
337d3aace3SMatt Arsenault cl::location(MaxStaticSize),
347d3aace3SMatt Arsenault cl::init(1024),
357d3aace3SMatt Arsenault cl::Hidden);
367d3aace3SMatt Arsenault
370699ef39SMatt Arsenault
380699ef39SMatt Arsenault class AMDGPULowerIntrinsics : public ModulePass {
39c90347d7SStanislav Mekhanoshin private:
40c90347d7SStanislav Mekhanoshin bool makeLIDRangeMetadata(Function &F) const;
41c90347d7SStanislav Mekhanoshin
420699ef39SMatt Arsenault public:
430699ef39SMatt Arsenault static char ID;
440699ef39SMatt Arsenault
AMDGPULowerIntrinsics()458b61764cSFrancis Visoiu Mistrih AMDGPULowerIntrinsics() : ModulePass(ID) {}
468b61764cSFrancis Visoiu Mistrih
470699ef39SMatt Arsenault bool runOnModule(Module &M) override;
489cd1cdf8SSean Fertile bool expandMemIntrinsicUses(Function &F);
getPassName() const490699ef39SMatt Arsenault StringRef getPassName() const override {
500699ef39SMatt Arsenault return "AMDGPU Lower Intrinsics";
510699ef39SMatt Arsenault }
529cd1cdf8SSean Fertile
getAnalysisUsage(AnalysisUsage & AU) const539cd1cdf8SSean Fertile void getAnalysisUsage(AnalysisUsage &AU) const override {
549cd1cdf8SSean Fertile AU.addRequired<TargetTransformInfoWrapperPass>();
559cd1cdf8SSean Fertile }
560699ef39SMatt Arsenault };
570699ef39SMatt Arsenault
580699ef39SMatt Arsenault }
590699ef39SMatt Arsenault
600699ef39SMatt Arsenault char AMDGPULowerIntrinsics::ID = 0;
610699ef39SMatt Arsenault
620699ef39SMatt Arsenault char &llvm::AMDGPULowerIntrinsicsID = AMDGPULowerIntrinsics::ID;
630699ef39SMatt Arsenault
648b61764cSFrancis Visoiu Mistrih INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false,
658b61764cSFrancis Visoiu Mistrih false)
660699ef39SMatt Arsenault
670699ef39SMatt Arsenault // TODO: Should refine based on estimated number of accesses (e.g. does it
680699ef39SMatt Arsenault // require splitting based on alignment)
shouldExpandOperationWithSize(Value * Size)690699ef39SMatt Arsenault static bool shouldExpandOperationWithSize(Value *Size) {
700699ef39SMatt Arsenault ConstantInt *CI = dyn_cast<ConstantInt>(Size);
717d3aace3SMatt Arsenault return !CI || (CI->getSExtValue() > MaxStaticSize);
720699ef39SMatt Arsenault }
730699ef39SMatt Arsenault
expandMemIntrinsicUses(Function & F)749cd1cdf8SSean Fertile bool AMDGPULowerIntrinsics::expandMemIntrinsicUses(Function &F) {
750699ef39SMatt Arsenault Intrinsic::ID ID = F.getIntrinsicID();
76022c6e4fSNAKAMURA Takumi bool Changed = false;
770699ef39SMatt Arsenault
78*4bef0304SKazu Hirata for (User *U : llvm::make_early_inc_range(F.users())) {
79*4bef0304SKazu Hirata Instruction *Inst = cast<Instruction>(U);
800699ef39SMatt Arsenault
810699ef39SMatt Arsenault switch (ID) {
820699ef39SMatt Arsenault case Intrinsic::memcpy: {
830699ef39SMatt Arsenault auto *Memcpy = cast<MemCpyInst>(Inst);
840699ef39SMatt Arsenault if (shouldExpandOperationWithSize(Memcpy->getLength())) {
859cd1cdf8SSean Fertile Function *ParentFunc = Memcpy->getParent()->getParent();
869cd1cdf8SSean Fertile const TargetTransformInfo &TTI =
879cd1cdf8SSean Fertile getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*ParentFunc);
889cd1cdf8SSean Fertile expandMemCpyAsLoop(Memcpy, TTI);
890699ef39SMatt Arsenault Changed = true;
900699ef39SMatt Arsenault Memcpy->eraseFromParent();
910699ef39SMatt Arsenault }
920699ef39SMatt Arsenault
930699ef39SMatt Arsenault break;
940699ef39SMatt Arsenault }
950699ef39SMatt Arsenault case Intrinsic::memmove: {
960699ef39SMatt Arsenault auto *Memmove = cast<MemMoveInst>(Inst);
970699ef39SMatt Arsenault if (shouldExpandOperationWithSize(Memmove->getLength())) {
980699ef39SMatt Arsenault expandMemMoveAsLoop(Memmove);
990699ef39SMatt Arsenault Changed = true;
1000699ef39SMatt Arsenault Memmove->eraseFromParent();
1010699ef39SMatt Arsenault }
1020699ef39SMatt Arsenault
1030699ef39SMatt Arsenault break;
1040699ef39SMatt Arsenault }
1050699ef39SMatt Arsenault case Intrinsic::memset: {
1060699ef39SMatt Arsenault auto *Memset = cast<MemSetInst>(Inst);
1070699ef39SMatt Arsenault if (shouldExpandOperationWithSize(Memset->getLength())) {
1080699ef39SMatt Arsenault expandMemSetAsLoop(Memset);
1090699ef39SMatt Arsenault Changed = true;
1100699ef39SMatt Arsenault Memset->eraseFromParent();
1110699ef39SMatt Arsenault }
1120699ef39SMatt Arsenault
1130699ef39SMatt Arsenault break;
1140699ef39SMatt Arsenault }
1150699ef39SMatt Arsenault default:
1160699ef39SMatt Arsenault break;
1170699ef39SMatt Arsenault }
1180699ef39SMatt Arsenault }
1190699ef39SMatt Arsenault
1200699ef39SMatt Arsenault return Changed;
1210699ef39SMatt Arsenault }
1220699ef39SMatt Arsenault
makeLIDRangeMetadata(Function & F) const123c90347d7SStanislav Mekhanoshin bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const {
1248b61764cSFrancis Visoiu Mistrih auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
1258b61764cSFrancis Visoiu Mistrih if (!TPC)
126c90347d7SStanislav Mekhanoshin return false;
127c90347d7SStanislav Mekhanoshin
1288b61764cSFrancis Visoiu Mistrih const TargetMachine &TM = TPC->getTM<TargetMachine>();
129c90347d7SStanislav Mekhanoshin bool Changed = false;
130c90347d7SStanislav Mekhanoshin
131c90347d7SStanislav Mekhanoshin for (auto *U : F.users()) {
132c90347d7SStanislav Mekhanoshin auto *CI = dyn_cast<CallInst>(U);
133c90347d7SStanislav Mekhanoshin if (!CI)
134c90347d7SStanislav Mekhanoshin continue;
135c90347d7SStanislav Mekhanoshin
136a1bc37c9SMatt Arsenault Function *Caller = CI->getParent()->getParent();
137a1bc37c9SMatt Arsenault const AMDGPUSubtarget &ST = AMDGPUSubtarget::get(TM, *Caller);
1386c770a09SMatt Arsenault Changed |= ST.makeLIDRangeMetadata(CI);
139c90347d7SStanislav Mekhanoshin }
140c90347d7SStanislav Mekhanoshin return Changed;
141c90347d7SStanislav Mekhanoshin }
142c90347d7SStanislav Mekhanoshin
runOnModule(Module & M)1430699ef39SMatt Arsenault bool AMDGPULowerIntrinsics::runOnModule(Module &M) {
1440699ef39SMatt Arsenault bool Changed = false;
1450699ef39SMatt Arsenault
1460699ef39SMatt Arsenault for (Function &F : M) {
1470699ef39SMatt Arsenault if (!F.isDeclaration())
1480699ef39SMatt Arsenault continue;
1490699ef39SMatt Arsenault
1500699ef39SMatt Arsenault switch (F.getIntrinsicID()) {
1510699ef39SMatt Arsenault case Intrinsic::memcpy:
1520699ef39SMatt Arsenault case Intrinsic::memmove:
1530699ef39SMatt Arsenault case Intrinsic::memset:
1540699ef39SMatt Arsenault if (expandMemIntrinsicUses(F))
1550699ef39SMatt Arsenault Changed = true;
1560699ef39SMatt Arsenault break;
157c90347d7SStanislav Mekhanoshin
158c90347d7SStanislav Mekhanoshin case Intrinsic::r600_read_tidig_x:
159c90347d7SStanislav Mekhanoshin case Intrinsic::r600_read_tidig_y:
160c90347d7SStanislav Mekhanoshin case Intrinsic::r600_read_tidig_z:
161c90347d7SStanislav Mekhanoshin case Intrinsic::r600_read_local_size_x:
162c90347d7SStanislav Mekhanoshin case Intrinsic::r600_read_local_size_y:
163c90347d7SStanislav Mekhanoshin case Intrinsic::r600_read_local_size_z:
164c90347d7SStanislav Mekhanoshin Changed |= makeLIDRangeMetadata(F);
165c90347d7SStanislav Mekhanoshin break;
166c90347d7SStanislav Mekhanoshin
1670699ef39SMatt Arsenault default:
1680699ef39SMatt Arsenault break;
1690699ef39SMatt Arsenault }
1700699ef39SMatt Arsenault }
1710699ef39SMatt Arsenault
1720699ef39SMatt Arsenault return Changed;
1730699ef39SMatt Arsenault }
1740699ef39SMatt Arsenault
createAMDGPULowerIntrinsicsPass()1758b61764cSFrancis Visoiu Mistrih ModulePass *llvm::createAMDGPULowerIntrinsicsPass() {
1768b61764cSFrancis Visoiu Mistrih return new AMDGPULowerIntrinsics();
1770699ef39SMatt Arsenault }
178