[LLVMdev] Inserting nodes into SelectionDAG (X86)

Dan Gohman gohman at apple.com
Wed Jul 8 17:32:49 PDT 2009

On Jul 3, 2009, at 1:56 PM, Artjom Kochtchi wrote:

> Thanks to your help I've actually made some progress... Especially the
> SelectionDAGNodes.h was a good hint.
> But there are still some things that I can't figure out:
>  // 'mov eax, 41'
>  Chain = DAG.getCopyToReg(Chain, DAG.getRegister(X86::EAX, MVT::i32),
> DAG.getConstant(41, MVT::i32), InFlag);
>  InFlag = Chain.getValue(1);
>  // 'inc eax'
>  SDValue eaxVal = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32);
>  SDValue inc = DAG.getNode(ISD::ADD, MVT::i32, eaxVal,  
> DAG.getConstant(1,
> MVT::i32));
>  InFlag = SDValue();
>  Chain = DAG.getCopyToReg(Chain, DAG.getRegister(X86::EAX,  
> MVT::i32), inc,
> InFlag);
>  InFlag = Chain.getValue(1);
> This code produces the following assembly instructions:
>  movl  $41, %eax
>  movl  $41, %eax
>  incl	   %eax
> I guess that's because what I want to become 'incl %eax' actually  
> becomes
> 'movl  $41, %eax' for the first parameter for the ADD-node and 'incl  
> %eax'
> for the second.
> So in order to fix this problem, I tried:
>  SDValue inc = DAG.getNode(ISD::ADD, MVT::i32, DAG.getConstant(41,
> MVT::i32) DAG.getConstant(1, MVT::i32));
>  InFlag = SDValue();
>  Chain = DAG.getCopyToReg(Chain, DAG.getRegister(X86::EAX,  
> MVT::i32), inc,
> InFlag);
>  InFlag = Chain.getValue(1);
> Unfortunately, this becomes
>  movl  $42, %eax
> 1) That is, the ADD-operation is being folded. Is there a way to  
> prevent
> this from happening? I tried creating the constants wit
> DAG::getTargetConstant, but it didn't help.

The code you're showing here is presumably just experimental code
that you'll eventually replace with something more interesting.
Unfortunately, it's difficult to see what you're actually
trying to do. For example, do you really need %eax, or do you
just need some register which isn't potentially used as an
argument register? If the latter, all this code could be a lot

One thing to keep in mind is that the pre-isel SelectionDAG is still
somewhat high-level, and it can be somewhat awkward to think about
it in terms of x86 instructions.

> 2) The second thing in this code is that InFlag. If I don't place  
> InFlag =
> SDValue(); there, llc complains about wrong topological ordering.  
> What's
> that about? Related to that: If I recover the Flag-result from the  
> Chain by
> InFlag = Chain.getValue(1);, what is it good for?

Physical register lifetimes are not fully modeled in the SelectionDAG.
Flags are used to glue nodes together to protect them. If a node needs
input values in multiple physical registers, the CopyToReg nodes are
attached via flag operand to each other in a sequence, and finally to
the node itself. The first node in the sequence does not use a flag
operand. In your case, there's only one physical register, so the
CopyToReg node doesn't need a Flag input.

> The last thing is that for the runtime check I want to insert I need  
> to
> compare the contents of eax with the parameter of the first  
> instruction of
> the call-target. If they are unequal, I want to jump to an error  
> label. So,
> the assembly to produce should look something like this (where  
> callee is the
> call destination):
>  cmp eax, 4(callee)
>  jne  error
> So what I've produced is:
>  // expected (from eax)
>  SDValue lhs = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32);
>  // operand of first callee instruction
>  SDValue rhs = DAG.getNode(ISD::ADD, MVT::i32, Callee,  
> DAG.getConstant(4,
> MVT::i32));
>  Ops.push_back(Chain);
>  Ops.push_back(DAG.getCondCode(ISD::SETEQ));
>  Ops.push_back(lhs);
>  Ops.push_back(rhs);
>  MachineBasicBlock *error_block;
>  Ops.push_back(DAG.getBasicBlock(error_block));
>  Chain = DAG.getNode(ISD::BR_CC, MVT::Other, &Ops[0], Ops.size());
> Now, there are, I guess, basically two things here:
> 3) How to access the value at address [callee + 4]? I guess, Callee  
> won't
> work as a parameter for add, and the result of the add in the cmp
> instruction wont be interpreted as a memory location (but as a  
> constant).

At pre-isel SelectionDAG time, the arguments aren't yet on the stack.  
just the operands to the ISD::CALL node.

> 4) The ISD::BR_CC instruction requires to be passed a  
> MachineBasicBlock.
> Obviously, the uninitialized pointer in my example won't work. Is  
> there any
> way to access any MBB in the Program from X86ISelLowering::LowerCALL?

The SelectionDAG framework currently only supports a single basic block
at a time, and it isn't possible to introduce new control flow from
within a block. This can perhaps be done by creating a new operator
which isn't lowered until later, or earlier, in LLVM IR, depending on
what you're trying to do.


More information about the llvm-dev mailing list