AArch64: Implement switch/jump tables
This improves the performance of Cmm switch statements (compared to a chain of if statements.) The implementation is almost identical to that of the RISCV64 NCG.
Example
From CmmSwitchTest64
.
Generated Cmm:
u34l: // global
switch [1 .. 10] _s2wn::I64 {
case 1 : goto c347;
case 2 : goto c348;
case 3 : goto c349;
case 4 : goto c34a;
case 5 : goto c34b;
case 6 : goto c34c;
case 7 : goto c34d;
case 8 : goto c34e;
case 9 : goto c34f;
case 10 : goto c34g;
} // CmmSwitch
Assembly:
.Lu34l:
ubfm x18, x18, #0, #63
adrp x17, .Ln34G
add x17, x17, :lo12:.Ln34G // CmmLit (CmmLabel .Ln34G(other CLabel))
# Jump table for switch
lsl x18, x18, #3 // CmmReg (CmmLocal (LocalReg s2wn (CmmType BitsCat W64)))
add x18, x18, x17
ldr x18, [ x18, 0 ]
add x18, x18, x17
br x18
...
.section .rodata
.balign 8
.Ln34G:
.quad 0
.quad .Lc347-(.Ln34G)+0
.quad .Lc348-(.Ln34G)+0
.quad .Lc349-(.Ln34G)+0
.quad .Lc34a-(.Ln34G)+0
.quad .Lc34b-(.Ln34G)+0
.quad .Lc34c-(.Ln34G)+0
.quad .Lc34d-(.Ln34G)+0
.quad .Lc34e-(.Ln34G)+0
.quad .Lc34f-(.Ln34G)+0
.quad .Lc34g-(.Ln34G)+0
Ticket: #19912
Edited by Sven Tennie