Be Careful with Positionally-Encoded Operands (AArch64, Mips, AMDGPU, etc.)

Hello,

Some of the backends seem to be combining positional and named operands when defining some instructions such that some of the positional operands overlap with some of the named operands. I suspect this is not intentional; here's an example:

AArch64 has the following instruction definition:

SMULHxxx {
  field bits<32> Inst = { 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, Rm{4}, Rm{3}, Rm{2}, Rm{1}, Rm{0}, 0, Ra{4}, Ra{3}, Ra{2}, Ra{1}, Ra{0}, Rn{4}, Rn{3}, Rn{2}, Rn{1}, Rn{0}, Rd{4}, Rd{3}, Rd{2}, Rd{1}, Rd{0} };
  ...
  dag OutOperandList = (outs GPR64:$Rd);
  dag InOperandList = (ins GPR64:$Rn, GPR64:$Rm);
  string AsmString = "smulh $Rd, $Rn, $Rm";
  list<dag> Pattern = [(set i64:$Rd, (mulhs i64:$Rn, i64:$Rm))];
  ...
  bits<5> Rd = { ?, ?, ?, ?, ? };
  bits<5> Rn = { ?, ?, ?, ?, ? };
  bits<5> Rm = { ?, ?, ?, ?, ? };
  bits<5> Ra = { ?, ?, ?, ?, ? };
...
}

So how do the operands in OutOperandList and InOperandList get mapped to the variables used to encode the instruction (Rd,Rn,Rm,Ra)? The first three match by name (as they appear explicitly in OutOperandList and InOperandList), but what about Ra? Ra contributes to defining the bits in Inst, and because there is, by default, no overlap checking, it also gets mapped to the first operand: GPR64:$Rd. The result, from AArch64GenMCCodeEmitter.inc is:

    case AArch64::SMULHxxx:
    case AArch64::UMULHxxx: {
      // op: Rd
      op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
      Value |= op & UINT64_C(31);
      // op: Rn
      op = getMachineOpValue(MI, MI.getOperand(1), Fixups, STI);
      Value |= (op & UINT64_C(31)) << 5;
      // op: Rm
      op = getMachineOpValue(MI, MI.getOperand(2), Fixups, STI);
      Value |= (op & UINT64_C(31)) << 16;
      // op: Ra
      op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
      Value |= (op & UINT64_C(31)) << 10;
      Value = fixMulHigh(MI, Value, STI);
      break;
    }

This may be correct (I have no idea), but even if it is, it seems like an odd way to get this behavior: depending on the fact that, after operands are matched by name, the remaining operands are matched by position such that they might overlap with those operands matched by name.

In any case, I believe that the only in-tree target that still really needs the positional operand support is PowerPC (because the named-operand matching scheme still can't deal with the complex operands that PPC uses for handling memory operands), and PowerPC needs the behavior that named and positional operands are disjoint so that we can start transitioning toward using named mapping, so I've added a new TableGen target bit to disable this problematic overlapping operand behavior (noNamedPositionallyEncodedOperands) in r203767.

This means that in lib/Target/PowerPC/PPC.td, we have:

def PPCInstrInfo : InstrInfo {
...

  let noNamedPositionallyEncodedOperands = 1;

...
}

I'd like those maintaining the current backends (especially AArch64, Mips, AMDGPU, which I know to be problematic in this regard) to try setting this and: a) fix those definitions that are problematic or b) explain to me that the current behavior is useful.

Thanks again,
Hal

Hi Hal,

This sounds like a really good idea in general, but...

let noNamedPositionallyEncodedOperands = 1;

The diagnostics produced are pretty atrocious (an assertion failure
without even mentioning which instruction is the problem). I couldn't
in good conscience recommend anyone try it in its present state if
there are more than 1-2 problems.

I'd like those maintaining the current backends (especially AArch64,
Mips, AMDGPU, which I know to be problematic in this regard) to try
setting this and: a) fix those definitions that are problematic or b) explain
to me that the current behavior is useful.

I've looked into the SMULH/UMULH case (which appears to be the only
issue in AArch64). It wasn't intended, but was also harmless.
Fortunately it can be removed fairly easily so I've done that and
enabled the flag in r203772.

Cheers.

Tim.

From: "Tim Northover" <t.p.northover@gmail.com>
To: "Hal Finkel" <hfinkel@anl.gov>
Cc: "LLVM Developers Mailing List" <llvmdev@cs.uiuc.edu>
Sent: Thursday, March 13, 2014 4:06:49 AM
Subject: Re: [LLVMdev] Be Careful with Positionally-Encoded Operands (AArch64, Mips, AMDGPU, etc.)

Hi Hal,

This sounds like a really good idea in general, but...

> let noNamedPositionallyEncodedOperands = 1;

The diagnostics produced are pretty atrocious (an assertion failure
without even mentioning which instruction is the problem). I couldn't
in good conscience recommend anyone try it in its present state if
there are more than 1-2 problems.

Good point. I can add a better diagnostic for this case (where enabling noNamedPositionallyEncodedOperands causes the position-based mapping to run off the end of the operand list); I may not have time until Tuesday, however.

> I'd like those maintaining the current backends (especially
> AArch64,
> Mips, AMDGPU, which I know to be problematic in this regard) to try
> setting this and: a) fix those definitions that are problematic or
> b) explain
> to me that the current behavior is useful.

I've looked into the SMULH/UMULH case (which appears to be the only
issue in AArch64). It wasn't intended, but was also harmless.
Fortunately it can be removed fairly easily so I've done that and
enabled the flag in r203772.

Thanks!

-Hal

Hello,

Some of the backends seem to be combining positional and named operands when defining some instructions such that some of the positional operands overlap with some of the named operands. I suspect this is not intentional; here's an example:

AArch64 has the following instruction definition:

SMULHxxx {
  field bits<32> Inst = { 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, Rm{4}, Rm{3}, Rm{2}, Rm{1}, Rm{0}, 0, Ra{4}, Ra{3}, Ra{2}, Ra{1}, Ra{0}, Rn{4}, Rn{3}, Rn{2}, Rn{1}, Rn{0}, Rd{4}, Rd{3}, Rd{2}, Rd{1}, Rd{0} };
  ...
  dag OutOperandList = (outs GPR64:$Rd);
  dag InOperandList = (ins GPR64:$Rn, GPR64:$Rm);
  string AsmString = "smulh $Rd, $Rn, $Rm";
  list<dag> Pattern = [(set i64:$Rd, (mulhs i64:$Rn, i64:$Rm))];
  ...
  bits<5> Rd = { ?, ?, ?, ?, ? };
  bits<5> Rn = { ?, ?, ?, ?, ? };
  bits<5> Rm = { ?, ?, ?, ?, ? };
  bits<5> Ra = { ?, ?, ?, ?, ? };
...
}

So how do the operands in OutOperandList and InOperandList get mapped to the variables used to encode the instruction (Rd,Rn,Rm,Ra)? The first three match by name (as they appear explicitly in OutOperandList and InOperandList), but what about Ra? Ra contributes to defining the bits in Inst, and because there is, by default, no overlap checking, it also gets mapped to the first operand: GPR64:$Rd. The result, from AArch64GenMCCodeEmitter.inc is:

    case AArch64::SMULHxxx:
    case AArch64::UMULHxxx: {
      // op: Rd
      op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
      Value |= op & UINT64_C(31);
      // op: Rn
      op = getMachineOpValue(MI, MI.getOperand(1), Fixups, STI);
      Value |= (op & UINT64_C(31)) << 5;
      // op: Rm
      op = getMachineOpValue(MI, MI.getOperand(2), Fixups, STI);
      Value |= (op & UINT64_C(31)) << 16;
      // op: Ra
      op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
      Value |= (op & UINT64_C(31)) << 10;
      Value = fixMulHigh(MI, Value, STI);
      break;
    }

This may be correct (I have no idea), but even if it is, it seems like an odd way to get this behavior: depending on the fact that, after operands are matched by name, the remaining operands are matched by position such that they might overlap with those operands matched by name.

In any case, I believe that the only in-tree target that still really needs the positional operand support is PowerPC (because the named-operand matching scheme still can't deal with the complex operands that PPC uses for handling memory operands), and PowerPC needs the behavior that named and positional operands are disjoint so that we can start transitioning toward using named mapping, so I've added a new TableGen target bit to disable this problematic overlapping operand behavior (noNamedPositionallyEncodedOperands) in r203767.

This means that in lib/Target/PowerPC/PPC.td, we have:

def PPCInstrInfo : InstrInfo {
...

  let noNamedPositionallyEncodedOperands = 1;

...
}

I'd like those maintaining the current backends (especially AArch64, Mips, AMDGPU, which I know to be problematic in this regard) to try setting this and: a) fix those definitions that are problematic or b) explain to me that the current behavior is useful.

Hi Hal,

Thanks for working on this, I have run into several problems with the
positional encodings and I would be happy to see it go away. However,
I was under the impression that positional encoding was the only way to
encode custom operand types that map to multiple machine operands.
See for example the MEMxi Operand sub-class in R600/R600Instructions.td.

Thanks,
Tom

From: "Tom Stellard" <tom@stellard.net>
To: "Hal Finkel" <hfinkel@anl.gov>
Cc: "LLVM Developers Mailing List" <llvmdev@cs.uiuc.edu>
Sent: Thursday, March 13, 2014 9:46:22 AM
Subject: Re: [LLVMdev] Be Careful with Positionally-Encoded Operands (AArch64, Mips, AMDGPU, etc.)

> Hello,
>
> Some of the backends seem to be combining positional and named
> operands when defining some instructions such that some of the
> positional operands overlap with some of the named operands. I
> suspect this is not intentional; here's an example:
>
> AArch64 has the following instruction definition:
>
> SMULHxxx {
> field bits<32> Inst = { 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, Rm{4},
> Rm{3}, Rm{2}, Rm{1}, Rm{0}, 0, Ra{4}, Ra{3}, Ra{2}, Ra{1},
> Ra{0}, Rn{4}, Rn{3}, Rn{2}, Rn{1}, Rn{0}, Rd{4}, Rd{3}, Rd{2},
> Rd{1}, Rd{0} };
> ...
> dag OutOperandList = (outs GPR64:$Rd);
> dag InOperandList = (ins GPR64:$Rn, GPR64:$Rm);
> string AsmString = "smulh $Rd, $Rn, $Rm";
> list<dag> Pattern = [(set i64:$Rd, (mulhs i64:$Rn, i64:$Rm))];
> ...
> bits<5> Rd = { ?, ?, ?, ?, ? };
> bits<5> Rn = { ?, ?, ?, ?, ? };
> bits<5> Rm = { ?, ?, ?, ?, ? };
> bits<5> Ra = { ?, ?, ?, ?, ? };
> ...
> }
>
> So how do the operands in OutOperandList and InOperandList get
> mapped to the variables used to encode the instruction
> (Rd,Rn,Rm,Ra)? The first three match by name (as they appear
> explicitly in OutOperandList and InOperandList), but what about
> Ra? Ra contributes to defining the bits in Inst, and because there
> is, by default, no overlap checking, it also gets mapped to the
> first operand: GPR64:$Rd. The result, from
> AArch64GenMCCodeEmitter.inc is:
>
> case AArch64::SMULHxxx:
> case AArch64::UMULHxxx: {
> // op: Rd
> op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
> Value |= op & UINT64_C(31);
> // op: Rn
> op = getMachineOpValue(MI, MI.getOperand(1), Fixups, STI);
> Value |= (op & UINT64_C(31)) << 5;
> // op: Rm
> op = getMachineOpValue(MI, MI.getOperand(2), Fixups, STI);
> Value |= (op & UINT64_C(31)) << 16;
> // op: Ra
> op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
> Value |= (op & UINT64_C(31)) << 10;
> Value = fixMulHigh(MI, Value, STI);
> break;
> }
>
> This may be correct (I have no idea), but even if it is, it seems
> like an odd way to get this behavior: depending on the fact that,
> after operands are matched by name, the remaining operands are
> matched by position such that they might overlap with those
> operands matched by name.
>
> In any case, I believe that the only in-tree target that still
> really needs the positional operand support is PowerPC (because
> the named-operand matching scheme still can't deal with the
> complex operands that PPC uses for handling memory operands), and
> PowerPC needs the behavior that named and positional operands are
> disjoint so that we can start transitioning toward using named
> mapping, so I've added a new TableGen target bit to disable this
> problematic overlapping operand behavior
> (noNamedPositionallyEncodedOperands) in r203767.
>
> This means that in lib/Target/PowerPC/PPC.td, we have:
>
> def PPCInstrInfo : InstrInfo {
> ...
>
> let noNamedPositionallyEncodedOperands = 1;
>
> ...
> }
>
> I'd like those maintaining the current backends (especially
> AArch64, Mips, AMDGPU, which I know to be problematic in this
> regard) to try setting this and: a) fix those definitions that are
> problematic or b) explain to me that the current behavior is
> useful.
>

Hi Hal,

Thanks for working on this, I have run into several problems with the
positional encodings and I would be happy to see it go away.
However,
I was under the impression that positional encoding was the only way
to
encode custom operand types that map to multiple machine operands.
See for example the MEMxi Operand sub-class in
R600/R600Instructions.td.

Yes, this is the remaining use case for the positional scheme. We need to invent something to replace it (maybe this should be something as simple as mapping '.' -> '_'). Thoughts?

-Hal

> From: "Tom Stellard" <tom@stellard.net>
> To: "Hal Finkel" <hfinkel@anl.gov>
> Cc: "LLVM Developers Mailing List" <llvmdev@cs.uiuc.edu>
> Sent: Thursday, March 13, 2014 9:46:22 AM
> Subject: Re: [LLVMdev] Be Careful with Positionally-Encoded Operands (AArch64, Mips, AMDGPU, etc.)
>
> > Hello,
> >
> > Some of the backends seem to be combining positional and named
> > operands when defining some instructions such that some of the
> > positional operands overlap with some of the named operands. I
> > suspect this is not intentional; here's an example:
> >
> > AArch64 has the following instruction definition:
> >
> > SMULHxxx {
> > field bits<32> Inst = { 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, Rm{4},
> > Rm{3}, Rm{2}, Rm{1}, Rm{0}, 0, Ra{4}, Ra{3}, Ra{2}, Ra{1},
> > Ra{0}, Rn{4}, Rn{3}, Rn{2}, Rn{1}, Rn{0}, Rd{4}, Rd{3}, Rd{2},
> > Rd{1}, Rd{0} };
> > ...
> > dag OutOperandList = (outs GPR64:$Rd);
> > dag InOperandList = (ins GPR64:$Rn, GPR64:$Rm);
> > string AsmString = "smulh $Rd, $Rn, $Rm";
> > list<dag> Pattern = [(set i64:$Rd, (mulhs i64:$Rn, i64:$Rm))];
> > ...
> > bits<5> Rd = { ?, ?, ?, ?, ? };
> > bits<5> Rn = { ?, ?, ?, ?, ? };
> > bits<5> Rm = { ?, ?, ?, ?, ? };
> > bits<5> Ra = { ?, ?, ?, ?, ? };
> > ...
> > }
> >
> > So how do the operands in OutOperandList and InOperandList get
> > mapped to the variables used to encode the instruction
> > (Rd,Rn,Rm,Ra)? The first three match by name (as they appear
> > explicitly in OutOperandList and InOperandList), but what about
> > Ra? Ra contributes to defining the bits in Inst, and because there
> > is, by default, no overlap checking, it also gets mapped to the
> > first operand: GPR64:$Rd. The result, from
> > AArch64GenMCCodeEmitter.inc is:
> >
> > case AArch64::SMULHxxx:
> > case AArch64::UMULHxxx: {
> > // op: Rd
> > op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
> > Value |= op & UINT64_C(31);
> > // op: Rn
> > op = getMachineOpValue(MI, MI.getOperand(1), Fixups, STI);
> > Value |= (op & UINT64_C(31)) << 5;
> > // op: Rm
> > op = getMachineOpValue(MI, MI.getOperand(2), Fixups, STI);
> > Value |= (op & UINT64_C(31)) << 16;
> > // op: Ra
> > op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
> > Value |= (op & UINT64_C(31)) << 10;
> > Value = fixMulHigh(MI, Value, STI);
> > break;
> > }
> >
> > This may be correct (I have no idea), but even if it is, it seems
> > like an odd way to get this behavior: depending on the fact that,
> > after operands are matched by name, the remaining operands are
> > matched by position such that they might overlap with those
> > operands matched by name.
> >
> > In any case, I believe that the only in-tree target that still
> > really needs the positional operand support is PowerPC (because
> > the named-operand matching scheme still can't deal with the
> > complex operands that PPC uses for handling memory operands), and
> > PowerPC needs the behavior that named and positional operands are
> > disjoint so that we can start transitioning toward using named
> > mapping, so I've added a new TableGen target bit to disable this
> > problematic overlapping operand behavior
> > (noNamedPositionallyEncodedOperands) in r203767.
> >
> > This means that in lib/Target/PowerPC/PPC.td, we have:
> >
> > def PPCInstrInfo : InstrInfo {
> > ...
> >
> > let noNamedPositionallyEncodedOperands = 1;
> >
> > ...
> > }
> >
> > I'd like those maintaining the current backends (especially
> > AArch64, Mips, AMDGPU, which I know to be problematic in this
> > regard) to try setting this and: a) fix those definitions that are
> > problematic or b) explain to me that the current behavior is
> > useful.
> >
>
> Hi Hal,
>
> Thanks for working on this, I have run into several problems with the
> positional encodings and I would be happy to see it go away.
> However,
> I was under the impression that positional encoding was the only way
> to
> encode custom operand types that map to multiple machine operands.
> See for example the MEMxi Operand sub-class in
> R600/R600Instructions.td.

Yes, this is the remaining use case for the positional scheme. We need to invent something to replace it (maybe this should be something as simple as mapping '.' -> '_'). Thoughts?

Do you mean something like this:

def MEMxi : Operand<iPTR> {
  let MIOperandInfo = (ops REG:$ptr, i32imm:$index);
}

def Instr {
let InOperandList = (ins MEMxi:$src);

field bits<32> Inst;
field bits<8> src_ptr; //$src.$ptr
field bits<8> src_index; //$src.$index

let Inst{7-0} = src_ptr;
let Inst{15-8} = src_index;
}

This seems like a good idea to me.

-Tom

From: "Tom Stellard" <tom@stellard.net>
To: "Hal Finkel" <hfinkel@anl.gov>
Cc: "LLVM Developers Mailing List" <llvmdev@cs.uiuc.edu>
Sent: Thursday, March 13, 2014 10:39:48 AM
Subject: Re: [LLVMdev] Be Careful with Positionally-Encoded Operands (AArch64, Mips, AMDGPU, etc.)

> > From: "Tom Stellard" <tom@stellard.net>
> > To: "Hal Finkel" <hfinkel@anl.gov>
> > Cc: "LLVM Developers Mailing List" <llvmdev@cs.uiuc.edu>
> > Sent: Thursday, March 13, 2014 9:46:22 AM
> > Subject: Re: [LLVMdev] Be Careful with Positionally-Encoded
> > Operands (AArch64, Mips, AMDGPU, etc.)
> >
> > > Hello,
> > >
> > > Some of the backends seem to be combining positional and named
> > > operands when defining some instructions such that some of the
> > > positional operands overlap with some of the named operands. I
> > > suspect this is not intentional; here's an example:
> > >
> > > AArch64 has the following instruction definition:
> > >
> > > SMULHxxx {
> > > field bits<32> Inst = { 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0,
> > > Rm{4},
> > > Rm{3}, Rm{2}, Rm{1}, Rm{0}, 0, Ra{4}, Ra{3}, Ra{2}, Ra{1},
> > > Ra{0}, Rn{4}, Rn{3}, Rn{2}, Rn{1}, Rn{0}, Rd{4}, Rd{3},
> > > Rd{2},
> > > Rd{1}, Rd{0} };
> > > ...
> > > dag OutOperandList = (outs GPR64:$Rd);
> > > dag InOperandList = (ins GPR64:$Rn, GPR64:$Rm);
> > > string AsmString = "smulh $Rd, $Rn, $Rm";
> > > list<dag> Pattern = [(set i64:$Rd, (mulhs i64:$Rn,
> > > i64:$Rm))];
> > > ...
> > > bits<5> Rd = { ?, ?, ?, ?, ? };
> > > bits<5> Rn = { ?, ?, ?, ?, ? };
> > > bits<5> Rm = { ?, ?, ?, ?, ? };
> > > bits<5> Ra = { ?, ?, ?, ?, ? };
> > > ...
> > > }
> > >
> > > So how do the operands in OutOperandList and InOperandList get
> > > mapped to the variables used to encode the instruction
> > > (Rd,Rn,Rm,Ra)? The first three match by name (as they appear
> > > explicitly in OutOperandList and InOperandList), but what about
> > > Ra? Ra contributes to defining the bits in Inst, and because
> > > there
> > > is, by default, no overlap checking, it also gets mapped to the
> > > first operand: GPR64:$Rd. The result, from
> > > AArch64GenMCCodeEmitter.inc is:
> > >
> > > case AArch64::SMULHxxx:
> > > case AArch64::UMULHxxx: {
> > > // op: Rd
> > > op = getMachineOpValue(MI, MI.getOperand(0), Fixups,
> > > STI);
> > > Value |= op & UINT64_C(31);
> > > // op: Rn
> > > op = getMachineOpValue(MI, MI.getOperand(1), Fixups,
> > > STI);
> > > Value |= (op & UINT64_C(31)) << 5;
> > > // op: Rm
> > > op = getMachineOpValue(MI, MI.getOperand(2), Fixups,
> > > STI);
> > > Value |= (op & UINT64_C(31)) << 16;
> > > // op: Ra
> > > op = getMachineOpValue(MI, MI.getOperand(0), Fixups,
> > > STI);
> > > Value |= (op & UINT64_C(31)) << 10;
> > > Value = fixMulHigh(MI, Value, STI);
> > > break;
> > > }
> > >
> > > This may be correct (I have no idea), but even if it is, it
> > > seems
> > > like an odd way to get this behavior: depending on the fact
> > > that,
> > > after operands are matched by name, the remaining operands are
> > > matched by position such that they might overlap with those
> > > operands matched by name.
> > >
> > > In any case, I believe that the only in-tree target that still
> > > really needs the positional operand support is PowerPC (because
> > > the named-operand matching scheme still can't deal with the
> > > complex operands that PPC uses for handling memory operands),
> > > and
> > > PowerPC needs the behavior that named and positional operands
> > > are
> > > disjoint so that we can start transitioning toward using named
> > > mapping, so I've added a new TableGen target bit to disable
> > > this
> > > problematic overlapping operand behavior
> > > (noNamedPositionallyEncodedOperands) in r203767.
> > >
> > > This means that in lib/Target/PowerPC/PPC.td, we have:
> > >
> > > def PPCInstrInfo : InstrInfo {
> > > ...
> > >
> > > let noNamedPositionallyEncodedOperands = 1;
> > >
> > > ...
> > > }
> > >
> > > I'd like those maintaining the current backends (especially
> > > AArch64, Mips, AMDGPU, which I know to be problematic in this
> > > regard) to try setting this and: a) fix those definitions that
> > > are
> > > problematic or b) explain to me that the current behavior is
> > > useful.
> > >
> >
> > Hi Hal,
> >
> > Thanks for working on this, I have run into several problems with
> > the
> > positional encodings and I would be happy to see it go away.
> > However,
> > I was under the impression that positional encoding was the only
> > way
> > to
> > encode custom operand types that map to multiple machine
> > operands.
> > See for example the MEMxi Operand sub-class in
> > R600/R600Instructions.td.
>
> Yes, this is the remaining use case for the positional scheme. We
> need to invent something to replace it (maybe this should be
> something as simple as mapping '.' -> '_'). Thoughts?
>

Do you mean something like this:

def MEMxi : Operand<iPTR> {
  let MIOperandInfo = (ops REG:$ptr, i32imm:$index);
}

def Instr {
let InOperandList = (ins MEMxi:$src);

field bits<32> Inst;
field bits<8> src_ptr; //$src.$ptr
field bits<8> src_index; //$src.$index

let Inst{7-0} = src_ptr;
let Inst{15-8} = src_index;
}

This seems like a good idea to me.

Yes, this is what I had in mind. I'll try implementing it next week.

-Hal

From: "Tim Northover" <t.p.northover@gmail.com>
To: "Hal Finkel" <hfinkel@anl.gov>
Cc: "LLVM Developers Mailing List" <llvmdev@cs.uiuc.edu>
Sent: Thursday, March 13, 2014 4:06:49 AM
Subject: Re: [LLVMdev] Be Careful with Positionally-Encoded Operands (AArch64, Mips, AMDGPU, etc.)

Hi Hal,

This sounds like a really good idea in general, but...

> let noNamedPositionallyEncodedOperands = 1;

The diagnostics produced are pretty atrocious (an assertion failure
without even mentioning which instruction is the problem). I couldn't
in good conscience recommend anyone try it in its present state if
there are more than 1-2 problems.

I've fixed this in r204542; TableGen now produces a usable error instead of asserting.

-Hal