memory-to-memory instructions

It appears impossible to match memory-to-memory instructions (except for MOV). The MSP430 supports these. The following test case tries to match the pattern that generates "add.w &foo,&bar":

; RUN: llvm-as < %s | llc -march=msp430 -O3
target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"
target triple = "msp430-generic-generic"
@foo = common global i16 0, align 2
@bar = common global i16 0, align 2
define void @x() nounwind {
  %1 = load i16* @bar
  %2 = load i16* @foo
  %3 = add i16 %2, %1
  store i16 %3, i16* @foo
  ret void
}

In the DAG matching code generated from the .td file there is :

if (N1.getOpcode() == ISD::ADD &&
     N1.hasOneUse()) {
    SDValue N10 = N1.getOperand(0);
    if (N10.getOpcode() == ISD::LOAD &&
        N10.hasOneUse() &&
        IsLegalAndProfitableToFold(N10.getNode(), N1.getNode(), N.getNode()) &&
        (Chain.getNode() == N10.getNode() || IsChainCompatible(Chain.getNode(),
            N10.getNode()))) {
... NEED TO MATCH ABOVE TO GENERATE MEMORY TO MEMORY PATTERN
    }

When debugged we get:
N10.hasOneUse() = 1
IsLegalAndProfitableToFold(N10.getNode(), N1.getNode(), N.getNode()) = 0
(Chain.getNode() == N10.getNode()) = 0
IsChainCompatible(Chain.getNode(), N10.getNode()) = 0

IsLegalAndProfitableToFold() rejects the pattern. (Yes, I had OptLevel > None).

Before I dig further, can anyone answer the question: Does LLVM currently allow a matching a pattern with two loads?

thanks,
bagel

It appears impossible to match memory-to-memory instructions (except for MOV).
The MSP430 supports these. The following test case tries to match the
pattern that generates "add.w &foo,&bar":

; RUN: llvm-as < %s | llc -march=msp430 -O3
target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"
target triple = "msp430-generic-generic"
@foo = common global i16 0, align 2
@bar = common global i16 0, align 2
define void @x() nounwind {
  %1 = load i16* @bar
  %2 = load i16* @foo
  %3 = add i16 %2, %1
  store i16 %3, i16* @foo
  ret void
}

In the DAG matching code generated from the .td file there is :

if (N1.getOpcode() == ISD::ADD &&
    N1.hasOneUse()) {
   SDValue N10 = N1.getOperand(0);
   if (N10.getOpcode() == ISD::LOAD &&
       N10.hasOneUse() &&
       IsLegalAndProfitableToFold(N10.getNode(), N1.getNode(), N.getNode()) &&
       (Chain.getNode() == N10.getNode() || IsChainCompatible(Chain.getNode(),
           N10.getNode()))) {
... NEED TO MATCH ABOVE TO GENERATE MEMORY TO MEMORY PATTERN
   }

When debugged we get:
N10.hasOneUse() = 1
IsLegalAndProfitableToFold(N10.getNode(), N1.getNode(), N.getNode()) = 0
(Chain.getNode() == N10.getNode()) = 0
IsChainCompatible(Chain.getNode(), N10.getNode()) = 0

IsLegalAndProfitableToFold() rejects the pattern. (Yes, I had OptLevel > None).

Before I dig further, can anyone answer the question: Does LLVM currently allow
a matching a pattern with two loads?

The difficulty with matching these kind of patterns is to avoid cyclic dag (tm). IsLegalAndProfitableToFold is probably checking for such possibilities and rejected the match. X86 isel goes to great pain to pre-process the dag to allow (store (op (load))) instructions to match. You can take a look at it.

Evan

I will look at the x86 stuff. However x86 doesn't have instructions that have dags (store (op (load), (load))) of the sort I'm trying to match. So I'm not too hopeful I'll find an easy fix.

thanks,
bagel