<div dir="ltr"><div><div>Our target has a load.idx opcode with the following semantics:<br><br></div>load.idx r1,r2,r3, SIZE  :   r1 <- mem[r2 + (r3 << sizeof(operand))]<br><br></div>(where sizeof(operand) is in the range 0..3<br><div><div><div><br>Here's a snippet of the DAG I want to match so that a load.idx instruction is selected:<br>...<br>            0x30d29c0: i64 = Constant<3><br><br>          0x30d2e00: i64 = shl 0x30d2be0, 0x30d29c0 [ORD=3]<br><br>        0x30d2f10: i64 = add 0x30d2cf0, 0x30d2e00 [ORD=3]<br><br>        0x30d28b0: <multiple use><br>      0x30d3020: i64,ch = load 0x30a3ec0, 0x30d2f10, 0x30d28b0<LD8[%arrayidx16(addrspace=4)](tbaa=<0x3082188>)> [ORD=4]<br>...<br><br></div><div>Here's what I'm trying in TargetInstrInfo.td:<br><br>class Addr< int numArgs, string funcName, dag opInfo ><br>  : Operand<i64>,<br>    ComplexPattern< i64, numArgs, funcName, [], [SDNPWantParent] > {<br>      let MIOperandInfo = opInfo;<br>    }<br><br>let PrintMethod = "printMemOperand" in {<br>  def ADDR_RR : Addr< 2, "SelectAddrRegReg",<br>                      (ops GPRC:$base, GPRC:$offsetreg) >;<br>  def ADDR_RI : Addr< 2, "SelectAddrRegImm",<br>                      (ops GPRC:$base, i64imm:$offsetimm) >;<br>}<br>def ADDR_I : Addr< 1, "SelectAddrImmLocal", (ops i64imm:$imm) >;<br>def ADDR_SHLI : Addr< 2, "SelectAddrShlImm", <br>                      (ops GPRC:$base, ( shl GPRC:$offsetreg, (i64 3))) >;<br>...<br><br>multiclass LoadOp< bits<7> op,<br>                   string instr_asm,<br>                   OperandInfo info,<br>                   InstrItinClass itin=II_LOAD1_RR > {<br>  let opsize = info.sizeCode in {<br>...<br>    //<br>    // store: mem[r2 + r3] = r1<br>    //<br>    def _RR : FR3< op,<br>        (outs),<br>        (ins ADDR_RR:$addr, info.regClass:$r1),<br>        instr_asm # "\t\t$r1, $addr, " # info.sizeStr,<br>        [(store info.regClass:$r1, ADDR_RR:$addr)],<br>        itin > {<br>          let regcount = 5; // ISA change<br>        }<br>    //<br>    // load: r1 = mem[r2 + (r3 << sizeof(operand) ]<br>    //<br>    def _SHLI : FR3< op,<br>        (outs info.regClass:$r1),<br>        (ins ADDR_SHLI:$addr),<br>        //instr_asm#"\t$r1, $r2, $r3, "#info.sizeStr,<br>        instr_asm # "\t\t$r1, $addr, " # info.sizeStr,<br>        [(set info.regClass:$r1, (load ADDR_SHLI:$addr))],<br>        itin > {<br>       }<br>...<br>}<br>...<br>defm LOADI64_SHL : LoadOp< 0b1001100, "load.idx", OpInfo_I64 >;<br></div><div>//end<br></div><div>(Note: ADDR_RR, ADDR_RI, ADDR_I definitions already existed, I'm trying to add ADDR_SHLI).<br></div><div><br></div><div>When I try to run llvm-tblgen with -gen-instr-info I get:<br>llvm-tblgen: /home/phil/eqware/tg/tg/xe-llvm/include/llvm/Support/Casting.h:237: typename llvm::cast_retty<X, Y*>::ret_type llvm::cast(Y*) [with X = llvm::DefInit; Y = llvm::Init; typename llvm::cast_retty<X, Y*>::ret_type = llvm::DefInit*]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.<br><br><br></div><div>The problem seems to be the (ins ADDR_SHLI:$addr in def _SHLI above. If I change it to: (ins ADDR_RR:$addr) it runs ok, but then it's not going to match what I'm trying to match.<br><br></div><div>Am I going about this the right way or is there be a different approach?<br></div><div><br></div><div>Phil<br></div><div><br></div></div></div></div>