@@ -460,7 +460,7 @@ class OpLowerer {
460
460
});
461
461
}
462
462
463
- [[nodiscard]] bool lowerCtpopToCBits (Function &F) {
463
+ [[nodiscard]] bool lowerCtpopToCountBits (Function &F) {
464
464
IRBuilder<> &IRB = OpBuilder.getIRB ();
465
465
Type *Int32Ty = IRB.getInt32Ty ();
466
466
@@ -471,13 +471,11 @@ class OpLowerer {
471
471
472
472
Type *RetTy = Int32Ty;
473
473
Type *FRT = F.getReturnType ();
474
- if (FRT->isVectorTy ()) {
475
- VectorType *VT = cast<VectorType>(FRT);
474
+ if (const auto *VT = dyn_cast<VectorType>(FRT))
476
475
RetTy = VectorType::get (RetTy, VT);
477
- }
478
476
479
477
Expected<CallInst *> OpCall = OpBuilder.tryCreateOp (
480
- dxil::OpCode::CBits , Args, CI->getName (), RetTy);
478
+ dxil::OpCode::CountBits , Args, CI->getName (), RetTy);
481
479
if (Error E = OpCall.takeError ())
482
480
return E;
483
481
@@ -491,31 +489,36 @@ class OpLowerer {
491
489
unsigned CastOp;
492
490
if (FRT->isIntOrIntVectorTy (16 ))
493
491
CastOp = Instruction::ZExt;
494
- else // must be 64 bits
492
+ else { // must be 64 bits
493
+ assert (FRT->isIntOrIntVectorTy (64 ) &&
494
+ " Currently only lowering 16, 32, or 64 bit ctpop to CountBits \
495
+ is supported." );
495
496
CastOp = Instruction::Trunc;
497
+ }
496
498
497
499
// It is correct to replace the ctpop with the dxil op and
498
- // remove an existing cast iff the cast is the only usage of
499
- // the ctpop
500
- // can use hasOneUse instead of hasOneUser, because the user
501
- // we care about should have one operand
502
- if (CI->hasOneUse ()) {
503
- User *U = CI->user_back ();
500
+ // remove all casts to i32
501
+ bool nonCastInstr = false ;
502
+ for (User *User : make_early_inc_range (CI->users ())) {
504
503
Instruction *I;
505
- if (isa<Instruction>(U) && ( I = cast <Instruction>(U)) &&
504
+ if (( I = dyn_cast <Instruction>(User)) != NULL &&
506
505
I->getOpcode () == CastOp && I->getType () == RetTy) {
507
506
I->replaceAllUsesWith (*OpCall);
508
507
I->eraseFromParent ();
509
- CI->eraseFromParent ();
510
- return Error::success ();
511
- }
508
+ } else
509
+ nonCastInstr = true ;
510
+ }
511
+
512
+ // It is correct to replace a ctpop with the dxil op and
513
+ // a cast from i32 to the return type of the ctpop
514
+ // the cast is emitted here if there is a non-cast to i32
515
+ // instr which uses the ctpop
516
+ if (nonCastInstr) {
517
+ Value *Cast =
518
+ IRB.CreateZExtOrTrunc (*OpCall, F.getReturnType (), " ctpop.cast" );
519
+ CI->replaceAllUsesWith (Cast);
512
520
}
513
521
514
- // It is always correct to replace a ctpop with the dxil op and
515
- // a cast
516
- Value *Cast =
517
- IRB.CreateZExtOrTrunc (*OpCall, F.getReturnType (), " ctpop.cast" );
518
- CI->replaceAllUsesWith (Cast);
519
522
CI->eraseFromParent ();
520
523
return Error::success ();
521
524
});
@@ -550,7 +553,7 @@ class OpLowerer {
550
553
HasErrors |= lowerTypedBufferStore (F);
551
554
break ;
552
555
case Intrinsic::ctpop:
553
- HasErrors |= lowerCtpopToCBits (F);
556
+ HasErrors |= lowerCtpopToCountBits (F);
554
557
break ;
555
558
}
556
559
Updated = true ;
0 commit comments