









Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
The handling of assignment in compilers, including strategies for evaluating and converting types, optimizing address calculations, and using condition codes. It also covers the use of conditional moves and predication for simplifying code.
Typology: Study notes
1 / 15
This page cannot be seen from the preview
Don't miss anything!










CMSC430 Spring 2007 (^1)
Strategy
Unambiguous scalars go into registers Ambiguous scalars or aggregates go into memory
Let hardware sort out the addresses!
CMSC430 Spring 2007 (^2)
What if the compiler cannot determine the type of the rhs?
Code for assignment becomes more complex
evaluate rhs if type(lhs) ≠ rhs.tag then
signal a run-time error lhs ← rhs
CMSC430 Spring 2007 (^3)
Compile-time type-checking
Optimization strategy
Can design the language so all checks are static
CMSC430 Spring 2007 (^4)
The problem with reference counting
With extra functional units & large caches, this may become free …
evaluate rhs lhs→count ← lhs →count - 1 lhs ← addr(rhs) rhs →count ← rhs →count + 1
Plus a check for zero at the end
CMSC430 Spring 2007 (^7)
A[ i ]
What about A[i 1 ][i 2 ]?
@A + (( i 1 – low 1 ) x (high 2 – low 2 + 1) + i 2 – low 2 ) x sizeof(A[1])
@A + (( i 2 – low 2 ) x (high 1 – low 1 + 1) + i 1 – low 1 ) x sizeof(A[1])
*(A[i 1 ])[i 2 ] — where A[i 1 ] is, itself, a 1-d array reference
This stuff looks expensive! Lots of implicit +, -, x ops
int A[1:10] ⇒ low is 1 Make low 0 for faster access (save a – )
Almost always a power of 2, known at compile-time ⇒ use a shift for speed
CMSC430 Spring 2007 (^8)
In row-major order @A + (i–low 1 )(high 2 –low 2 +1) x w + (j – low 2 ) x sizeof(A[1][1]) Which can be factored into @A + i x (high 2 –low 2 +1) x sizeof(A[1][1]) + j x sizeof(A[1][1])
Then, the address expression becomes @A 0 + (i x len 2 + j ) x sizeof(A[1][1]) Compile-time constants
CMSC430 Spring 2007 (^9)
What about arrays as actual parameters?
Whole arrays, as call-by-reference parameters
Some improvement is possible
What about call-by-value?
@A low 1 high 1 low 2 high 2
CMSC430 Spring 2007 (^10)
What about A[12] as an actual parameter?
If corresponding parameter is a scalar, it’s easy
What is corresponding parameter is an array?
⇒ Again, we’re treading on language design issues
CMSC430 Spring 2007 (^13)
DO J = 1, N A[I,J] = A[I,J] + B[I,J] END DO
R1 = I x floatsize c = len 1 x floatsize! Compile-time constant R2 = @A 0 + R R3 = @B 0 + R DO J = 1, N a = J x c R4 = R2 + a R5 = R3 + a MEM(R4) = MEM(R4) + MEM(R5) END DO
CMSC430 Spring 2007 (^14)
DO J = 1, N A[I,J] = A[I,J] + B[I,J] END DO
R1 = I x floatsize c = len 1 x floatsize! Compile-time constant R2 = @A 0 + R1 ; R3 = @B 0 + R DO J = 1, N R2 = R2 + c R3 = R3 + c MEM(R2) = MEM(R2) + MEM(R3) END DO
CMSC430 Spring 2007 (^15)
How should the compiler represent them?
Two classic approaches
CMSC430 Spring 2007 (^16)
Numerical representation
Examples
if (x < y)
else stmt 2
cmp_LT r (^) x ,r (^) y ⇒r (^1) cbr r1→_stmt 1 ,_stmt 2
CMSC430 Spring 2007 (^19)
The last example actually encodes result in the PC If result is used to control an operation, this may be enough
Condition code version does not directly produce (x < y) Boolean version does Still, there is no significant difference in the code produced
comp r (^) x ,r (^) y⇒cc 1 cmp_LT r (^) x ,r (^) y⇒r (^1) cbr _LT cc 1 →L 1 ,L 2 cbr r 1 →L 1 ,L (^2) L 1 : add r (^) c ,r (^) d⇒r (^) a L 1 : add r (^) c ,r (^) d⇒r (^) a br →LOUT br →LOUT L 2 : add r (^) e ,r (^) f ⇒r (^) a L 2 : add r (^) e ,r (^) f ⇒r (^) a br (^) →LOUT br (^) →LOUT LOUT : nop LOUT : nop
if (x < y) then a ← c + d else a ← e + f
Example
CMSC430 Spring 2007 (^20)
Conditional move & predication both simplify this code
Both versions avoid the branches Both are shorter than CCs or Boolean-valued compare
Are they better?
comp r (^) x,r (^) y⇒cc 1 cmp LT r (^) x,r (^) y⇒r (^1) add r (^) c ,r (^) d⇒r 1 (r 1 )? add r (^) c ,r (^) d⇒r (^) a add r (^) e ,r (^) f ⇒r 2 (¬r 1 )? add r (^) e ,r (^) f ⇒r (^) a i2i< cc 1 ,r 1 ,r 2 ⇒r (^) a
if (x < y) then a ← c + d else a ← e + f
Example
CMSC430 Spring 2007 (^21)
Consider the assignment x ← a < b ∧ c < d
Here, the boolean compare produces much better code
comp r (^) a ,r (^) b⇒cc 1 cmp_LT r (^) a ,r (^) b⇒r (^1) cbr _LT cc 1 →L 1 ,L 2 cmp_LT r (^) c ,r (^) d⇒r (^2) L 1 : (^) comp r (^) c ,r (^) d⇒cc 2 and r 1 ,r 2 ⇒r (^) x cbr _LT cc 2 →L 3 ,L (^2) L 2 : loadI 0 ⇒ rx br →L^ OUT L 3 : (^) loadI 1 ⇒ rx br →L^ OUT L (^) OUT : (^) nop
CMSC430 Spring 2007 (^22)
Conditional move & predication help here, too
Conditional move is worse than Boolean compares Predication is identical to Boolean compares
Context & hardware determine the appropriate choice
comp r (^) a ,r (^) b ⇒cc 1 cmp_LT r (^) a ,r (^) b⇒r (^1) i2i_< cc 1 ,r (^) T ,r (^) F ⇒r 1 cmp_LT r (^) c ,r (^) d⇒r (^2) comp r (^) c ,r (^) d ⇒cc 2 and r 1 ,r 2 ⇒r (^) x i2i_< cc 2 ,r (^) T ,r (^) F ⇒r (^2) and r 1 ,r 2 ⇒r (^) x
CMSC430 Spring 2007 (^25)
Case Statements 1 Evaluate the controlling expression 2 Branch to the selected case 3 Execute the code for that case 4 Branch to the statement after the case Parts 1, 3, & 4 are well understood, part 2 is the key
Strategies
Surprisingly many compilers do this for all cases!
CMSC430 Spring 2007 (^26)
Assume a procedure at level 3 calls a function with 2 arguments at static level 3: X(A,B)
CMSC430 Spring 2007 (^27)
CMSC430 Spring 2007 (^28)