Repository: Qiskit/qiskit

Issue:
Inefficient representation when doing custom controlled gates verses native implimentations
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**: master
- **Python version**:
- **Operating system**:

### What is the current behavior?
Consider a CCZ gate made by controlling a Z gate:

```python

qc = QuantumCircuit(2)
qc.z(1)
ctr_gate = qc.to_gate().control(2)
```

This has a decomposition of 

```python
circ1 = QuantumCircuit(4)
circ1.append(ctr_gate, range(4))
circ1.decompose().draw('mpl')
```
<img width="864" alt="Screen Shot 2020-10-28 at 21 01 40" src="https://user-images.githubusercontent.com/1249193/97512790-c8b82c00-1960-11eb-9aae-80c902bb773d.png">

that uses P, U, and CX gates, where as writing the same expression written in terms of predefined gates yields:

```python

circ2 = QuantumCircuit(4)
circ2.h(3)
circ2.ccx(0,1,3)
circ2.h(3)
circ2.decompose().draw('mpl')
```
<img width="645" alt="Screen Shot 2020-10-28 at 21 03 14" src="https://user-images.githubusercontent.com/1249193/97512868-0026d880-1961-11eb-81ed-ab0ab5a7005a.png">

that is decomposed into an combination of U2(0,pi) (which is an H), H, T, and CX.  Importantly, there are only 6 CX gates in this latter decomposition and 8 in the former.  These gates cannot be transpiled away at any optimization level.  So in this very simple case there are 33% more CX gates when implementing the exact same thing using custom controlled gates, and a 40% increase in the final transpiled depth (14 vs 10).



### Steps to reproduce the problem



### What is the expected behavior?



### Suggested solutions





Discussion:
I believe this could be fixed by adding `'z'` to the `basis` list https://github.com/Qiskit/qiskit-terra/blob/2d11db2/qiskit/circuit/add_control.py#L114 and a corresponding rule below for the case where `gate.name == 'z'`.

Resolving patch:
diff --git a/qiskit/circuit/add_control.py b/qiskit/circuit/add_control.py
--- a/qiskit/circuit/add_control.py
+++ b/qiskit/circuit/add_control.py
@@ -111,7 +111,7 @@ def control(operation: Union[Gate, ControlledGate],
         if operation.definition is not None and operation.definition.global_phase:
             global_phase += operation.definition.global_phase
     else:
-        basis = ['p', 'u', 'x', 'rx', 'ry', 'rz', 'cx']
+        basis = ['p', 'u', 'x', 'z', 'rx', 'ry', 'rz', 'cx']
         unrolled_gate = _unroll_gate(operation, basis_gates=basis)
         if unrolled_gate.definition.global_phase:
             global_phase += unrolled_gate.definition.global_phase
@@ -165,6 +165,11 @@ def control(operation: Union[Gate, ControlledGate],
                                              q_ancillae, use_basis_gates=True)
                         controlled_circ.mcrz(phi, q_control, q_target[qreg[0].index],
                                              use_basis_gates=True)
+            elif gate.name == 'z':
+                controlled_circ.h(q_target[qreg[0].index])
+                controlled_circ.mcx(q_control, q_target[qreg[0].index],
+                                    q_ancillae)
+                controlled_circ.h(q_target[qreg[0].index])
             else:
                 raise CircuitError('gate contains non-controllable instructions: {}'.format(
                     gate.name))


Test patch:
diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py
--- a/test/python/circuit/test_controlled_gate.py
+++ b/test/python/circuit/test_controlled_gate.py
@@ -207,6 +207,22 @@ def test_single_controlled_composite_gate(self):
         ref_mat = Operator(qc).data
         self.assertTrue(matrix_equal(cop_mat, ref_mat, ignore_phase=True))
 
+    def test_multi_control_z(self):
+        """Test a multi controlled Z gate. """
+        qc = QuantumCircuit(1)
+        qc.z(0)
+        ctr_gate = qc.to_gate().control(2)
+
+        ctr_circ = QuantumCircuit(3)
+        ctr_circ.append(ctr_gate, range(3))
+
+        ref_circ = QuantumCircuit(3)
+        ref_circ.h(2)
+        ref_circ.ccx(0, 1, 2)
+        ref_circ.h(2)
+
+        self.assertEqual(ctr_circ.decompose(), ref_circ)
+
     def test_multi_control_u3(self):
         """Test the matrix representation of the controlled and controlled-controlled U3 gate."""
         import qiskit.circuit.library.standard_gates.u3 as u3