1//===- NVPTXUtilities.cpp - Utility Functions -----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains miscellaneous utility functions
10//
11//===----------------------------------------------------------------------===//
12
13#include "NVPTXUtilities.h"
14#include "NVPTX.h"
15#include "NVPTXTargetMachine.h"
16#include "NVVMProperties.h"
17#include "llvm/IR/Attributes.h"
18#include "llvm/IR/DataLayout.h"
19#include "llvm/IR/Function.h"
20#include "llvm/Support/Alignment.h"
21#include "llvm/Support/CommandLine.h"
22#include <algorithm>
23
24namespace llvm {
25
26static cl::opt<bool> ForceMinByValParamAlign(
27 "nvptx-force-min-byval-param-align", cl::Hidden,
28 cl::desc("NVPTX Specific: force 4-byte minimal alignment for byval"
29 " params of device functions."),
30 cl::init(Val: false));
31
32Function *getMaybeBitcastedCallee(const CallBase *CB) {
33 return dyn_cast<Function>(Val: CB->getCalledOperand()->stripPointerCasts());
34}
35
36Align getPTXPromotedParamTypeAlign(const Function *F, Type *ArgTy,
37 const DataLayout &DL) {
38 // Capping the alignment to 128 bytes as that is the maximum alignment
39 // supported by PTX.
40 const Align ABITypeAlign = std::min(a: Align(128), b: DL.getABITypeAlign(Ty: ArgTy));
41
42 // If a function has linkage different from internal or private, we
43 // must use default ABI alignment as external users rely on it. Same
44 // for a function that may be called from a function pointer.
45 const bool MayOptimizeAlign =
46 F && F->hasLocalLinkage() &&
47 !F->hasAddressTaken(/*Users=*/nullptr,
48 /*IgnoreCallbackUses=*/false,
49 /*IgnoreAssumeLikeCalls=*/true,
50 /*IgnoreLLVMUsed=*/IngoreLLVMUsed: true);
51 assert(!(MayOptimizeAlign && isKernelFunction(*F)) &&
52 "Expect kernels to have non-local linkage");
53 const Align OptimizedAlign = MayOptimizeAlign ? Align(16) : Align(1);
54 return std::max(a: OptimizedAlign, b: ABITypeAlign);
55}
56
57Align getDeviceByValParamAlign(const Function *F, Type *ArgTy,
58 Align InitialAlign, const DataLayout &DL) {
59 const Align OptimizedAlign = getPTXPromotedParamTypeAlign(F, ArgTy, DL);
60
61 // Old ptx versions have a bug. When PTX code takes address of
62 // byval parameter with alignment < 4, ptxas generates code to
63 // spill argument into memory. Alas on sm_50+ ptxas generates
64 // SASS code that fails with misaligned access. To work around
65 // the problem, make sure that we align byval parameters by at
66 // least 4. This bug seems to be fixed at least starting from
67 // ptxas > 9.0.
68 // TODO: remove this after verifying the bug is not reproduced
69 // on non-deprecated ptxas versions.
70 const bool ShouldForceMinAlign =
71 ForceMinByValParamAlign && (!F || !isKernelFunction(F: *F));
72 const Align AlignFloor = ShouldForceMinAlign ? Align(4) : Align(1);
73
74 return std::max(l: {InitialAlign, OptimizedAlign, AlignFloor});
75}
76
77Align getPTXParamAlign(const Function *F, Type *Ty, unsigned AttrIdx,
78 const DataLayout &DL) {
79 if (F)
80 if (MaybeAlign StackAlign = getStackAlign(F: *F, Index: AttrIdx))
81 return StackAlign.value();
82
83 Align TypeAlign = getPTXPromotedParamTypeAlign(F, ArgTy: Ty, DL);
84 if (F && AttrIdx >= AttributeList::FirstArgIndex) {
85 unsigned ArgNo = AttrIdx - AttributeList::FirstArgIndex;
86 if (F->getAttributes().hasParamAttr(ArgNo, Kind: Attribute::ByVal))
87 return std::max(a: TypeAlign, b: F->getParamAlign(ArgNo).valueOrOne());
88 }
89 return TypeAlign;
90}
91
92Align getPTXParamAlign(const CallBase *CB, Type *Ty, unsigned Idx,
93 const DataLayout &DL) {
94 const Function *DirectCallee = CB ? CB->getCalledFunction() : nullptr;
95
96 if (!DirectCallee && CB) {
97 if (MaybeAlign StackAlign = getStackAlign(*CB, Idx))
98 return StackAlign.value();
99
100 DirectCallee = getMaybeBitcastedCallee(CB);
101 }
102
103 return getPTXParamAlign(F: DirectCallee, Ty, AttrIdx: Idx, DL);
104}
105
106bool shouldEmitPTXNoReturn(const Value *V, const TargetMachine &TM) {
107 const auto &ST =
108 *static_cast<const NVPTXTargetMachine &>(TM).getSubtargetImpl();
109 if (!ST.hasNoReturn())
110 return false;
111
112 assert((isa<Function>(V) || isa<CallInst>(V)) &&
113 "Expect either a call instruction or a function");
114
115 if (const CallInst *CallI = dyn_cast<CallInst>(Val: V))
116 return CallI->doesNotReturn() &&
117 CallI->getFunctionType()->getReturnType()->isVoidTy();
118
119 const Function *F = cast<Function>(Val: V);
120 return F->doesNotReturn() &&
121 F->getFunctionType()->getReturnType()->isVoidTy() &&
122 !isKernelFunction(F: *F);
123}
124
125} // namespace llvm
126