@@ -175,8 +175,10 @@ class GenXEmulate : public ModulePass {
175175 // handles genx_{XX}add_sat cases
176176 Value *visitGenxAddSat (CallInst &CI);
177177
178+ // handles genx_constanti
179+ Value *visitConstantI (CallInst &CI);
180+
178181 // [+] bitcast
179- // [-] genx.constanti ?
180182 // [-] genx.scatter ?
181183 // [-] genx.gather ?
182184 Value *visitCallInst (CallInst &CI);
@@ -191,6 +193,7 @@ class GenXEmulate : public ModulePass {
191193 static bool isI64ToFP (const Instruction &I);
192194 static bool isI64Cmp (const Instruction &I);
193195 static bool isI64AddSat (const Instruction &I);
196+ static bool isI64Constant (const Instruction &I);
194197 static Value *detectBitwiseNot (BinaryOperator &);
195198 static Type *changeScalarType (Type *T, Type *NewTy);
196199
@@ -216,7 +219,7 @@ class GenXEmulate : public ModulePass {
216219 bool needsEmulation () const {
217220 return (SplitBuilder.IsI64Operation () || isI64Cmp (Inst) ||
218221 isConvertOfI64 (Inst) || isI64PointerOp (Inst) ||
219- isI64AddSat (Inst));
222+ isI64AddSat (Inst) || isI64Constant (Inst) );
220223 }
221224
222225 IRBuilder getIRBuilder () {
@@ -454,6 +457,13 @@ bool GenXEmulate::Emu64Expander::isI64AddSat(const Instruction &I) {
454457 }
455458 return false ;
456459}
460+ bool GenXEmulate::Emu64Expander::isI64Constant (const Instruction &I) {
461+ auto IID = vc::getAnyIntrinsicID (&I);
462+ if (IID != GenXIntrinsic::genx_constanti)
463+ return false ;
464+ Type *RetTy = I.getType ();
465+ return RetTy->isIntOrIntVectorTy (64 );
466+ }
457467
458468Value *GenXEmulate::Emu64Expander::detectBitwiseNot (BinaryOperator &Op) {
459469 if (Instruction::Xor != Op.getOpcode ())
@@ -564,8 +574,24 @@ Value *GenXEmulate::Emu64Expander::visitAdd(BinaryOperator &Op) {
564574 auto AddcRes = buildAddc (Inst.getModule (), Builder, *Src0.Lo , *Src1.Lo ,
565575 " int_emu.add64.lo." );
566576 auto *AddLo = AddcRes.Val ;
567- auto *AddHi =
568- buildTernaryAddition (Builder, *AddcRes.CB , *Src0.Hi , *Src1.Hi , " add_hi" );
577+ Value *AddHi = nullptr ;
578+
579+ auto *Src0HiConst = dyn_cast<Constant>(Src0.Hi );
580+ auto *Src1HiConst = dyn_cast<Constant>(Src1.Hi );
581+ if (Src0HiConst && Src1HiConst && Src0HiConst->isZeroValue () &&
582+ Src1HiConst->isZeroValue ()) {
583+ // Optimization for the case when both high parts are zero
584+ AddHi = AddcRes.CB ;
585+ } else if (Src0HiConst && Src0HiConst->isZeroValue ()) {
586+ // Optimization for the case when src0 high part is zero
587+ AddHi = Builder.CreateAdd (AddcRes.CB , Src1.Hi , " add_hi" );
588+ } else if (Src1HiConst && Src1HiConst->isZeroValue ()) {
589+ // Optimization for the case when src1 high part is zero
590+ AddHi = Builder.CreateAdd (AddcRes.CB , Src0.Hi , " add_hi" );
591+ } else {
592+ AddHi = buildTernaryAddition (Builder, *AddcRes.CB , *Src0.Hi , *Src1.Hi ,
593+ " add_hi" );
594+ }
569595 return SplitBuilder.combineLoHiSplit (
570596 {AddLo, AddHi}, Twine (" int_emu." ) + Op.getOpcodeName () + " ." ,
571597 Inst.getType ()->isIntegerTy ());
@@ -589,9 +615,26 @@ Value *GenXEmulate::Emu64Expander::visitSub(BinaryOperator &Op) {
589615 auto *Borrow =
590616 Builder.CreateExtractValue (SubbVal, {IdxSubb_Borrow}, " subb.borrow" );
591617 auto *MinusBorrow = Builder.CreateNeg (Borrow, " borrow.negate" );
592- auto *MinusS1Hi = Builder.CreateNeg (Src1.Hi , " negative.src1_hi" );
593- auto *SubHi = buildTernaryAddition (Builder, *Src0.Hi , *MinusBorrow,
594- *MinusS1Hi, " sub_hi" );
618+
619+ Value *SubHi = nullptr ;
620+
621+ auto *Src0HiConst = dyn_cast<Constant>(Src0.Hi );
622+ auto *Src1HiConst = dyn_cast<Constant>(Src1.Hi );
623+ if (Src0HiConst && Src1HiConst && Src0HiConst->isZeroValue () &&
624+ Src1HiConst->isZeroValue ()) {
625+ // Optimization for the case when both high parts are zero
626+ SubHi = MinusBorrow;
627+ } else if (Src0HiConst && Src0HiConst->isZeroValue ()) {
628+ // Optimization for the case when src0 high part is zero
629+ SubHi = Builder.CreateSub (MinusBorrow, Src1.Hi , " sub_hi" );
630+ } else if (Src1HiConst && Src1HiConst->isZeroValue ()) {
631+ // Optimization for the case when src1 high part is zero
632+ SubHi = Builder.CreateAdd (Src0.Hi , MinusBorrow, " sub_hi" );
633+ } else {
634+ auto *MinusS1Hi = Builder.CreateNeg (Src1.Hi , " negative.src1_hi" );
635+ SubHi = buildTernaryAddition (Builder, *Src0.Hi , *MinusBorrow, *MinusS1Hi,
636+ " sub_hi" );
637+ }
595638 return SplitBuilder.combineLoHiSplit (
596639 {SubLo, SubHi}, Twine (" int_emu." ) + Op.getOpcodeName () + " ." ,
597640 Inst.getType ()->isIntegerTy ());
@@ -1206,6 +1249,57 @@ Value *GenXEmulate::Emu64Expander::visitGenxAddSat(CallInst &CI) {
12061249 return Result;
12071250}
12081251
1252+ Value *GenXEmulate::Emu64Expander::visitConstantI (CallInst &CI) {
1253+ auto Builder = getIRBuilder ();
1254+ auto *M = CI.getModule ();
1255+ auto &Ctx = M->getContext ();
1256+
1257+ auto *Src = CI.getOperand (0 );
1258+ auto *SrcTy = cast<IGCLLVM::FixedVectorType>(Src->getType ());
1259+ auto NumElements = SrcTy->getNumElements ();
1260+
1261+ SmallVector<uint32_t , 8 > Values;
1262+ bool CanBeZext = false ;
1263+
1264+ if (auto *SrcC = dyn_cast<ConstantDataVector>(Src)) {
1265+ CanBeZext = true ;
1266+ for (unsigned I = 0 ; CanBeZext && I < NumElements; I++) {
1267+ auto Val = SrcC->getElementAsInteger (I);
1268+ CanBeZext &= Val <= std::numeric_limits<uint32_t >::max ();
1269+ Values.emplace_back (static_cast <uint32_t >(Val));
1270+ }
1271+ }
1272+
1273+ Value *Result = nullptr ;
1274+ if (CanBeZext) {
1275+ // Can be represented as zext from 32-bit values, so create 32-bit constants
1276+ // and zext it to 64-bit.
1277+ auto *NewSrc = ConstantDataVector::get (Ctx, Values);
1278+ auto *NewTy = NewSrc->getType ();
1279+ IGC_ASSERT_EXIT (NewTy->getScalarSizeInBits () == 32 );
1280+
1281+ auto *NewIntr =
1282+ vc::getAnyDeclaration (M, GenXIntrinsic::genx_constanti, {NewTy});
1283+ auto *NewConst = Builder.CreateCall (NewIntr, {NewSrc});
1284+ Result = Builder.CreateZExt (NewConst, CI.getType ());
1285+ } else {
1286+ // Cannot be represented as zext from 32-bit values, so bitcast the
1287+ // <N x i64> constant to <2N x i32>.
1288+ auto *NewTy =
1289+ IGCLLVM::FixedVectorType::get (Builder.getInt32Ty (), NumElements * 2 );
1290+
1291+ auto *Cast = Builder.CreateBitCast (Src, NewTy);
1292+ IGC_ASSERT_EXIT (isa<Constant>(Cast));
1293+
1294+ auto *NewIntr =
1295+ vc::getAnyDeclaration (M, GenXIntrinsic::genx_constanti, {NewTy});
1296+ auto *NewConst = Builder.CreateCall (NewIntr, {Cast});
1297+ Result = Builder.CreateBitCast (NewConst, CI.getType ());
1298+ }
1299+
1300+ return Result;
1301+ }
1302+
12091303Value *GenXEmulate::Emu64Expander::visitCallInst (CallInst &CI) {
12101304 switch (vc::getAnyIntrinsicID (&Inst)) {
12111305 case Intrinsic::smax:
@@ -1225,6 +1319,8 @@ Value *GenXEmulate::Emu64Expander::visitCallInst(CallInst &CI) {
12251319 case GenXIntrinsic::genx_uuadd_sat:
12261320 case GenXIntrinsic::genx_ssadd_sat:
12271321 return visitGenxAddSat (CI);
1322+ case GenXIntrinsic::genx_constanti:
1323+ return visitConstantI (CI);
12281324 }
12291325 return nullptr ;
12301326}
0 commit comments