1 | //===-- SIDefines.h - SI Helper Functions -----------------------*- 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 | /// \file - utility functions for the SIDefines and its common uses. |
8 | // |
9 | //===----------------------------------------------------------------------===// |
10 | |
11 | #ifndef LLVM_LIB_TARGET_AMDGPU_UTILS_SIDEFINESUTILS_H |
12 | #define LLVM_LIB_TARGET_AMDGPU_UTILS_SIDEFINESUTILS_H |
13 | |
14 | #include "llvm/MC/MCExpr.h" |
15 | #include <utility> |
16 | |
17 | namespace llvm { |
18 | class MCContext; |
19 | namespace AMDGPU { |
20 | |
21 | /// Deduce the least significant bit aligned shift and mask values for a binary |
22 | /// Complement \p Value (as they're defined in SIDefines.h as C_*) as a returned |
23 | /// pair<shift, mask>. That is to say \p Value == ~(mask << shift) |
24 | /// |
25 | /// For example, given C_00B848_FWD_PROGRESS (i.e., 0x7FFFFFFF) from |
26 | /// SIDefines.h, this will return the pair as (31,1). |
27 | constexpr std::pair<unsigned, unsigned> getShiftMask(unsigned Value) { |
28 | unsigned Shift = 0; |
29 | unsigned Mask = 0; |
30 | |
31 | Mask = ~Value; |
32 | for (; !(Mask & 1); Shift++, Mask >>= 1) { |
33 | } |
34 | |
35 | return std::make_pair(x&: Shift, y&: Mask); |
36 | } |
37 | |
38 | /// Provided with the MCExpr * \p Val, uint32 \p Mask and \p Shift, will return |
39 | /// the masked and left shifted, in said order of operations, MCExpr * created |
40 | /// within the MCContext \p Ctx. |
41 | /// |
42 | /// For example, given MCExpr *Val, Mask == 0xf, Shift == 6 the returned MCExpr |
43 | /// * will be the equivalent of (Val & 0xf) << 6 |
44 | inline const MCExpr *maskShiftSet(const MCExpr *Val, uint32_t Mask, |
45 | uint32_t Shift, MCContext &Ctx) { |
46 | if (Mask) { |
47 | const MCExpr *MaskExpr = MCConstantExpr::create(Value: Mask, Ctx); |
48 | Val = MCBinaryExpr::createAnd(LHS: Val, RHS: MaskExpr, Ctx); |
49 | } |
50 | if (Shift) { |
51 | const MCExpr *ShiftExpr = MCConstantExpr::create(Value: Shift, Ctx); |
52 | Val = MCBinaryExpr::createShl(LHS: Val, RHS: ShiftExpr, Ctx); |
53 | } |
54 | return Val; |
55 | } |
56 | |
57 | /// Provided with the MCExpr * \p Val, uint32 \p Mask and \p Shift, will return |
58 | /// the right shifted and masked, in said order of operations, MCExpr * created |
59 | /// within the MCContext \p Ctx. |
60 | /// |
61 | /// For example, given MCExpr *Val, Mask == 0xf, Shift == 6 the returned MCExpr |
62 | /// * will be the equivalent of (Val >> 6) & 0xf |
63 | inline const MCExpr *maskShiftGet(const MCExpr *Val, uint32_t Mask, |
64 | uint32_t Shift, MCContext &Ctx) { |
65 | if (Shift) { |
66 | const MCExpr *ShiftExpr = MCConstantExpr::create(Value: Shift, Ctx); |
67 | Val = MCBinaryExpr::createLShr(LHS: Val, RHS: ShiftExpr, Ctx); |
68 | } |
69 | if (Mask) { |
70 | const MCExpr *MaskExpr = MCConstantExpr::create(Value: Mask, Ctx); |
71 | Val = MCBinaryExpr::createAnd(LHS: Val, RHS: MaskExpr, Ctx); |
72 | } |
73 | return Val; |
74 | } |
75 | |
76 | } // end namespace AMDGPU |
77 | } // end namespace llvm |
78 | |
79 | #endif // LLVM_LIB_TARGET_AMDGPU_UTILS_SIDEFINESUTILS_H |
80 | |