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
24using namespace 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 *llvm::getMaybeBitcastedCallee(const CallBase *CB) {
33 return dyn_cast<Function>(Val: CB->getCalledOperand()->stripPointerCasts());
34}
35
36Align llvm::getPTXParamTypeAlign(Type *ArgTy, const DataLayout &DL) {
37 // Capping the alignment to 128 bytes as that is the maximum alignment
38 // supported by PTX.
39 return std::min(a: Align(128), b: DL.getABITypeAlign(Ty: ArgTy));
40}
41
42static Align getByValParamAlignFloor(const Function *F) {
43 // Old ptx versions have a bug. When PTX code takes address of
44 // byval parameter with alignment < 4, ptxas generates code to
45 // spill argument into memory. Alas on sm_50+ ptxas generates
46 // SASS code that fails with misaligned access. To work around
47 // the problem, make sure that we align byval parameters by at
48 // least 4. This bug seems to be fixed at least starting from
49 // ptxas > 9.0.
50 // TODO: remove this after verifying the bug is not reproduced
51 // on non-deprecated ptxas versions.
52 const bool ShouldForceMinAlign =
53 ForceMinByValParamAlign && (!F || !isKernelFunction(F: *F));
54 return ShouldForceMinAlign ? Align(4) : Align(1);
55}
56
57Align llvm::getDeviceByValParamAlign(const Function *F, Type *ArgTy,
58 unsigned AttrIdx, const DataLayout &DL) {
59 return std::max(a: getPTXParamAlign(F, Ty: ArgTy, AttrIdx, DL),
60 b: getByValParamAlignFloor(F));
61}
62
63Align llvm::getDeviceByValParamAlign(const CallBase *CB, Type *ArgTy,
64 unsigned AttrIdx, const DataLayout &DL) {
65 Align ParamAlign = getPTXParamAlign(CB, Ty: ArgTy, AttrIdx, DL);
66
67 // For an indirect call getPTXParamAlign can't see the call's own byval
68 // alignment, so fold it in.
69 if (CB && AttrIdx >= AttributeList::FirstArgIndex)
70 ParamAlign = std::max(
71 a: ParamAlign,
72 b: CB->getParamAlign(ArgNo: AttrIdx - AttributeList::FirstArgIndex).valueOrOne());
73
74 return std::max(a: ParamAlign, b: getByValParamAlignFloor(
75 F: CB ? CB->getCalledFunction() : nullptr));
76}
77
78Align llvm::getPTXParamAlign(const Function *F, Type *Ty, unsigned AttrIdx,
79 const DataLayout &DL) {
80 if (F)
81 if (MaybeAlign StackAlign = getStackAlign(F: *F, Index: AttrIdx))
82 return StackAlign.value();
83
84 Align TypeAlign = getPTXParamTypeAlign(ArgTy: Ty, DL);
85 if (F && AttrIdx >= AttributeList::FirstArgIndex) {
86 unsigned ArgNo = AttrIdx - AttributeList::FirstArgIndex;
87 if (F->getAttributes().hasParamAttr(ArgNo, Kind: Attribute::ByVal))
88 return std::max(a: TypeAlign, b: F->getParamAlign(ArgNo).valueOrOne());
89 }
90 return TypeAlign;
91}
92
93Align llvm::getPTXParamAlign(const CallBase *CB, Type *Ty, unsigned Idx,
94 const DataLayout &DL) {
95 if (CB)
96 if (MaybeAlign StackAlign = getStackAlign(*CB, Idx))
97 return StackAlign.value();
98
99 // Otherwise resolve the direct callee and use its parameter alignment.
100 const Function *DirectCallee = CB ? CB->getCalledFunction() : nullptr;
101 if (!DirectCallee && CB)
102 DirectCallee = getMaybeBitcastedCallee(CB);
103
104 return getPTXParamAlign(F: DirectCallee, Ty, AttrIdx: Idx, DL);
105}
106
107bool llvm::shouldEmitPTXNoReturn(const Value *V, const TargetMachine &TM) {
108 const auto &ST =
109 *static_cast<const NVPTXTargetMachine &>(TM).getSubtargetImpl();
110 if (!ST.hasNoReturn())
111 return false;
112
113 assert((isa<Function>(V) || isa<CallInst>(V)) &&
114 "Expect either a call instruction or a function");
115
116 if (const CallInst *CallI = dyn_cast<CallInst>(Val: V))
117 return CallI->doesNotReturn() &&
118 CallI->getFunctionType()->getReturnType()->isVoidTy();
119
120 const Function *F = cast<Function>(Val: V);
121 return F->doesNotReturn() &&
122 F->getFunctionType()->getReturnType()->isVoidTy() &&
123 !isKernelFunction(F: *F);
124}
125