LLVM Backend Issues

Hi,

I am having issues running a new backend that I created for a new architecture. I suspect these errors may have something to do with how I have the string setup in LLVMTargetMachine() below?

Also - It would be great if someone could point me to a document that describes some of these error messages? For example what does t26 …t4 mean?

Thanks in advance for taking your valuable time to help me!

Jeff

jeff@ubuntu:~/code$ llc dft_gf_msp.ll
LLVM ERROR: Cannot select: t28: ch = store<ST2%le, trunc to i16> t27, t26, FrameIndex:i32<14>, undef:i32
t26: i32,ch = load<LD2%sz, anyext from i16> t25, FrameIndex:i32<2>, undef:i32
t7: i32 = FrameIndex<2>
t4: i32 = undef
t17: i32 = FrameIndex<14>
t4: i32 = undef
In function: main

LLVMTargetMachine(T, “e-m:e-p:32:32-i8:8:32-i16:16:32-n32-S32”, TT, CPU, FS, Options, RM, CM, OL),

It seems you don't handle truncstores properly. So, you'd either need
to expand them, or lower / select properly.

t26, etc. is just a numbering of nodes in sdag, so you could easily
how the things are connected. It used to be just addresses in the past
instead :slight_smile:

The t.. are just identifiers of the DAG nodes. It used to print addresses, but they were long and would change every time.

The "cannot select" errors are not that hard to track down: compile the failing testcase with -debug-only=isel and you'll see all the steps being taken up to the moment of failure. The last few messages will be something like "match failed at nnn". In your build directory in lib/Target/<yourtarget> there will be a file <yourtarget>GenDAGISel.inc. It contains the matching "script". The numbers nnn are shown in comments in that file and correspond to the steps the matcher performs. You'll be able to see what exactly it's trying to match.

-Krzysztof

Thanks Anton and Krzysztof!

Here is the dump using the -debug flag. At this point I am not making much sense of this, would it be too much to ask if one of you could walk me through one of these lines?

One thing that I didn’t point out is that I never defined any separate floating point registers, not sure if this will pose any issue?

Thanks again for your time!

Jeff

jeff@ubuntu:~/code$ llc -debug-only=isel dft_gf_msp.ll

=== main
Initial selection DAG: BB#0 ‘main:entry’
SelectionDAG has 18 nodes:
t0: ch = EntryToken
t4: ch = store<ST4[%retval]> t0, Constant:i32<0>, FrameIndex:i32<0>, undef:i32
t7: ch = store<ST4[%sz]> t4, Constant:i32<256>, FrameIndex:i32<2>, undef:i32
t10: ch = store<ST4[%dir]> t7, ConstantFP:f32<-1.000000e+00>, FrameIndex:i32<3>, undef:i32
t12: ch = store<ST4[%m]> t10, Constant:i32<0>, FrameIndex:i32<19>, undef:i32
t13: i32,ch = load<LD4[%sz]> t12, FrameIndex:i32<2>, undef:i32
t15: ch = store<ST4[%j]> t13:1, t13, FrameIndex:i32<16>, undef:i32
t17: ch = store<ST4[%le]> t15, t13, FrameIndex:i32<14>, undef:i32

Optimized lowered selection DAG: BB#0 ‘main:entry’
SelectionDAG has 18 nodes:
t0: ch = EntryToken
t4: ch = store<ST4[%retval]> t0, Constant:i32<0>, FrameIndex:i32<0>, undef:i32
t7: ch = store<ST4[%sz]> t4, Constant:i32<256>, FrameIndex:i32<2>, undef:i32
t19: ch = store<ST4[%dir]> t7, Constant:i32<-1082130432>, FrameIndex:i32<3>, undef:i32
t12: ch = store<ST4[%m]> t19, Constant:i32<0>, FrameIndex:i32<19>, undef:i32
t13: i32,ch = load<LD4[%sz]> t12, FrameIndex:i32<2>, undef:i32
t15: ch = store<ST4[%j]> t13:1, t13, FrameIndex:i32<16>, undef:i32
t17: ch = store<ST4[%le]> t15, t13, FrameIndex:i32<14>, undef:i32

Type-legalized selection DAG: BB#0 ‘main:entry’
SelectionDAG has 18 nodes:
t0: ch = EntryToken
t4: ch = store<ST4[%retval]> t0, Constant:i32<0>, FrameIndex:i32<0>, undef:i32
t7: ch = store<ST4[%sz]> t4, Constant:i32<256>, FrameIndex:i32<2>, undef:i32
t19: ch = store<ST4[%dir]> t7, Constant:i32<-1082130432>, FrameIndex:i32<3>, undef:i32
t12: ch = store<ST4[%m]> t19, Constant:i32<0>, FrameIndex:i32<19>, undef:i32
t13: i32,ch = load<LD4[%sz]> t12, FrameIndex:i32<2>, undef:i32
t15: ch = store<ST4[%j]> t13:1, t13, FrameIndex:i32<16>, undef:i32
t17: ch = store<ST4[%le]> t15, t13, FrameIndex:i32<14>, undef:i32

Legalized selection DAG: BB#0 ‘main:entry’
SelectionDAG has 18 nodes:
t0: ch = EntryToken
t4: ch = store<ST4[%retval]> t0, Constant:i32<0>, FrameIndex:i32<0>, undef:i32
t7: ch = store<ST4[%sz]> t4, Constant:i32<256>, FrameIndex:i32<2>, undef:i32
t19: ch = store<ST4[%dir]> t7, Constant:i32<-1082130432>, FrameIndex:i32<3>, undef:i32
t12: ch = store<ST4[%m]> t19, Constant:i32<0>, FrameIndex:i32<19>, undef:i32
t13: i32,ch = load<LD4[%sz]> t12, FrameIndex:i32<2>, undef:i32
t15: ch = store<ST4[%j]> t13:1, t13, FrameIndex:i32<16>, undef:i32
t17: ch = store<ST4[%le]> t15, t13, FrameIndex:i32<14>, undef:i32

Optimized legalized selection DAG: BB#0 ‘main:entry’
SelectionDAG has 18 nodes:
t0: ch = EntryToken
t4: ch = store<ST4[%retval]> t0, Constant:i32<0>, FrameIndex:i32<0>, undef:i32
t7: ch = store<ST4[%sz]> t4, Constant:i32<256>, FrameIndex:i32<2>, undef:i32
t19: ch = store<ST4[%dir]> t7, Constant:i32<-1082130432>, FrameIndex:i32<3>, undef:i32
t12: ch = store<ST4[%m]> t19, Constant:i32<0>, FrameIndex:i32<19>, undef:i32
t13: i32,ch = load<LD4[%sz]> t12, FrameIndex:i32<2>, undef:i32
t15: ch = store<ST4[%j]> t13:1, t13, FrameIndex:i32<16>, undef:i32
t17: ch = store<ST4[%le]> t15, t13, FrameIndex:i32<14>, undef:i32

===== Instruction selection begins: BB#0 ‘entry’
ISEL: Starting pattern match on root node: t17: ch = store<ST4[%le]> t15, t13, FrameIndex:i32<14>, undef:i32

Match failed at index 0
LLVM ERROR: Cannot select: t17: ch = store<ST4[%le]> t15, t13, FrameIndex:i32<14>, undef:i32
t13: i32,ch = load<LD4[%sz]> t12, FrameIndex:i32<2>, undef:i32
t6: i32 = FrameIndex<2>
t3: i32 = undef
t16: i32 = FrameIndex<14>
t3: i32 = undef
In function: main

Here's the beginning of the HexagonGenDAGISel.inc file (without the comment):

// The main instruction selector code.
SDNode *SelectCode(SDNode *N) {
   // Some target values are emitted as 2 bytes, TARGET_VAL handles
   // this.
   #define TARGET_VAL(X) X & 255, unsigned(X) >> 8
   static const unsigned char MatcherTable = {
/*0*/ OPC_SwitchOpcode /*95 cases */, 16|128,95/*12176*/, TARGET_VAL(ISD::STORE),// ->12181
/*5*/ OPC_RecordMemRef,
/*6*/ OPC_RecordNode, // #0 = 'st' chained node
/*7*/ OPC_Scope, 75|128,64/*8267*/, /*->8277*/ // 4 children in Scope
/*10*/ OPC_MoveChild1,

You should have the corresponding file for yout target in your build directory (it's an automatically generated file).

The /*0*/ is the first step that the selector takes in your case, and it's the step where it fails ("match failed at index 0"). What's at this index in your file? What patterns for stores do you have in your .td files?

-Krzysztof

Hi Krzysztof,

It actually shows a load at 0, I should also mention that I am using the msp430 as a template as I iteratively modify it. It may not be the best template to move to a standard 32 bit load / store RISC type architecture. :confused: The msp430 can have memory locations as the source input on instructions.

Thanks for your time,

Jeff

// InstrInfo.td

def MOV32rm : I32<0x0,
(outs GR32:$dst), (ins memsrc:$src),
“mov.w\t{$src, $dst}”,
[(set GR32:$dst, (load addr:$src))]>;
}

//GenDAGISel.inc

#define TARGET_VAL(X) X & 255, unsigned(X) >> 8
static const unsigned char MatcherTable = {
/0/ OPC_SwitchOpcode /27 cases /, 22, TARGET_VAL(ISD::LOAD),// ->26
/4/ OPC_RecordMemRef,
/5/ OPC_RecordNode, // #0 = ‘ld’ chained node
/6/ OPC_RecordChild1, // #1 = $src
/7/ OPC_CheckPredicate, 0, // Predicate_unindexedload
/9/ OPC_CheckPredicate, 1, // Predicate_load
/11/ OPC_CheckType, MVT::i32,
/13/ OPC_CheckComplexPat, /CP/0, /
#
/1, // SelectAddr:$src #2 #3
/16/ OPC_EmitMergeInputChains1_0,
/17/ OPC_MorphNodeTo, TARGET_VAL(JEFFARCH::MOV32rm), 0|OPFL_Chain|OPFL_MemRefs,
1/#VTs/, MVT::i32, 2/#Ops/, 2, 3,

Hi Jeff,

Dealing with .td files can be tricky, since the order of pattern can make a difference, a given DAG can match several different patterns with different outcomes, etc. Using the .td file from one architecture to develop one for another architecture can lead to many misleading problems. I'd suggest removing all the msp430-specific parts and adding yours from scratch. That will likely be easier than the porting.

-Krzysztof