1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #pragma once
10 
11 #include "common/LLVMWarningsPush.hpp"
12 #include <llvm/Pass.h>
13 #include <llvm/ADT/MapVector.h>
14 #include <llvm/IR/DataLayout.h>
15 #include <llvm/IR/InstVisitor.h>
16 #include "common/LLVMWarningsPop.hpp"
17 
18 namespace IGC
19 {
20 
21     /// @brief  This pass correctly sets the alignment of all loads
22     ///         and stores according to OpenCL rules.
23     ///         It perform a data-flow analysis to keep track of the highest power
24     ///         of 2 that divides a value.
25     ///         This tracking is performed for integers and for pointers, and is
26     ///         based on the assumption that global variables and kernel arguments
27     ///         are always aligned on their data type.
28     ///         The result is an underapproximation of the actual alignment, so it
29     ///         is always safe.
30     class AlignmentAnalysis : public llvm::FunctionPass, public llvm::InstVisitor<AlignmentAnalysis, unsigned int>
31     {
32     public:
33         // Pass identification, replacement for typeid
34         static char ID;
35 
36         /// @brief  Constructor
37         AlignmentAnalysis();
38 
39         /// @brief  Destructor
~AlignmentAnalysis()40         ~AlignmentAnalysis() {}
41 
42         /// @brief  Provides name of pass
getPassName() const43         virtual llvm::StringRef getPassName() const override
44         {
45             return "AlignmentAnalysisPass";
46         }
47 
getAnalysisUsage(llvm::AnalysisUsage & AU) const48         virtual void getAnalysisUsage(llvm::AnalysisUsage& AU) const override
49         {
50             AU.setPreservesCFG();
51         }
52 
53         /// @brief  Main entry point.
54         virtual bool runOnFunction(llvm::Function& F) override;
55 
56         // @ brief Instruction visitors
57         unsigned int visitInstruction(llvm::Instruction& I);
58         unsigned int visitAllocaInst(llvm::AllocaInst& I);
59         unsigned int visitIntToPtrInst(llvm::IntToPtrInst& I);
60         unsigned int visitPtrToIntInst(llvm::PtrToIntInst& I);
61         unsigned int visitSelectInst(llvm::SelectInst& I);
62         unsigned int visitGetElementPtrInst(llvm::GetElementPtrInst& I);
63         unsigned int visitPHINode(llvm::PHINode& I);
64         unsigned int visitBitCastInst(llvm::BitCastInst& I);
65         unsigned int visitAdd(llvm::BinaryOperator& I);
66         unsigned int visitMul(llvm::BinaryOperator& I);
67         unsigned int visitShl(llvm::BinaryOperator& I);
68         unsigned int visitAnd(llvm::BinaryOperator& I);
69         unsigned int visitTruncInst(llvm::TruncInst& I);
70         unsigned int visitZExtInst(llvm::ZExtInst& I);
71         unsigned int visitSExtInst(llvm::SExtInst& I);
72         unsigned int visitCallInst(llvm::CallInst& I);
73 
74         void SetInstAlignment(llvm::Instruction& I);
75         void SetInstAlignment(llvm::LoadInst& I);
76         void SetInstAlignment(llvm::StoreInst& I);
77         void SetInstAlignment(llvm::MemSetInst& I);
78         void SetInstAlignment(llvm::MemCpyInst& I);
79         void SetInstAlignment(llvm::MemMoveInst& I);
80 
81     protected:
82         /// @breif Evaluates the alignment of I based on its operands.
83         ///        For Load and Store instructions, also sets the alignment
84         ///        of the operation itself.
85         /// @param I The instruction to process
86         bool processInstruction(llvm::Instruction* I);
87 
88         /// @brief Returns the alignment for V, if it is known.
89         ///        Otherwise, returns the maximum alignment.
90         /// @param V the value the alignment of which we're interested in
91         unsigned int getAlignValue(llvm::Value* V) const;
92 
93         /// @brief Returns the alignment of a constant integer.
94         ///        This is normally 1 << ctz(C) (the highest power of 2 that divides C),
95         ///        except when C is 0, when it is the max alignment
96         unsigned int getConstantAlignment(uint64_t C) const;
97 
98         /// @brief This map stores the known alignment of every value.
99         llvm::MapVector<llvm::Value*, unsigned int> m_alignmentMap;
100 
101         static const unsigned int MinimumAlignment = 1;
102 
103         const llvm::DataLayout* m_DL;
104     };
105 
106 } // namespace IGC
107