Utility method for adding a Quake `ApplyOp` in the case of `cudaq.control` or `cudaq.adjoint`. This function will search recursively for all required function operations and add them to the module.
(self, target, isAdjoint, controls, *args)
| 671 | return |
| 672 | |
| 673 | def __applyControlOrAdjoint(self, target, isAdjoint, controls, *args): |
| 674 | """ |
| 675 | Utility method for adding a Quake `ApplyOp` in the case of |
| 676 | `cudaq.control` or `cudaq.adjoint`. This function will search |
| 677 | recursively for all required function operations and add them to the |
| 678 | module. |
| 679 | """ |
| 680 | self.clearCache() |
| 681 | with self.insertPoint, self.loc: |
| 682 | if isinstance(target, cc.CreateLambdaOp): |
| 683 | otherFuncCloned = target |
| 684 | otherModule = self.module |
| 685 | otherFTy = FunctionType( |
| 686 | TypeAttr(target.attributes['function_type']).value).inputs |
| 687 | else: |
| 688 | otherFuncCloned, otherModule = self.__cloneOrGetFunction( |
| 689 | target.name, self.module, target) |
| 690 | assert isinstance(otherFuncCloned, func.FuncOp) |
| 691 | # Same as __addAllCalledFunctionsRecursively does for |
| 692 | # transitively called functions: a sub-kernel merged into this |
| 693 | # module is no longer an `entrypoint`. |
| 694 | if 'cudaq-entrypoint' in otherFuncCloned.operation.attributes: |
| 695 | otherFuncCloned.operation.attributes.__delitem__( |
| 696 | 'cudaq-entrypoint') |
| 697 | self.__addAllCalledFunctionsRecursively(otherFuncCloned, |
| 698 | self.module, |
| 699 | otherModule) |
| 700 | otherFTy = [] |
| 701 | for a in otherFuncCloned.body.blocks[0].arguments: |
| 702 | otherFTy.append(a.type) |
| 703 | mlirValues = [] |
| 704 | for i, v in enumerate(args): |
| 705 | argTy = otherFTy[i] |
| 706 | if not isinstance(v, QuakeValue): |
| 707 | # here we have to map constant Python data to an MLIR Value |
| 708 | value = self.__getMLIRValueFromPythonArg(v, argTy) |
| 709 | else: |
| 710 | value = v.mlirValue |
| 711 | inTy = value.type |
| 712 | |
| 713 | if (quake.VeqType.isinstance(inTy) and |
| 714 | quake.VeqType.isinstance(argTy)): |
| 715 | if quake.VeqType.hasSpecifiedSize( |
| 716 | inTy) and not quake.VeqType.hasSpecifiedSize(argTy): |
| 717 | value = quake.RelaxSizeOp(argTy, value).result |
| 718 | |
| 719 | mlirValues.append(value) |
| 720 | if isAdjoint or len(controls) > 0: |
| 721 | quake.ApplyOp([], [], |
| 722 | controls, |
| 723 | mlirValues, |
| 724 | callee=FlatSymbolRefAttr.get( |
| 725 | otherFuncCloned.name.value), |
| 726 | is_adj=isAdjoint) |
| 727 | elif isinstance(otherFuncCloned, cc.CreateLambdaOp): |
| 728 | cc.CallCallableOp([], otherFuncCloned, mlirValues) |
| 729 | else: |
| 730 | func.CallOp(otherFuncCloned, mlirValues) |
no test coverage detected