@@ -1154,26 +1154,7 @@ bool HWConformity::fixOpndType(INST_LIST_ITER it, G4_BB *bb) {
1154
1154
}
1155
1155
}
1156
1156
}
1157
- if (inst->opcode () == G4_bfn) {
1158
- // BFN requires its operands to be UD/UW
1159
- // ToDo: anyway to generalize this to all instructions requiring
1160
- // signed/unsigned int type? IGA doesn't seem to have API to query supported
1161
- // types
1162
- auto dst = inst->getDst ();
1163
- if (dst->getType () == Type_D || dst->getType () == Type_W) {
1164
- dst->setType (builder, dst->getType () == Type_D ? Type_UD : Type_UW);
1165
- }
1166
- auto changeSrcToUnsigned = [this ](G4_Operand *opnd) {
1167
- if (opnd->isSrcRegRegion () &&
1168
- (opnd->getType () == Type_D || opnd->getType () == Type_W)) {
1169
- opnd->asSrcRegRegion ()->setType (
1170
- builder, opnd->getType () == Type_D ? Type_UD : Type_UW);
1171
- }
1172
- };
1173
- changeSrcToUnsigned (inst->getSrc (0 ));
1174
- changeSrcToUnsigned (inst->getSrc (1 ));
1175
- changeSrcToUnsigned (inst->getSrc (2 ));
1176
- }
1157
+
1177
1158
return changed;
1178
1159
}
1179
1160
@@ -6483,6 +6464,12 @@ void HWConformity::chkHWConformity() {
6483
6464
#ifdef _DEBUG
6484
6465
verifyG4Kernel (kernel, Optimizer::PI_HWConformityChk, false );
6485
6466
#endif
6467
+
6468
+ fixBfnInst (bb);
6469
+ #ifdef _DEBUG
6470
+ verifyG4Kernel (kernel, Optimizer::PI_HWConformityChk, false );
6471
+ #endif
6472
+
6486
6473
// fix source operand first to avoid redundant MOVs if this fix is done
6487
6474
// after reducing execution size. used by 3d. Mainly to fix sel with two imm
6488
6475
// sources
@@ -9960,3 +9947,47 @@ void HWConformity::fixImmAddrOffsetOOB(INST_LIST_ITER it, G4_BB *bb) {
9960
9947
-immAddrOff, G4_ExecSize (execSize)));
9961
9948
}
9962
9949
}
9950
+
9951
+ void HWConformity::fixBfnInst (G4_BB* bb) {
9952
+ INST_LIST_ITER it = bb->begin ();
9953
+
9954
+ for (auto iterEnd = bb->end (); it != iterEnd; ++it) {
9955
+ G4_INST *inst = *it;
9956
+ if (inst->opcode () != G4_bfn) {
9957
+ continue ;
9958
+ }
9959
+
9960
+ // BFN requires its operands to be UD/UW
9961
+ // ToDo: anyway to generalize this to all instructions requiring
9962
+ // signed/unsigned int type? IGA doesn't seem to have API to query supported
9963
+ // types
9964
+ auto dst = inst->getDst ();
9965
+ if (dst->getType () == Type_D || dst->getType () == Type_W) {
9966
+ dst->setType (builder, dst->getType () == Type_D ? Type_UD : Type_UW);
9967
+ }
9968
+
9969
+ // When create visa immediate operand, we will lower immediate type.
9970
+ // For example:
9971
+ // bfn.xd8 (M1_NM, 1) V0042(0,0)<1> 0xffff8089:d 0xffffb4d8:d 0xffff895b:d
9972
+ // lower to:
9973
+ // (W) bfn.0xD8 (1) V0042(0,0)<1>:d 0x8089:w 0xb4d8:w 0x895b:w
9974
+ // In this case, the dst is dword type, the immediate source operand should
9975
+ // be dword as well. Since HW can only support 16b immediate value, we need
9976
+ // to insert mov instruction to resolve it.
9977
+ for (int i = 0 ; i < inst->getNumSrc (); i++)
9978
+ if (inst->getSrc (i)->isImm () && IS_DTYPE (inst->getDst ()->getType ()) &&
9979
+ inst->getSrc (i)->getType () == Type_W)
9980
+ inst->setSrc (insertMovBefore (it, i, Type_D, bb), i);
9981
+
9982
+ auto changeSrcToUnsigned = [this ](G4_Operand *opnd) {
9983
+ if (opnd->isSrcRegRegion () &&
9984
+ (opnd->getType () == Type_D || opnd->getType () == Type_W)) {
9985
+ opnd->asSrcRegRegion ()->setType (
9986
+ builder, opnd->getType () == Type_D ? Type_UD : Type_UW);
9987
+ }
9988
+ };
9989
+ changeSrcToUnsigned (inst->getSrc (0 ));
9990
+ changeSrcToUnsigned (inst->getSrc (1 ));
9991
+ changeSrcToUnsigned (inst->getSrc (2 ));
9992
+ }
9993
+ }
0 commit comments