Confusion over ISelLowering of setcc

Hi,

I'm investigating an issue with the PTX backend I've come across (latest version from the trunk). Not being very familiar with Selection Dags, it's highly likely that I misunderstand some part of the process. I'd appreciate if someone can point me in the right direction.

Here's the LLVM IR that is causing problems (I'm aware this code doesn't do anything useful):

define ptx_device i32 @test(i32 %parameter) {
entry:
  %0 = icmp eq i32 %parameter, 0
  %1 = and i1 %0, 1
  %2 = and i1 %0, %1
  %3 = and i1 %0, %1
  br i1 %3, label %then, label %else

then: ; preds = %entry
  ret i32 1

else: ; preds = %entry
  ret i32 2
}

Run like this:

llvm-as test.ll -o test.bc
llc -march=ptx -relocation-model=pic -mattr=sm20 -mattr=ptx22 -mattr=64bit -mattr=double test.bc -o test.ptx

My first question would be why does it evaluate the entry basicblock twice (BB#0, BB#3), is this to do with predicated branching?

If I run this through llc with the -debug=1 flag (or by viewing the graphs), I get this in the initial selection dag:

        0x3451240: i1,ch = CopyFromReg 0x34341a8, 0x3451640
        0x3451340: i1 = Constant<-1>
      0x3451a40: i1 = xor 0x3451240, 0x3451340
      0x3451540: ch = BasicBlock<else 0x344c230>
    0x3451140: ch = brcond 0x34341a8, 0x3451a40, 0x3451540

This then gets lowered to this:

        0x3741240: i1,ch = CopyFromReg 0x37241a8, 0x3741640
        0x3741340: i1 = Constant<-1>
        0x3741940: ch = setne
      0x3741740: i1 = setcc 0x3741240, 0x3741340, 0x3741940
      0x3741540: ch = BasicBlock<else 0x373c230>
    0x3741140: ch = brcond 0x37241a8, 0x3741740, 0x3741540

And finally gets optimised to this:

        0x3741240: i1,ch = CopyFromReg 0x37241a8, 0x3741640 [ID=6]
        0x3741340: i1 = Constant<-1> [ID=2]
        0x3741940: ch = setne
      0x3741740: i64 = setcc 0x3741240, 0x3741340, 0x3741940
      0x3741540: ch = BasicBlock<else 0x373c230> [ID=3]
    0x3741140: ch = brcond 0x37241a8, 0x3741740, 0x3741540 [ID=8]

Which is invalid as setcc should always return an i1 type. I'm unsure as to whether this is coming from the -1 constant turning the setcc into an i64, or just the ISelLowering being set up incorrectly. http://llvm.org/docs/CodeGenerator.html#targetlowering does indicate that the return type of setcc operations should be specified in this class, though I'm not sure how this should be done.

Any help would be appreciated, (I've read through much of the docs but I'm still unsure).

Thanks,
Dan

Hi Dan,

And finally gets optimised to this:

0x3741240: i1,ch = CopyFromReg 0x37241a8, 0x3741640 [ID=6]
0x3741340: i1 = Constant<-1> [ID=2]
0x3741940: ch = setne
0x3741740: i64 = setcc 0x3741240, 0x3741340, 0x3741940
0x3741540: ch = BasicBlock<else 0x373c230> [ID=3]
0x3741140: ch = brcond 0x37241a8, 0x3741740, 0x3741540 [ID=8]

Which is invalid as setcc should always return an i1 type. I’m unsure as
to whether this is coming from the -1 constant turning the setcc into an
i64, or just the ISelLowering being set up incorrectly.
http://llvm.org/docs/CodeGenerator.html#targetlowering does indicate
that the return type of setcc operations should be specified in this
class, though I’m not sure how this should be done.

If you take a look at the TargetLowering class implementation (lib/CodeGen/SelectionDAG/TargetLowering.cpp), the virtual member function “getSetCCResultType()” is implemented as:

return PointerTy.SimpleTy;

So, the default action for the target independent code generator is to promote SetCC return types to the machine pointer type. Since this member function is virtual, you may try overriding getSetCCResultType().

But I think SetCC returning a type different of i1 is not invalid because you are in the lowering phase. In this phase, the code should comply to machine constraints (or, in other words, whatever the machine instruction selector can handle), and not the LLVM IR constraints.

-Rafael