Selection Condition Codes

I am attempting to lower the selectCC instruction to the instruction set
of the backend I'm working on and I cannot seem to find a way to
correctly implement this instruction. I know how this instruction should
get implemented; I just have yet to find a way to do it. I want the
select_cc instruction to be lowered into a comparison followed by a
conditional move. I've attempted to use a custom rule pasted below, but
it keeps giving me an error about the first argument.

What I attempted is as follows:

class InstFormat<dag outs, dag ins, string asmstr, list<dag> pattern>

        : Instruction {

    let Namespace = "Inst";

    dag OutOperandList = outs;

    dag InOperandList = ins;

    let Pattern = pattern;

    let AsmString = asmstr;

}

def SDTGenTernaryOp : SDTypeProfile<1, 3, [ SDTCisSameAs<0,
1>,SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3> ]>;

def cmov_logical : SDNode<"INSTISD::CMOVLOG", SDTGenTernaryOp>;

let PrintMethod = "printCCOperand" in

    def CCOp : Operand<i32>;

def CMOVLOG : InstFormat<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS,
GPR:$TVAL, GPR:$FVAL, CCOp:$cond),

                                "$cond $LHS, $LHS, $RHS\ncmov_logical
$dst, $LHS, $TVAL, $FVAL",

                                [(set GPR:$dst, (selectcc GPR:$LHS,
GPR:$RHS, GPR:$TVAL, GPR:$FVAL, CCOp:$cond))]>;

Maybe I'm approaching this from the wrong way, but I don't think this
transformation should be that difficult.

Basically I want dst = select $LHS, $RHS, $TVAL, $FVAL, $condOp to be
transformed into

$condOp tmp, $LHS, $RHS

cmov_logical dst, tmp, $TVAL, $FVAL

My attempt at doing so with a custom OperationAction also failed. So,
what would I need to do to figure out how to implement this correctly?
Is there any place you can point me to which shows how to go from a
single instruction to multiple consecutive instructions? A function that
I can study would be nice since my problem is even though I can look at
the other backends, I don't completely understand everything that is
going on so I probably overlooked this already.

Thanks,

Micah Villmow

Systems Engineer

Advanced Technology & Performance

Advanced Micro Devices Inc.

4555 Great America Pkwy,

Santa Clara, CA. 95054

P: 408-572-6219

F: 408-572-6596

I am attempting to lower the selectCC instruction to the instruction set of
the backend I'm working on and I cannot seem to find a way to correctly
implement this instruction. I know how this instruction should get
implemented; I just have yet to find a way to do it. I want the select_cc
instruction to be lowered into a comparison followed by a conditional move.

"setOperationAction(ISD::SELECT_CC , MVT::Other, Expand);"
should do the trick; that will prevent SELECT_CC instructions from
being introduced. This one is easy to miss.

def CMOVLOG : InstFormat<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS,
GPR:$TVAL, GPR:$FVAL, CCOp:$cond),

The condition isn't properly an input... this seems likely to confuse
ISel. I'm not sure, though; I'm not really an expert on patterns, and
they can mess up in non-obvious ways.

Maybe I'm approaching this from the wrong way, but I don't think this
transformation should be that difficult.

If you need to transform a construct into multiple instructions, there
are a few different ways; one is a custom lowering, one is a selection
pattern, and another is a custom inserter. Stuffing multiple actual
instructions into a single target instruction is generally a bad
approach.

-Eli

Eli, Thanks for the tips.
I've been able to get something working using a custom instruction
inserter, however, I'm still having the problem of linking together the
setcc and the select_cc commands. I want to turn the setcc into a
comparison and use the results in the select_cc register. However, the
comparison information is in the select_cc instruction and the result of
the comparison is in the setcc instruction. What I am trying to figure
out is using MachineInstruction/MachineBasicBlock, how I can access the
previous/next instruction without having to use an iterator and parse
over the whole block.

Is this possible? I've put comments in the code below to help understand
what I'm attempting to do.

case INST::SELECT_CC:
            // Here we want to write a custom instruction inserter for
the
            // select_cc operation. What we want to do is turn this into
            // a series of instructions that in the end become a compare
            // and a cmov_logical
            {
                MachineOperand Dst = MI->getOperand(0);
                MachineOperand TrueVal = MI->getOperand(1);
                MachineOperand FalseVal = MI->getOperand(2);
                MachineOperand CCFlag = MI->getOperand(3);
                CC = (INSTCC::CondCodes)MI->getOperand(3).getImm();
      // Here I want to get the destination register
of SET_CC instruction and place it as the first addReg
                TODO(Get setcc destination register);
                BuildMI(BB,
TII.get(INST::CMOVLOG_32),Dst.getReg()).addReg(CCFlag.getImm()).addReg(T
rueVal.getReg()).addReg(FalseVal.getReg());
            }
            break;
        case INST::SET_CC:
            {
                MachineOperand Dst = MI->getOperand(0);
                MachineOperand LHS = MI->getOperand(1);
                MachineOperand RHS = MI->getOperand(2);
      // I want to get the CCFlag from the select_CC
instruction
                  // and place it in the TII.get() field.
                BuildMI(BB, TII.get(INST::IL_COMPARE_INSTR),
Dst.getReg()).addReg(LHS.getReg()).addReg(RHS.getReg());
            }
        default:
};

Again,
Thanks for any tips you might be able to share.

Micah

I don't know too much about custom instruction inserters... so I don't
have any detailed comments on the code. But how exactly are you
defining INST::SET_CC and INST::SELECT_CC?

If I'm understanding what you're trying to do correctly, the x86
backend deals with this using a custom lowering; see
X86TargetLowering::LowerSELECT in X86ISelLowering.cpp.

-Eli

Hi Micah,

You should not need to select both setcc and select_cc. By its definition select_cc contains the conditional code as well as the two comparison operands.

Also, I don't think you need to use a custom instruction inserter. That is only needed if you are converting a single instruction into multiple ones that involve CFG update. You should follow examples in x86 and other targets and do a custom lowering of select_cc instead.

Evan