Dr. ERDI Gergo via llvm-dev
2017-May-30 13:01 UTC
[llvm-dev] Pseudo-instruction that overwrites its input register
On Tue, 30 May 2017, Nemanja Ivanovic wrote:> This is typically accomplished with something like PPC's `RegConstraint` and > `NoEncode`. You can see examples of it that are very similar to what you're after in > PPC's load/store with update forms (i.e. load a value and update the base register > with the effective address - these are used for pre-increment loads/stores). > For example: the definition of LBZU and friends in lib/Target/PowerPC/PPCInstrInfo.td. > For a simpler example of just the `RegConstraint` usage (as it doesn't use a compound > node like PPC's address nodes), you can look at all the fused multiply-add such as > XSMADDADP in lib/Target/PowerPC/PPCInstrVSX.td. > > Hope this helps.Thanks! However, none of the NoEncode examples in PPCInstrInfo.td seem to have an isel pattern; and the VSX examples, like XSMADDADP, seem to match on setting a single output: let BaseName = "XSMADDADP" in { let isCommutable = 1 in def XSMADDADP : XX3Form<60, 33, (outs vsfrc:$XT), (ins vsfrc:$XTi, vsfrc:$XA, vsfrc:$XB), "xsmaddadp $XT, $XA, $XB", IIC_VecFP, [(set f64:$XT, (fma f64:$XA, f64:$XB, f64:$XTi))]>, RegConstraint<"$XTi = $XT">, NoEncode<"$XTi">, AltVSXFMARel; If I'm reading this right, this matches an instruction that updates $XT by taking the current $XT, and two extra args in $XA and $XB. However, my situation would be something akin to (set f64:$XC, (fma f64:$XA, f64:$XB, f64:$XTi)) with the extra constraint that $XTi is overwritten in the process. Is there maybe a way to write a pattern like (set (tuple f64:$XC, f64:$XT), (fma f64:$XA, f64:$XB, f64:$XTi)) that would match (set f64:$XC, (fma f64:$XA, f64:$XB, f64:$XTi)) by automatically lifting it to store $XT as well? (of course, with a RegConstraint that $XT = $XTi)
Nemanja Ivanovic via llvm-dev
2017-May-30 13:54 UTC
[llvm-dev] Pseudo-instruction that overwrites its input register
The reason the ones in PPCInstrInfo.td don't have the patterns to match is the reason they are more analogous to your problem. Namely, tblgen does not have a way to produce nodes with more than one result. The load-with-update instructions do exactly that - one of the inputs is also an output, but the other output is independent (and necessarily a separate register). The FMA variants have patterns in the .td file because they don't have multiple results - they just have one of their operands being both an input and an output. So the idea is that you specify your `outs` in the instruction definition, one of those will have a `RegConstraint` on them and finally, you emit these nodes in your <TargetName>ISelDAGToDAG.cpp. On Tue, May 30, 2017 at 3:01 PM, Dr. ERDI Gergo <gergo at erdi.hu> wrote:> On Tue, 30 May 2017, Nemanja Ivanovic wrote: > > This is typically accomplished with something like PPC's `RegConstraint` >> and >> `NoEncode`. You can see examples of it that are very similar to what >> you're after in >> PPC's load/store with update forms (i.e. load a value and update the base >> register >> with the effective address - these are used for pre-increment >> loads/stores). >> For example: the definition of LBZU and friends in >> lib/Target/PowerPC/PPCInstrInfo.td. >> For a simpler example of just the `RegConstraint` usage (as it doesn't >> use a compound >> node like PPC's address nodes), you can look at all the fused >> multiply-add such as >> XSMADDADP in lib/Target/PowerPC/PPCInstrVSX.td. >> >> Hope this helps. >> > > Thanks! > > However, none of the NoEncode examples in PPCInstrInfo.td seem to have an > isel pattern; and the VSX examples, like XSMADDADP, seem to match on > setting a single output: > > let BaseName = "XSMADDADP" in { > let isCommutable = 1 in > def XSMADDADP : XX3Form<60, 33, > (outs vsfrc:$XT), (ins vsfrc:$XTi, vsfrc:$XA, > vsfrc:$XB), > "xsmaddadp $XT, $XA, $XB", IIC_VecFP, > [(set f64:$XT, (fma f64:$XA, f64:$XB, > f64:$XTi))]>, > RegConstraint<"$XTi = $XT">, NoEncode<"$XTi">, > AltVSXFMARel; > > If I'm reading this right, this matches an instruction that updates $XT by > taking the current $XT, and two extra args in $XA and $XB. However, my > situation would be something akin to > > (set f64:$XC, (fma f64:$XA, f64:$XB, f64:$XTi)) > > with the extra constraint that $XTi is overwritten in the process. > > Is there maybe a way to write a pattern like > > (set (tuple f64:$XC, f64:$XT), (fma f64:$XA, f64:$XB, f64:$XTi)) > > that would match > > (set f64:$XC, (fma f64:$XA, f64:$XB, f64:$XTi)) > > by automatically lifting it to store $XT as well? (of course, with a > RegConstraint that $XT = $XTi) >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170530/16372f4b/attachment.html>
Dr. ERDI Gergo via llvm-dev
2017-Jun-03 12:13 UTC
[llvm-dev] Pseudo-instruction that overwrites its input register
On Tue, 30 May 2017, Nemanja Ivanovic wrote:> So the idea is that you specify your `outs` in the instruction definition, one of > those will have a `RegConstraint` on them and finally, you emit these nodes in your > <TargetName>ISelDAGToDAG.cpp.OK, thanks, I now get the basic idea -- but I'm still struggling with the implementation. In my ISelDATToDAG, if I match something like Selecting: t17: i16,ch = load<LD2[%v25](align=1)(dereferenceable)> t16:1, t2, undef:i16 then whatever I return as the machine node, it will have to be of the same type, i.e. (i16, ch), right? But if I have this extra output port for the changed address register, that means my output is now (i16, i16, ch). It is unclear to me how to reconcile that with the original abstract node that I'm matching on. In more concrete terms, I tried ignoring this and just copying the address argument and the chain: const LoadSDNode *LD = cast<LoadSDNode>(N); int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue(); if (AM == ISD::UNINDEXED && Offs == 0) { SDNode* LDW = CurDAG->getMachineNode( AVR::LDWRdPtr, SDLoc(N), VT, PtrVT, MVT::Other, LD->getBasePtr(), LD->getChain()); ReplaceNode(N, LDW); return true; } but this fails with /home/cactus/prog/rust/rust-avr/llvm/include/llvm/Support/Casting.h:222: typename std::enable_if<(! llvm::is_simple_type<Y>::value), typename llvm::cast_retty<X, const Y>::ret_type>::type llvm::cast(const Y&) [with X = llvm::ConstantSDNode; Y = llvm::SDValue; typename std::enable_if<(!llvm::is_simple_type<Y>::value), typename llvm::cast_retty<X, const Y>::ret_type>::type = llvm::ConstantSDNode*]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. Any more hints, please? Thanks, Gergo