blob: 337ced70a3559c24516da4db573151ccc6daf936 [file] [log] [blame] [edit]
-- Test cases for "flag elimination" optimization. Used to optimize away
-- registers that are always used immediately after assignment as branch conditions.
[case testFlagEliminationSimple]
def c() -> bool:
return True
def d() -> bool:
return True
def f(x: bool) -> int:
if x:
b = c()
else:
b = d()
if b:
return 1
else:
return 2
[out]
def c():
L0:
return 1
def d():
L0:
return 1
def f(x):
x, r0, r1 :: bool
L0:
if x goto L1 else goto L2 :: bool
L1:
r0 = c()
if r0 goto L3 else goto L4 :: bool
L2:
r1 = d()
if r1 goto L3 else goto L4 :: bool
L3:
return 2
L4:
return 4
[case testFlagEliminationOneAssignment]
def c() -> bool:
return True
def f(x: bool) -> int:
# Not applied here
b = c()
if b:
return 1
else:
return 2
[out]
def c():
L0:
return 1
def f(x):
x, r0, b :: bool
L0:
r0 = c()
b = r0
if b goto L1 else goto L2 :: bool
L1:
return 2
L2:
return 4
[case testFlagEliminationThreeCases]
def c(x: int) -> bool:
return True
def f(x: bool, y: bool) -> int:
if x:
b = c(1)
elif y:
b = c(2)
else:
b = c(3)
if b:
return 1
else:
return 2
[out]
def c(x):
x :: int
L0:
return 1
def f(x, y):
x, y, r0, r1, r2 :: bool
L0:
if x goto L1 else goto L2 :: bool
L1:
r0 = c(2)
if r0 goto L5 else goto L6 :: bool
L2:
if y goto L3 else goto L4 :: bool
L3:
r1 = c(4)
if r1 goto L5 else goto L6 :: bool
L4:
r2 = c(6)
if r2 goto L5 else goto L6 :: bool
L5:
return 2
L6:
return 4
[case testFlagEliminationAssignmentNotLastOp]
def f(x: bool) -> int:
y = 0
if x:
b = True
y = 1
else:
b = False
if b:
return 1
else:
return 2
[out]
def f(x):
x :: bool
y :: int
b :: bool
L0:
y = 0
if x goto L1 else goto L2 :: bool
L1:
b = 1
y = 2
goto L3
L2:
b = 0
L3:
if b goto L4 else goto L5 :: bool
L4:
return 2
L5:
return 4
[case testFlagEliminationAssignmentNoDirectGoto]
def f(x: bool) -> int:
if x:
b = True
else:
b = False
if x:
if b:
return 1
else:
return 2
return 4
[out]
def f(x):
x, b :: bool
L0:
if x goto L1 else goto L2 :: bool
L1:
b = 1
goto L3
L2:
b = 0
L3:
if x goto L4 else goto L7 :: bool
L4:
if b goto L5 else goto L6 :: bool
L5:
return 2
L6:
return 4
L7:
return 8
[case testFlagEliminationBranchNotNextOpAfterGoto]
def f(x: bool) -> int:
if x:
b = True
else:
b = False
y = 1 # Prevents the optimization
if b:
return 1
else:
return 2
[out]
def f(x):
x, b :: bool
y :: int
L0:
if x goto L1 else goto L2 :: bool
L1:
b = 1
goto L3
L2:
b = 0
L3:
y = 2
if b goto L4 else goto L5 :: bool
L4:
return 2
L5:
return 4
[case testFlagEliminationFlagReadTwice]
def f(x: bool) -> bool:
if x:
b = True
else:
b = False
if b:
return b # Prevents the optimization
else:
return False
[out]
def f(x):
x, b :: bool
L0:
if x goto L1 else goto L2 :: bool
L1:
b = 1
goto L3
L2:
b = 0
L3:
if b goto L4 else goto L5 :: bool
L4:
return b
L5:
return 0
[case testFlagEliminationArgumentNotEligible]
def f(x: bool, b: bool) -> bool:
if x:
b = True
else:
b = False
if b:
return True
else:
return False
[out]
def f(x, b):
x, b :: bool
L0:
if x goto L1 else goto L2 :: bool
L1:
b = 1
goto L3
L2:
b = 0
L3:
if b goto L4 else goto L5 :: bool
L4:
return 1
L5:
return 0
[case testFlagEliminationFlagNotAlwaysDefined]
def f(x: bool, y: bool) -> bool:
if x:
b = True
elif y:
b = False
else:
bb = False # b not assigned here -> can't optimize
if b:
return True
else:
return False
[out]
def f(x, y):
x, y, r0, b, bb, r1 :: bool
L0:
r0 = <error> :: bool
b = r0
if x goto L1 else goto L2 :: bool
L1:
b = 1
goto L5
L2:
if y goto L3 else goto L4 :: bool
L3:
b = 0
goto L5
L4:
bb = 0
L5:
if is_error(b) goto L6 else goto L7
L6:
r1 = raise UnboundLocalError('local variable "b" referenced before assignment')
unreachable
L7:
if b goto L8 else goto L9 :: bool
L8:
return 1
L9:
return 0