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