1//===- llvm/BundleAttributes.cpp - LLVM Bundle Attributes -------*- C++ -*-===//
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#include "llvm/IR/BundleAttributes.h"
10
11#include "llvm/ADT/StringSwitch.h"
12#include "llvm/IR/Constants.h"
13
14using namespace llvm;
15
16StringRef llvm::getNameFromBundleAttr(BundleAttr BA) {
17 switch (BA) {
18#define ATTR(Name, Str) \
19 case BundleAttr::Name: \
20 return #Str;
21#include "llvm/IR/BundleAttributes.def"
22 case BundleAttr::None:
23 return "none";
24 }
25 llvm_unreachable("unknonwn bundle attribute");
26}
27
28BundleAttr llvm::getBundleAttrFromID(uint32_t ID) {
29 switch (ID) {
30#define ATTR(Name, Str) \
31 case LLVMContext::OB_##Name: \
32 return BundleAttr::Name;
33#include "llvm/IR/BundleAttributes.def"
34 default:
35 return BundleAttr::None;
36 }
37}
38
39AssumeAlignInfo llvm::getAssumeAlignInfo(OperandBundleUse OBU) {
40 assert(OBU.getTagID() == LLVMContext::OB_Align && OBU.Inputs.size() >= 2 &&
41 OBU.Inputs.size() <= 3);
42 AssumeAlignInfo Ret{.Ptr: OBU.Inputs[0], .Alignment: OBU.Inputs[1], .Offset: nullptr, .AlignmentVal: std::nullopt,
43 .OffsetVal: std::nullopt};
44 if (auto *Align = dyn_cast<ConstantInt>(Val: OBU.Inputs[1]))
45 Ret.AlignmentVal = Align->getZExtValue();
46 if (OBU.Inputs.size() == 3) {
47 Ret.Offset = &OBU.Inputs[2];
48 if (auto *Offset = dyn_cast<ConstantInt>(Val: OBU.Inputs[2]))
49 Ret.OffsetVal = Offset->getZExtValue();
50 } else {
51 Ret.OffsetVal = 0;
52 }
53 return Ret;
54}
55
56AssumeNoUndefInfo llvm::getAssumeNoUndefInfo(OperandBundleUse OBU) {
57 assert(OBU.getTagID() == LLVMContext::OB_NoUndef && OBU.Inputs.size() == 1);
58 return {.Val: OBU.Inputs[0]};
59}
60
61AssumeSeparateStorageInfo
62llvm::getAssumeSeparateStorageInfo(OperandBundleUse OBU) {
63 assert(OBU.getTagID() == LLVMContext::OB_SeparateStorage &&
64 OBU.Inputs.size() == 2);
65 return {.Ptr1: OBU.Inputs[0], .Ptr2: OBU.Inputs[1]};
66}
67
68AssumeNonNullInfo llvm::getAssumeNonNullInfo(OperandBundleUse OBU) {
69 assert(OBU.getTagID() == LLVMContext::OB_NonNull && OBU.Inputs.size() == 1);
70 return {.Ptr: OBU.Inputs[0]};
71}
72
73AssumeDereferenceableInfo
74llvm::getAssumeDereferenceableInfo(OperandBundleUse OBU) {
75 assert(OBU.getTagID() == LLVMContext::OB_Dereferenceable &&
76 OBU.Inputs.size() == 2);
77 AssumeDereferenceableInfo Ret{.Ptr: OBU.Inputs[0], .Count: OBU.Inputs[1], .CountVal: std::nullopt};
78
79 if (auto *Size = dyn_cast<ConstantInt>(Val: OBU.Inputs[1]))
80 Ret.CountVal = Size->getZExtValue();
81 return Ret;
82}
83
84bool llvm::assumeBundleImpliesNonNull(const Value *Val, const Function *Context,
85 OperandBundleUse OBU) {
86 switch (getBundleAttrFromOBU(OBU)) {
87 case BundleAttr::Align: {
88 auto [Ptr, _, _2, Alignment, Offset] = getAssumeAlignInfo(OBU);
89 return Ptr == Val && Alignment && Offset && isPowerOf2_64(Value: *Alignment) &&
90 *Offset % *Alignment != 0;
91 }
92
93 case BundleAttr::Dereferenceable: {
94 auto [Ptr, _, Count] = getAssumeDereferenceableInfo(OBU);
95 return Ptr == Val && Count && *Count != 0 &&
96 !NullPointerIsDefined(F: Context,
97 AS: Val->getType()->getPointerAddressSpace());
98 }
99
100 case BundleAttr::NonNull:
101 return getAssumeNonNullInfo(OBU).Ptr == Val;
102
103 default:
104 return false;
105 }
106}
107