@@ -3990,6 +3990,13 @@ void EmitPass::emitVideoAnalyticGRF(llvm::GenIntrinsicInst *inst, const DWORD re
39903990 m_encoder->Push();
39913991}
39923992
3993+ static bool isVectorTypeAllowed(Value *I) {
3994+ IGCLLVM::FixedVectorType *VecType = llvm::dyn_cast<IGCLLVM::FixedVectorType>(I->getType());
3995+ if (!VecType) return false;
3996+ auto ElType = VecType->getElementType();
3997+ return ElType->isIntegerTy(32) || ElType->isFloatTy();
3998+ }
3999+
39934000void EmitPass::EmitGenericPointersCmp(llvm::Instruction *inst, const SSource source[2], const DstModifier &modifier,
39944001 uint8_t clearTagMask) {
39954002 Cmp(cast<CmpInst>(inst)->getPredicate(), source, modifier, clearTagMask);
@@ -4026,13 +4033,13 @@ void EmitPass::BinaryUnary(llvm::Instruction *inst, const SSource source[2], con
40264033 Xor(source, modifier);
40274034 break;
40284035 case Instruction::Mul:
4029- Mul(source, modifier);
4030- break;
40314036 case Instruction::FMul:
40324037 Mul(source, modifier);
40334038 break;
40344039 case Instruction::FAdd:
4035- Add(source, modifier);
4040+ case Instruction::Add:
4041+ if (inst->getType()->isVectorTy()) Add(source, modifier);
4042+ else EmitSimpleAlu(inst, source, modifier);
40364043 break;
40374044 case Instruction::Call:
40384045 EmitAluIntrinsic(cast<CallInst>(inst), source, modifier);
@@ -4231,6 +4238,7 @@ static unsigned getVectorSize(Value *I) {
42314238 return NumElements;
42324239}
42334240
4241+
42344242void EmitPass::FPTrunc(const SSource sources[2], const DstModifier &modifier) {
42354243
42364244 CVariable *src[2];
@@ -4275,13 +4283,15 @@ void EmitPass::Sub(const SSource sources[2], const DstModifier &modifier) {
42754283 }
42764284 e_modifier mod1 = CombineModifier(EMOD_NEG, sources[1].mod);
42774285
4278- if (IGC_IS_FLAG_ENABLED(EnableVectorEmitter) && sources[0].value->getType()->isVectorTy() &&
4279- sources[1].value->getType()->isVectorTy()) {
4286+ bool IsPossible = isVectorEmissionPossible(sources, src);
4287+
4288+ if (IGC_IS_FLAG_ENABLED(EnableVectorEmitter) && IsPossible) {
42804289
42814290 IGC_ASSERT_EXIT_MESSAGE(m_encoder->GetSimdSize() == lanesToSIMDMode(16),
42824291 "As of now Vector Emission is only supported for SIMD16");
42834292
42844293 unsigned VectorSize = getVectorSize(sources[0].value);
4294+ IGC_ASSERT_MESSAGE(VectorSize == getVectorSize(sources[1].value), "operands must have same vector types");
42854295
42864296 bool AllUniform = src[0]->IsUniform() && src[1]->IsUniform() && m_destination->IsUniform();
42874297
@@ -4329,23 +4339,50 @@ void EmitPass::Sub(const SSource sources[2], const DstModifier &modifier) {
43294339 m_encoder->Push();
43304340}
43314341
4342+ bool EmitPass::isVectorEmissionPossible(const SSource sources[2], CVariable *src[2]) {
4343+
4344+ // any non ordinary state of source modifiers
4345+ // can be a sign of emission of a specific pattern,
4346+ // emission can interfere with
4347+ if (sources[0].elementOffset != 0) return false;
4348+ if (sources[1].elementOffset != 0) return false;
4349+ if (sources[0].SIMDOffset != 0) return false;
4350+ if (sources[1].SIMDOffset != 0) return false;
4351+
4352+ bool AllowedVectorTypes = isVectorTypeAllowed(sources[0].value) && isVectorTypeAllowed(sources[1].value);
4353+ if (!AllowedVectorTypes) return false;
4354+
4355+ bool DestSizeEquals = false;
4356+ // it's possible have a case where two uniform vectors are
4357+ // deliberately not processed uniformly,
4358+ // in this case we will have virtual dest register with not
4359+ // the same size as operands, so we should default to
4360+ // scalar emission
4361+ DestSizeEquals = m_destination->GetNumberElement() == src[0]->GetNumberElement();
4362+ DestSizeEquals |= m_destination->GetNumberElement() == src[1]->GetNumberElement();
4363+ return DestSizeEquals;
4364+ }
4365+
43324366void EmitPass::Add(const SSource sources[2], const DstModifier &modifier) {
43334367 CVariable *src[2];
43344368 for (int i = 0; i < 2; ++i) {
43354369 src[i] = GetSrcVariable(sources[i]);
43364370 }
43374371
4338- if (IGC_IS_FLAG_ENABLED(EnableVectorEmitter) && sources[0].value->getType()->isVectorTy() &&
4339- sources[1].value->getType()->isVectorTy()) {
4372+ bool IsPossible = isVectorEmissionPossible(sources, src);
4373+
4374+ if (IGC_IS_FLAG_ENABLED(EnableVectorEmitter) && IsPossible) {
43404375
43414376 IGC_ASSERT_EXIT_MESSAGE(numLanes(m_encoder->GetSimdSize()) == 16,
43424377 "As of now Vector Emission is only supported for SIMD16");
4343- unsigned VectorSize = getVectorSize(sources[0].value);
43444378
43454379 bool AllUniform = src[0]->IsUniform() && src[1]->IsUniform() && m_destination->IsUniform();
43464380 // cannot emit 16 SIMD if SIMD SIZE is set to 8, but can emit 4
43474381 // simple ALU instructions has the same possible width as SIMD, "math"
43484382 // pipeline instructions has reduced width
4383+ unsigned VectorSize = getVectorSize(sources[0].value);
4384+ IGC_ASSERT_MESSAGE(VectorSize == getVectorSize(sources[1].value), "operands must have same vector types");
4385+
43494386 bool CanEmitThisSize = VectorSize <= numLanes(m_currShader->m_SIMDSize);
43504387
43514388 if (IGC_IS_FLAG_ENABLED(VectorizerUniformValueVectorizationEnabled) && AllUniform && CanEmitThisSize) {
@@ -4391,13 +4428,14 @@ void EmitPass::Mul(const SSource sources[2], const DstModifier &modifier) {
43914428 }
43924429
43934430 unsigned SIMDSize = numLanes(m_currShader->m_SIMDSize);
4431+ bool IsPossible = isVectorEmissionPossible(sources, src);
43944432
4395- if (IGC_IS_FLAG_ENABLED(EnableVectorEmitter) && sources[0].value->getType()->isVectorTy() &&
4396- sources[1].value->getType()->isVectorTy()) {
4433+ if (IGC_IS_FLAG_ENABLED(EnableVectorEmitter) && IsPossible) {
43974434
43984435 IGC_ASSERT_EXIT_MESSAGE(numLanes(m_encoder->GetSimdSize()) == 16,
43994436 "As of now Vector Emission is only supported for SIMD16");
44004437 unsigned VectorSize = getVectorSize(sources[0].value);
4438+ IGC_ASSERT_MESSAGE(VectorSize == getVectorSize(sources[1].value), "operands must have same vector types");
44014439
44024440 bool AllUniform = src[0]->IsUniform() && src[1]->IsUniform() && m_destination->IsUniform();
44034441 // cannot emit 16 SIMD if SIMD SIZE is set to 8, but can emit 4
@@ -4685,8 +4723,12 @@ void EmitPass::VectorMad(const SSource sources[3], const DstModifier &modifier)
46854723}
46864724
46874725void EmitPass::FDiv(const SSource sources[2], const DstModifier &modifier) {
4688- if (IGC_IS_FLAG_ENABLED(EnableVectorEmitter) && sources[0].value->getType()->isVectorTy() &&
4689- sources[1].value->getType()->isVectorTy()) {
4726+
4727+ CVariable *src[2];
4728+ for (int i = 0; i < 2; ++i) src[i] = GetSrcVariable(sources[i]);
4729+ bool IsPossible = isVectorEmissionPossible(sources, src);
4730+
4731+ if (IGC_IS_FLAG_ENABLED(EnableVectorEmitter) && IsPossible) {
46904732
46914733 IGC_ASSERT_EXIT_MESSAGE(numLanes(m_encoder->GetSimdSize()) == 16,
46924734 "As of now Vector Emission is only supported for SIMD16");
0 commit comments