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 #include "Compiler/IGCPassSupport.h"
10 #include "Compiler/InitializePasses.h"
11 #include "common/Types.hpp"
12 #include "ScalarizerCodeGen.hpp"
13 #include "llvmWrapper/IR/DerivedTypes.h"
14 
15 using namespace llvm;
16 using namespace IGC;
17 
18 #define PASS_FLAG "igc-scalarizer-in-codegen"
19 #define PASS_DESCRIPTION "Scalarizer in codegen"
20 #define PASS_CFG_ONLY false
21 #define PASS_ANALYSIS false
22 IGC_INITIALIZE_PASS_BEGIN(ScalarizerCodeGen, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
23 IGC_INITIALIZE_PASS_END(ScalarizerCodeGen, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
24 
25 char ScalarizerCodeGen::ID = 0;
26 
27 #define DEBUG_TYPE "ScalarizerCodeGen"
28 
ScalarizerCodeGen()29 ScalarizerCodeGen::ScalarizerCodeGen() : FunctionPass(ID)
30 {
31     initializeScalarizerCodeGenPass(*PassRegistry::getPassRegistry());
32 }
33 
34 
runOnFunction(Function & F)35 bool ScalarizerCodeGen::runOnFunction(Function& F)
36 {
37     llvm::IRBuilder<> builder(F.getContext());
38     m_builder = &builder;
39 
40     visit(F);
41     return false;
42 }
43 
visitBinaryOperator(llvm::BinaryOperator & I)44 void ScalarizerCodeGen::visitBinaryOperator(llvm::BinaryOperator& I)
45 {
46     // Scalarizing vector type And/Or instructions
47     if (I.getOpcode() == Instruction::And || I.getOpcode() == Instruction::Or || I.getOpcode() == Instruction::Xor)
48     {
49         if (I.getType()->isVectorTy())
50         {
51             bool isNewTypeVector = false;
52 
53             IGCLLVM::FixedVectorType* instType = cast<IGCLLVM::FixedVectorType>(I.getType());
54             unsigned numElements = int_cast<unsigned>(instType->getNumElements());
55             unsigned scalarSize = instType->getScalarSizeInBits();
56             unsigned newScalarBits = numElements * scalarSize;
57             Type* newType = nullptr;
58             //  Check if the operands can be bitcasted to types int8/16/32
59             if (newScalarBits == 8)
60                 newType = m_builder->getInt8Ty();
61             else if (newScalarBits == 16)
62                 newType = m_builder->getInt16Ty();
63             else if (newScalarBits == 32)
64                 newType = m_builder->getInt32Ty();
65             else
66             {
67                 // Check the suitable vector type to cast to, inorder to minimize the number of instructions
68                 isNewTypeVector = true;
69                 if (newScalarBits % 32 == 0)
70                     newType = IGCLLVM::FixedVectorType::get(m_builder->getInt32Ty(), newScalarBits / 32);
71                 else if (newScalarBits % 16 == 0)
72                     newType = IGCLLVM::FixedVectorType::get(m_builder->getInt16Ty(), newScalarBits / 16);
73                 else if (newScalarBits % 8 == 0)
74                     newType = IGCLLVM::FixedVectorType::get(m_builder->getInt8Ty(), newScalarBits / 8);
75                 else
76                     isNewTypeVector = false;
77             }
78 
79             if (newType)
80             {
81                 Value* src0 = I.getOperand(0);
82                 Value* src1 = I.getOperand(1);
83                 auto logicOp = I.getOpcode();
84                 m_builder->SetInsertPoint(&I);
85                 // bitcast the operands to new type
86                 Value* castedSrc0 = m_builder->CreateBitCast(src0, newType);
87                 Value* castedSrc1 = m_builder->CreateBitCast(src1, newType);
88                 Value* newBitCastInst;
89 
90                 // Generate scalar logic operations, and then bitcast the result to a vector type
91                 if (!isNewTypeVector)
92                 {
93                     Value* newLogicInst = m_builder->CreateBinOp(logicOp, castedSrc0, castedSrc1);
94                     newBitCastInst = m_builder->CreateBitCast(newLogicInst, instType);
95                 }
96                 else
97                 {
98                     IGCLLVM::FixedVectorType* newVecType = cast<IGCLLVM::FixedVectorType>(newType);
99                     unsigned newVecTypeNumEle = int_cast<unsigned>(newVecType->getNumElements());
100                     Value* ieLogicOp = UndefValue::get(newType);
101                     for (unsigned i = 0; i < newVecTypeNumEle; i++)
102                     {
103                         Value* constIndex = ConstantInt::get(m_builder->getInt32Ty(), i);
104                         Value* eeSrc0 = m_builder->CreateExtractElement(castedSrc0, constIndex);
105                         Value* eeSrc1 = m_builder->CreateExtractElement(castedSrc1, constIndex);
106                         Value* newLogicInst = m_builder->CreateBinOp(logicOp, eeSrc0, eeSrc1);
107                         ieLogicOp = m_builder->CreateInsertElement(ieLogicOp, newLogicInst, constIndex);
108                     }
109                     newBitCastInst = m_builder->CreateBitCast(ieLogicOp, instType);
110                 }
111                 // Now replace all the instruction users with the newly bitcasted Logic Instruction
112                 I.replaceAllUsesWith(newBitCastInst);
113                 I.eraseFromParent();
114             }
115         }
116     }
117 }
118