@@ -117,6 +117,14 @@ class SPIRVRegularizeLLVMBase {
117
117
void expandVEDWithSYCLTypeSRetArg (Function *F);
118
118
void expandVIDWithSYCLTypeByValComp (Function *F);
119
119
120
+ // According to the specification, the operands of a shift instruction must be
121
+ // a scalar/vector of integer. When LLVM-IR contains a shift instruction with
122
+ // i1 operands, they are treated as a bool. We need to extend them to i32 to
123
+ // comply with the specification. For example: "%shift = lshr i1 0, 1";
124
+ // The bit instruction should be changed to the extended version
125
+ // "%shift = lshr i32 0, 1" so the args are treated as int operands.
126
+ Value *extendBitInstBoolArg (Instruction *OldInst);
127
+
120
128
static std::string lowerLLVMIntrinsicName (IntrinsicInst *II);
121
129
void adaptStructTypes (StructType *ST);
122
130
static char ID;
@@ -412,6 +420,31 @@ void SPIRVRegularizeLLVMBase::expandSYCLTypeUsing(Module *M) {
412
420
expandVIDWithSYCLTypeByValComp (F);
413
421
}
414
422
423
+ Value *SPIRVRegularizeLLVMBase::extendBitInstBoolArg (Instruction *II) {
424
+ IRBuilder<> Builder (II);
425
+ auto *ArgTy = II->getOperand (0 )->getType ();
426
+ Type *NewArgType = nullptr ;
427
+ if (ArgTy->isIntegerTy ()) {
428
+ NewArgType = Builder.getInt32Ty ();
429
+ } else if (ArgTy->isVectorTy () &&
430
+ cast<VectorType>(ArgTy)->getElementType ()->isIntegerTy ()) {
431
+ unsigned NumElements = cast<FixedVectorType>(ArgTy)->getNumElements ();
432
+ NewArgType = VectorType::get (Builder.getInt32Ty (), NumElements, false );
433
+ } else {
434
+ llvm_unreachable (" Unexpected type" );
435
+ }
436
+ auto *NewBase = Builder.CreateZExt (II->getOperand (0 ), NewArgType);
437
+ auto *NewShift = Builder.CreateZExt (II->getOperand (1 ), NewArgType);
438
+ switch (II->getOpcode ()) {
439
+ case Instruction::LShr:
440
+ return Builder.CreateLShr (NewBase, NewShift);
441
+ case Instruction::Shl:
442
+ return Builder.CreateShl (NewBase, NewShift);
443
+ default :
444
+ return II;
445
+ }
446
+ }
447
+
415
448
void SPIRVRegularizeLLVMBase::adaptStructTypes (StructType *ST) {
416
449
if (!ST->hasName ())
417
450
return ;
@@ -556,6 +589,21 @@ bool SPIRVRegularizeLLVMBase::regularize() {
556
589
}
557
590
}
558
591
592
+ // Translator treats i1 as boolean, but bit instructions take
593
+ // a scalar/vector integers, so we have to extend such arguments
594
+ if (II.isLogicalShift () &&
595
+ II.getOperand (0 )->getType ()->isIntOrIntVectorTy (1 )) {
596
+ auto *NewInst = extendBitInstBoolArg (&II);
597
+ for (auto *U : II.users ()) {
598
+ if (cast<Instruction>(U)->getOpcode () == Instruction::ZExt) {
599
+ U->dropAllReferences ();
600
+ U->replaceAllUsesWith (NewInst);
601
+ ToErase.push_back (cast<Instruction>(U));
602
+ }
603
+ }
604
+ ToErase.push_back (&II);
605
+ }
606
+
559
607
// Remove optimization info not supported by SPIRV
560
608
if (auto BO = dyn_cast<BinaryOperator>(&II)) {
561
609
if (isa<PossiblyExactOperator>(BO) && BO->isExact ())
0 commit comments