Target does not provide no preserved mask

I’m dealing with the jumpTable of control flow of my backend, and I found something very strange.

here’s my test case:

int test_JumpTable()
{
    unsigned char flag[4] = {0x21, 0x22, 0x23, 0x24};
    int Result = 0;
    switch (flag[0])
    {
        case 0x21:
            Result = 1;
            break;
        case 0x22:
            Result = 2;
            break;
        case 0x23:
            Result = 3;
            break;
    }

    return Result;
}

My backend can generate .s file from this test case’s .ll file by llc command, like that:

test_JumpTable:
...
# %bb.0:
...
	beq	$r4, $r5, $BB0_3
	b	$BB0_1
$BB0_1:
	addi.w	$r5, $r0, 34
	beq	$r4, $r5, $BB0_4
	b	$BB0_2
$BB0_2:
	...
$BB0_3:
	...
$BB0_4:
	...
$BB0_5:
	...
$BB0_6:
	ld.w	$r4, $r3, 8
	addi.w	$r3, $r3, 16
	jr	$r1
$func_end0:

But ! if I add one more case in the switch statement, the llc command would fail, it says:

target does not provide no preserved mask
UNREACHABLE executed at /home/dyy/llvm-project-llvmorg-10.0.0/llvm/include/llvm/CodeGen/TargetRegisterInfo.h:447!
Stack dump:
0.	Program arguments: ./llc -march=loongarch -relocation-model=pic -mcpu=loongarch32 -filetype=asm test.ll -o - 
1.	Running pass 'Function Pass Manager' on module 'test.ll'.
2.	Running pass 'Live Interval Analysis' on function '@test_JumpTable'

I also tried many other test cases, such as
3 case + 1 default - it’s ok !
2 case - it’s ok !
5 case - no ok!

it seems like My backend can’t support switch with more than 3 case. Why? Comparing the two .ll files generated from 3case and 4case , the only difference is 4case has one more label than 3case. One more label won’t exceed the address limit, I have 16-bit for BasicBlock address.

Does any one have any idea what this bug might be about ? Thank you !

TLI’s MinimumJumpTableEntries defaults to 4; below that it lowers switch to a series of branches, at and above that it lowers it to indirection through a jump table (ISD::BR_JT).

1 Like

I noticed BR_JT too, and I expand it as Mips do :

setOperationAction(ISD::BR_JT, MVT::Other, Expand);

Isn’t this enough ?

Clearly for whatever reason TRI.getNoPreservedMask() ends up being called in the process. Perhaps ISD::BRIND (what it gets expanded to use on the computed jump target) doesn’t work for your target?

1 Like

Thank you for your reply

If I recall correctly TRI.getNoPreservedMask is used when a block has no successors and also doesn’t end in a return instruction

1 Like