Ifcvt: Detecting predicate cloober in GPRs

Dear devs,
I’m having issues to detect predicate clobber instructions when performing if-conversion.
Here is a minimal MIR use case:


bb.0 (%ir-block.0):
  successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)
  liveins: $r0, $r1, $r2, $r3         << Perhaps not related, but $r0 should not be in liveins.
  $r0 = FCOMPNHQ killed $r0, killed $r1, 4
  $r0 = ANDWri10 killed $r0, 1                   <<=== Conditional branch predicate lives in $r0, a GPR
  CB killed $r0, %bb.2, 8                        << Conditional Branch

bb.1.then:
; predecessors: %bb.0
  liveins: $r2
  $r0 = MAKEi16 0                          <<===   Instruction uses predicate dead register
  SWri10 0, killed $r2, killed $r0 :: (store 4 into %ir.p1)
  RET implicit $ra

bb.2.else:
; predecessors: %bb.0
  liveins: $r3
  $r0 = MAKEi16 0                          <<===   Instruction uses predicate dead register
  SWri10 0, killed $r3, killed $r0 :: (store 4 into %ir.p2)
  RET implicit $ra

gets transformed to:

bb.0 (%ir-block.0):
  liveins: $r0, $r1, $r2, $r3
  $r0 = FCOMPNHQ killed $r0, killed $r1, 4
  dead $r0 = ANDWri10 killed $r0, 1 << Predicate is dead
  $r0 = MAKEi16 0                   <<=== The predicate gets destroyed by the true/false joint instruction.
  SWrrc killed $r3, $r0, 8, $r0 :: (store 4 into %ir.p2) <<=== True instruction has a bad predicate
  SWrrc killed $r2, killed $r0, 9, killed $r0 :: (store 4 into %ir.p1) <<=== False instruction has a bad predicate
  RET implicit $ra

Ideally at first step I would like it to just avoid performing the if-conversion. With the current API I could,
for each instruction tested in TargetInstrInfo.ClobbersPredicate, perform branchAnalyze(MI.getParent()->pred_begin)
to obtain the predicate register and then check if MI defines the same register. But that seems rather awkward.
Is there a better option I’m missing? It really seems ClobbersPredicate assumes predicates are in a special class of registers.

At a second stage, I would like to use RegisterScavenger to obtain a register not used in the True or False
bbs and change the predicate register to an unused value, such as:

bb.0 (%ir-block.0):
  liveins: $r0, $r1, $r2, $r3
  $r0 = FCOMPNHQ killed $r0, killed $r1, 4
  $r10 = ANDWri10 killed $r0, 1                   <<=== Get a free register to the predicate
  $r0 = MAKEi16 0                                 <<== Clobber no more
  SWrrc killed $r3, $r0, 8, $r10 :: (store 4 into %ir.p2) <<=== Instruction when predicated uses the new value
  SWrrc killed $r2, killed $r0, 9, killed $r10 :: (store 4 into %ir.p1) <<=== Instruction when predicated uses the new value
  RET implicit $ra

I guess the best solution would be to add to TTI a hook to tell that predicates live in GPRs and hack IfConverter::AnalyzeBranches to detect the predicate is clobbered. If clobbered, it could try to move the predicate register if it has a single use (the conditional branch).
Does that seem useful for anyone else?

Cheers
Diogo Sampaio
Senior Compiler Engineer • Kalray

Tags: if-conversion ifconversion ifcvt