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