On 8 March 2014 00:53, Owen Anderson <resistor at mac.com> wrote:> ISDOpcodes.h contains what documentation there is on the semantics of each > opcode.And TargetOpcodes.h for a few of the post-ISel ones (mostly they're in MachineInstr form, but you'll see them with -view-sched-dags, and occasionally before). Tim.
On 3/8/14, 7:18 AM, Tim Northover wrote: [...]> And TargetOpcodes.h for a few of the post-ISel ones (mostly they're in > MachineInstr form, but you'll see them with -view-sched-dags, and > occasionally before).Thanks very much; but I'm afraid it's not helping much... if only I could find some loose ends to unravel, I'm sure I can make this work (I have compiler experience elsewhere, just not with LLVM), but no matter how much I pick I can't make anything come loose! Some specific questions: (1) Given the DAG: i32 = GlobalAddress<i32* @i> ...I would expect to be able to select for it with an instruction pattern of this form: def MOVar : S32< (outs GR32:$rD), (ins i32imm:$addr), "mov $rD, $addr", [(set GR32:$rD, globaladdr:$addr)]>;(I'm aware the i32imm in the ins field is wrong, but I don't think I've got far enough for that to be a problem yet.) What actually happens when I try it is the compiler stack dumps, producing debug tracing that looks like this: x7f914882e210: i32 = <<Unknown Machine Node #65509>> 0x7f914882e210 [ORD=2] [ID=1] 0x7f914882e210: i32 = <<Unknown Machine Node #65509>> 0x7f914882e210 [ORD=2] [ID=1] 0x7f914882e210: i32 = <<Unknown Machine Node #65509>> 0x7f914882e210 [ORD=2] [ID=1] ...etc... It seems to have somehow managed to create a cycle in the DAG, which is of course wrong. But how? Has it replaced the GlobalAddress node with the MOVar node and then updated $addr to refer to the MOVar node? I'm not sure what I should be doing here --- I can't select for the enclosing CopyToReg node, and GlobalAddress is a leaf... (2) Even when I do manage to generate machine instructions, they're all discarded because they're dead. This is leading to very fast but slightly flawed code (all I get is a return instruction). My best guess is that this is because I'm incorrectly wiring up the function outputs, resulting in the compiler discarding the instructions because the result isn't used. Except I'm using precisely the same function lowering as one of the other targets. How do I find out what's happening here? -- ┌─── dg@cowlark.com ───── http://www.cowlark.com ───── │ │ "You cannot truly appreciate _Atlas Shrugged_ until you have read it │ in the original Klingon." --- Sea Wasp on r.a.sf.w -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 876 bytes Desc: OpenPGP digital signature URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140308/61a6c3a4/attachment.sig>
Hi David,> [(set GR32:$rD, globaladdr:$addr)]> It seems to have somehow managed to create a cycle in the DAG, which is > of course wrong. But how?When I write a similar pattern into the ARM .td files and look at (from the build directory) lib/Target/ARM/ARMGenDAGISel.inc, I see: /*56478*/ /*SwitchOpcode*/ 13, TARGET_VAL(ISD::GlobalAddress),// ->56494 /*56481*/ OPC_RecordNode, // #0 = $src /*56482*/ OPC_CheckType, MVT::i32, /*56484*/ OPC_CheckPatternPredicate, 4, // (!Subtarget->isThumb()) /*56486*/ OPC_MorphNodeTo, TARGET_VAL(ARM::MOVi32imm), 0, 1/*#VTs*/, MVT::i32, 1/*#Ops*/, 0, // Src: (globaladdr:i32):$src - Complexity = 3 // Dst: (MOVi32imm:i32 (globaladdr:i32):$src) The first lines are fairly unimportant, but the last two show what the DAG thinks it's doing and make it clear why the recursion happens. It's because the globaladdr node doesn't actually get changed during matching, so LLVM is just going to encounter it again at the next step and perform the same substitution. I'd want that Dst globaladdr to be a tglobaladdr (target globaladdr) since LLVM knows it shouldn't try to select target nodes. Existing targets mostly do that during ISelLowering for various reasons, but for your case a separate pattern can probably do the job: def : Pat<(globaladdr:$addr), (MOVar tglobaladdr:$addr)>;> (2) Even when I do manage to generate machine instructions, they're all > discarded because they're dead. This is leading to very fast but > slightly flawed code (all I get is a return instruction). > > My best guess is that this is because I'm incorrectly wiring up the > function outputs, resulting in the compiler discarding the instructions > because the result isn't used.That sounds most likely. If you run "llc -print-after-all" you should be able to see the MachineInstr dataflow before it all gets removed. For example a simple "ret i32* @glob" function (on ARM again) gives me: BB#0: derived from LLVM BB %0 %vreg0<def> = MOVi32imm <ga:@addr>; GPR:%vreg0 %R0<def> = COPY %vreg0; GPR:%vreg0 BX_RET pred:14, pred:%noreg, %R0<imp-use> The important point here is that the BX_RET has some kind of <imp-use> of the registers that will be used to return (%R0 in this case). It gets added first in XYZTargetLowering::LowerReturn, and then selected in the .td file using a variadic node. Which other target's LowerReturn are you using? That's probably the first thing we should check is doing its job. The pictures from of "llc -view-isel-dags" and "llc -view-sched-dags" on a simple function returning something would be very useful there. If you can upload them somewhere (or attach them) I'll take a look and see if anything looks wrong. Cheers. Tim.