Repository: numba/numba

Issue:
After updating the Numba from 0.43 to 0.51.2, the parallel code is displaying the error
 I have recently updated Numba in Anaconda at my machine from 0.43 to 0.51.2. The code which was running successfully with parallel=True is not running with prange. When I have replaced prange with range, the code executes but sequentially. Also, the sequential execution is taking much greater time with parallel=True in comparison to parallel=False.

The error message that I am getting in correspondence to my my program using parallel=True and prange is
```
TypingError: Internal error at <numba.core.typeinfer.CallConstraint object at 0x000001F463923C18>.
Failed in nopython mode pipeline (step: convert to parfors)
maximum recursion depth exceeded while calling a Python object
During: resolving callee type: type(CPUDispatcher(<function case1_flagi1_j1 at 0x000001F462EBC620>))

Enable logging at debug level for details.
```



Discussion:
Thanks for the report - can you provide an executable sample of code that allows reproducing the error please?
> 
> 
> Thanks for the report - can you provide an executable sample of code that allows reproducing the error please?

I have faced it in the following code 
```
@njit(cache=True,parallel=True)
def case1(edge_list,signs,i,j,rows,ppp,nnn,ppn_I,ppn_II,ppn_III,ppn_IV,pnn_I,pnn_II,pnn_III,pnn_IV):  
	a1,a2,a3,a4,a5,a6,a7,a8,a9,a10=0,0,0,0,0,0,0,0,0,0     
        for k in prange(j+1,rows):
                if (edge_list[i,1]==edge_list[k,0] and edge_list[j,1]==edge_list[k,1]) or (edge_list[i,1]==edge_list[k,1] and edge_list[j,1]==edge_list[k,0]):
                    if np.sum(signs[i]+signs[j]+signs[k])==3:               	
			a1+=1
                    elif np.sum(signs[i]+signs[j]+signs[k])==1:
                        x=np.zeros((3,1),dtype=np.int8)
                        if edge_list[i,1]==edge_list[k,0]:  
				x[0]=signs[i]
                        elif edge_list[j,1]==edge_list[k,0]:  		
				x[0]=signs[j]                        
                        if x[0,0]==1 and x[1,0]==1 and x[2,0]==-1: 		
				a3+=1
                        elif x[0,0]==1 and x[1,0]==-1 and x[2,0]==1: 
				a4+=1
                        elif x[0,0]==-1 and x[1,0]==1 and x[2,0]==1: 
				a5+=1
                    elif np.sum(signs[i]+signs[j]+signs[k])==-1:
                        x=np.zeros((3,1),dtype=np.int8)
                        if edge_list[i,1]==edge_list[k,0]: 			
				x[0]=signs[i]
                        elif edge_list[j,1]==edge_list[k,0]: 			
				x[0]=signs[j]                        
                        if x[0,0]==-1 and x[1,0]==-1 and x[2,0]==1:         	
				a7+=1
                        elif x[0,0]==-1 and x[1,0]==1 and x[2,0]==-1:      	
				a8+=1
                        elif x[0,0]==1 and x[1,0]==-1 and x[2,0]==-1:     	
				a9+=1
                    elif np.sum(signs[i]+signs[j]+signs[k])==-3:        	
			a2+=1
        return ppp,nnn, ppn_I,ppn_II,ppn_III,ppn_IV,pnn_I,pnn_II,pnn_III,pnn_IV

@njit(cache=True)
def signed_directed_triangles_numba1(edge_list):    
    edge_list=edge_list[:,0:3]
    rows_edge_lists=edge_list.shape    
    rows=rows_edge_lists[0]   
    signs=np.zeros((rows_edge_lists[0],1),dtype=np.int8);
    for ii in range(0,rows_edge_lists[0]):       
        if edge_list[ii,2]>=0: 		            signs[ii]=1;
        elif edge_list[ii,2]<0:			    signs[ii]=-1;        
    edge_list=edge_list[:,0:2]
    extracted_triangles=np.zeros((rows_edge_lists[0]-2,10),dtype=np.uint16);
    for i in range(0,rows_edge_lists[0]-2):
        flag_i1_j1=0
        ppp,nnn=0,0
        ppn_I,ppn_II,ppn_III,ppn_IV=0,0,0,0
        pnn_I,pnn_II,pnn_III,pnn_IV=0,0,0,0
        for j in range(i+1,rows-1):#rows_edge_lists[0]-1):
            if edge_list[i,0]==edge_list[j,0]:
                flag_i1_j1=1
		ppp,nnn,ppn_I,ppn_II,ppn_III,ppn_IV,pnn_I,pnn_II,pnn_III,pnn_IV=case1(edge_list,signs,i,j,rows,ppp,nnn,ppn_I,ppn_II,ppn_III,ppn_IV,pnn_I,pnn_II,pnn_III,pnn_IV)
        extracted_triangles[i]=np.array([ppp,nnn,ppn_I,ppn_II,ppn_III,ppn_IV,pnn_I,pnn_II,pnn_III,pnn_IV],dtype=np.uint16)    
    triangles_each_type=np.sum(extracted_triangles,axis=0)
    print(triangles_each_type)
    return 

edge_list=np.array([[6,2,4,1],[6,5,2,2],[1,15,1,4],[4,3,7,4],[13,16,8,5],[13,10,8,6],[7,5,1,7],[2,5,-1,8],[2,100,-10,9],[13,100,10,10],[16,10,-6,11],[16,100,-4,12],[5,100,-3,13],[13,200,-4,14],[100,200,3,15],[7,300,1,16],[7,400,1,17],[5,300,-5,18],[5,400,3,19],[111,222,-4,20]],dtype=np.int16)
signed_directed_triangles_numba1(edge_list)
```

I have also discussed about this error on https://numba.discourse.group/t/re-execution-of-the-same-jitted-function-causes-re-compilation-for-same-type-of-data/300 and Mr.Luk-f-a has also agreed about this error. He advised me to post at here. I have slightly changed the code from there because the code that I posted there was not for parallel execution and the code that I have written above is for parallel execution and to avoid race conditions. 

I have uninstalled on my machine the Anaconda with the latest update of Numba as I am not able to roll back the version 0.43.1 and re-installed March 2019 version of Anaconda (having Numba version 0.43.1) such that the above code is working there. 

I have one more query about the above code on version 0.43.1 of Numba that it is working sequentially (without any parallel=True) option in 2.7 seconds, while, with parallel=True, it is executing in 9.14 seconds. Due to this inefficiency, I have updated Numba on my machine and I got the above error in version 0.51.2 for the above code. Earlier, I have also installed the latest version of Anaconda but, in that version, I am also getting the same error where I have also noted that the version of Numba is 0.51.1 and hence I have re-installed March 2019 version of Anaconda with 0.43.1 version of Numba.
Thanks for the report. This is a bug. Reproducer:
```python
from numba import njit, prange
import numpy as np

@njit(parallel=True)
def foo():
    A = B = 0
    for k in prange(1):
        if k == 2:
            A += 1
        else:
            x = np.zeros((1, 1))
            if x[0, 0]:
                B += 1

foo()
```
this gets stuck here when working out the reductions:
https://github.com/numba/numba/blob/5dcb2f1252f30f30060725171facee0217685394/numba/parfors/parfor.py#L3524-L3529
Because `defs` contains `{'A.3': Var(A.2, issue6414.py:9), 'A.2': Var(A.3, issue6414.py:9)}` which is a mutually referent structure. I imagine that this is SSA related as these are just versions of the same variable.

CC @DrTodd13 

Resolving patch:
diff --git a/numba/parfors/parfor.py b/numba/parfors/parfor.py
--- a/numba/parfors/parfor.py
+++ b/numba/parfors/parfor.py
@@ -3436,7 +3436,7 @@ def get_parfor_reductions(func_ir, parfor, parfor_params, calltypes, reductions=
             if isinstance(stmt, Parfor):
                 # recursive parfors can have reductions like test_prange8
                 get_parfor_reductions(func_ir, stmt, parfor_params, calltypes,
-                    reductions, reduce_varnames, param_uses, param_nodes, var_to_param)
+                    reductions, reduce_varnames, None, param_nodes, var_to_param)
 
     for param, used_vars in param_uses.items():
         # a parameter is a reduction variable if its value is used to update it


Test patch:
diff --git a/numba/tests/test_parfors.py b/numba/tests/test_parfors.py
--- a/numba/tests/test_parfors.py
+++ b/numba/tests/test_parfors.py
@@ -2343,6 +2343,32 @@ def test_impl(n):
                'operators.')
         self.assertIn(msg, str(raises.exception))
 
+    @skip_parfors_unsupported
+    def test_prange_two_conditional_reductions(self):
+        # issue6414
+        def test_impl():
+            A = B = 0
+            for k in range(1):
+                if k == 2:
+                    A += 1
+                else:
+                    x = np.zeros((1, 1))
+                    if x[0, 0]:
+                        B += 1
+            return A, B
+        self.prange_tester(test_impl)
+
+    @skip_parfors_unsupported
+    def test_prange_nested_reduction1(self):
+        def test_impl():
+            A = 0
+            for k in range(1):
+                for i in range(1):
+                    if i == 0:
+                        A += 1
+            return A
+        self.prange_tester(test_impl)
+
 #    @skip_parfors_unsupported
     @disabled_test
     def test_check_error_model(self):