Some background on the query
I’m trying to test the possibility of pre-computing conditional branch instructions as far ahead as possible (target and taken/not taken info) instead of the speculating at fetch using the BTB.
To do that I plan to convert a branch into multiple different instructions that write into an internal structure using a new custom register class ($bpr) which now contains the pre-computed branch information to avoid speculation.
Original instruction : beq $rs, $rt, Target
New instructions :
bmovt $bpr, Target_pc, $bpr
seteq $rd, $rs, $rt
bmovc $bpr, $rd, $bpr
The bmov instructions write into the same bpr registers at different slices essentially creating a BTB like structure. The hardware will then read this structure to get the pre-computed result instead of the conventional BTB that predicts the direction at fetch. The extra sourcing of the $bpr at the end is to avoid deadcode elimination by the compiler. (Is there a better way to get around this?)
I tried to write this pattern in the tablegen format using SETNE as an example :
def : Pat<(riscv_brcc GPR:$rs1, GPR:$rs2, SETNE, bb:$imm12),
(BMOVC (SLTU X0, (XOR GPR:$rs1, GPR:$rs2)), (BMOVT simm13_lsb0:$imm12, <bpr>))>;
The problem here is that the register is not part of the branch instruction so I’m unsure of how to specify it in the pattern match.
I tried doing this in C++ in the DAGtoDAG select function but I run into the same problem of specifying a register class that wasn’t part of the original instruction.