[llvm] r252997 - [WebAssembly] Inline asm support.

Dan Gohman via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 17 12:11:55 PST 2015


asm("" : "=r" (x)) is a convenient way to force a use of x in a register
while introducing minimal disruption, for the purpose of writing a compiler
test. One can create a variety of contrived constraints this way.

Also, inline asm is convenient for writing tests of WebAssembly engines
too, where one wants to craft a very specific code sequence in the middle
of a larger program without having to write the whole function in assembly.

This just adds the "r", " m", and "i" constraints. We won't need a lot more
because the ISA is very regular. Which other tools are you concerned about?

Dan

On Tue, Nov 17, 2015 at 10:46 AM, JF Bastien <jfb at chromium.org> wrote:

> Do you have concrete examples in mind? This was a tad surprising to folks
> here (self included), and I want to make sure that all our tools support
> the same feature set (i.e. we don't end up with the slightly mad situation
> of GCC inline asm).
>
> On Tue, Nov 17, 2015 at 7:09 AM, Dan Gohman <sunfish at mozilla.com> wrote:
>
>> We do have __builtin functions for all instructions not accessible
>> through plain C syntax, so inline asm will almost never be needed. However,
>> inline asm is a useful tool for writing certain kinds of testcases, both
>> for LLVM itself and for the underlying platform.
>>
>> Dan
>>
>>
>> On Mon, Nov 16, 2015 at 4:51 PM, JF Bastien <jfb at chromium.org> wrote:
>>
>>> (catching up on email post-vacation)
>>>
>>> I'm a bit confused about this: the code looks like what I'd expect, but
>>> I thought we weren't going to do inline asm. Could you clarify the usecase?
>>> I thought we'd do calls to the embedders / syscalls through extern C
>>> functions, so I'm not sure I get the use for inline asm.
>>>
>>> On Thu, Nov 12, 2015 at 5:42 PM, Dan Gohman via llvm-commits <
>>> llvm-commits at lists.llvm.org> wrote:
>>>
>>>> Author: djg
>>>> Date: Thu Nov 12 19:42:29 2015
>>>> New Revision: 252997
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=252997&view=rev
>>>> Log:
>>>> [WebAssembly] Inline asm support.
>>>>
>>>> Added:
>>>>     llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll
>>>> Modified:
>>>>     llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
>>>>     llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
>>>>     llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
>>>>     llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h
>>>>
>>>> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp?rev=252997&r1=252996&r2=252997&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
>>>> (original)
>>>> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp Thu Nov
>>>> 12 19:42:29 2015
>>>> @@ -77,6 +77,12 @@ private:
>>>>    void EmitFunctionBodyStart() override;
>>>>    void EmitInstruction(const MachineInstr *MI) override;
>>>>    void EmitEndOfAsmFile(Module &M) override;
>>>> +  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
>>>> +                       unsigned AsmVariant, const char *ExtraCode,
>>>> +                       raw_ostream &OS) override;
>>>> +  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
>>>> +                             unsigned AsmVariant, const char
>>>> *ExtraCode,
>>>> +                             raw_ostream &OS) override;
>>>>
>>>>    std::string getRegTypeName(unsigned RegNo) const;
>>>>    const char *toString(MVT VT) const;
>>>> @@ -275,6 +281,41 @@ void WebAssemblyAsmPrinter::EmitEndOfAsm
>>>>      OutStreamer->EmitRawText(Text.substr(0, Text.size() - 1));
>>>>  }
>>>>
>>>> +bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
>>>> +                                            unsigned OpNo, unsigned
>>>> AsmVariant,
>>>> +                                            const char *ExtraCode,
>>>> +                                            raw_ostream &OS) {
>>>> +  if (AsmVariant != 0)
>>>> +    report_fatal_error("There are no defined alternate asm variants");
>>>> +
>>>> +  if (!ExtraCode) {
>>>> +    const MachineOperand &MO = MI->getOperand(OpNo);
>>>> +    if (MO.isImm())
>>>> +      OS << MO.getImm();
>>>> +    else
>>>> +      OS << regToString(MO);
>>>> +    return false;
>>>> +  }
>>>> +
>>>> +  return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode,
>>>> OS);
>>>> +}
>>>> +
>>>> +bool WebAssemblyAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
>>>> *MI,
>>>> +                                                  unsigned OpNo,
>>>> +                                                  unsigned AsmVariant,
>>>> +                                                  const char
>>>> *ExtraCode,
>>>> +                                                  raw_ostream &OS) {
>>>> +  if (AsmVariant != 0)
>>>> +    report_fatal_error("There are no defined alternate asm variants");
>>>> +
>>>> +  if (!ExtraCode) {
>>>> +    OS << regToString(MI->getOperand(OpNo));
>>>> +    return false;
>>>> +  }
>>>> +
>>>> +  return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, AsmVariant,
>>>> ExtraCode, OS);
>>>> +}
>>>> +
>>>>  // Force static initialization.
>>>>  extern "C" void LLVMInitializeWebAssemblyAsmPrinter() {
>>>>    RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32);
>>>>
>>>> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp?rev=252997&r1=252996&r2=252997&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
>>>> (original)
>>>> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp Thu
>>>> Nov 12 19:42:29 2015
>>>> @@ -56,6 +56,9 @@ public:
>>>>
>>>>    SDNode *Select(SDNode *Node) override;
>>>>
>>>> +  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned
>>>> ConstraintID,
>>>> +                                    std::vector<SDValue> &OutOps)
>>>> override;
>>>> +
>>>>  // Include the pieces autogenerated from the target description.
>>>>  #include "WebAssemblyGenDAGISel.inc"
>>>>
>>>> @@ -101,6 +104,22 @@ SDNode *WebAssemblyDAGToDAGISel::Select(
>>>>    return ResNode;
>>>>  }
>>>>
>>>> +bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
>>>> +    const SDValue &Op, unsigned ConstraintID, std::vector<SDValue>
>>>> &OutOps) {
>>>> +  switch (ConstraintID) {
>>>> +  case InlineAsm::Constraint_i:
>>>> +  case InlineAsm::Constraint_m:
>>>> +    // We just support simple memory operands that just have a single
>>>> address
>>>> +    // operand and need no special handling.
>>>> +    OutOps.push_back(Op);
>>>> +    return false;
>>>> +  default:
>>>> +    break;
>>>> +  }
>>>> +
>>>> +  return true;
>>>> +}
>>>> +
>>>>  /// This pass converts a legalized DAG into a WebAssembly-specific
>>>> DAG, ready
>>>>  /// for instruction scheduling.
>>>>  FunctionPass *llvm::createWebAssemblyISelDag(WebAssemblyTargetMachine
>>>> &TM,
>>>>
>>>> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp?rev=252997&r1=252996&r2=252997&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
>>>> (original)
>>>> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp Thu
>>>> Nov 12 19:42:29 2015
>>>> @@ -211,6 +211,23 @@ WebAssemblyTargetLowering::getTargetNode
>>>>    return nullptr;
>>>>  }
>>>>
>>>> +std::pair<unsigned, const TargetRegisterClass *>
>>>> +WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
>>>> +    const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
>>>> {
>>>> +  // First, see if this is a constraint that directly corresponds to a
>>>> +  // WebAssembly register class.
>>>> +  if (Constraint.size() == 1) {
>>>> +    switch (Constraint[0]) {
>>>> +    case 'r':
>>>> +      return std::make_pair(0U, &WebAssembly::I32RegClass);
>>>> +    default:
>>>> +      break;
>>>> +    }
>>>> +  }
>>>> +
>>>> +  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint,
>>>> VT);
>>>> +}
>>>> +
>>>>
>>>>  //===----------------------------------------------------------------------===//
>>>>  // WebAssembly Lowering private implementation.
>>>>
>>>>  //===----------------------------------------------------------------------===//
>>>>
>>>> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h?rev=252997&r1=252996&r2=252997&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h
>>>> (original)
>>>> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h Thu Nov
>>>> 12 19:42:29 2015
>>>> @@ -49,6 +49,9 @@ private:
>>>>    bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const
>>>> override;
>>>>    MVT getScalarShiftAmountTy(const DataLayout &DL, EVT) const override;
>>>>    const char *getTargetNodeName(unsigned Opcode) const override;
>>>> +  std::pair<unsigned, const TargetRegisterClass *>
>>>> +  getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
>>>> +                               StringRef Constraint, MVT VT) const
>>>> override;
>>>>
>>>>    SDValue LowerCall(CallLoweringInfo &CLI,
>>>>                      SmallVectorImpl<SDValue> &InVals) const override;
>>>>
>>>> Added: llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll?rev=252997&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll (added)
>>>> +++ llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll Thu Nov 12
>>>> 19:42:29 2015
>>>> @@ -0,0 +1,53 @@
>>>> +; RUN: llc < %s -asm-verbose=false | FileCheck %s
>>>> +
>>>> +; Test basic inline assembly.
>>>> +
>>>> +target datalayout = "e-p:32:32-i64:64-n32:64-S128"
>>>> +target triple = "wasm32-unknown-unknown"
>>>> +
>>>> +; CHECK-LABEL: foo:
>>>> +; CHECK-NEXT: .param i32{{$}}
>>>> +; CHECK-NEXT: .result i32{{$}}
>>>> +; CHECK-NEXT: .local i32, i32{{$}}
>>>> +; CHECK-NEXT: #APP{{$}}
>>>> +; CHECK-NEXT: 1 = aaa(0){{$}}
>>>> +; CHECK-NEXT: #NO_APP{{$}}
>>>> +; CHECK-NEXT: return (get_local 1){{$}}
>>>> +define i32 @foo(i32 %r) {
>>>> +entry:
>>>> +  %0 = tail call i32 asm sideeffect "$0 = aaa($1)", "=r,r"(i32 %r) #0,
>>>> !srcloc !0
>>>> +  ret i32 %0
>>>> +}
>>>> +
>>>> +; CHECK-LABEL: bar:
>>>> +; CHECK-NEXT: .param i32{{$}}
>>>> +; CHECK-NEXT: .param i32{{$}}
>>>> +; CHECK-NEXT: .local i32, i32{{$}}
>>>> +; CHECK-NEXT: #APP{{$}}
>>>> +; CHECK-NEXT: 1 = bbb(0){{$}}
>>>> +; CHECK-NEXT: #NO_APP{{$}}
>>>> +; CHECK-NEXT: return{{$}}
>>>> +define void @bar(i32* %r, i32* %s) {
>>>> +entry:
>>>> +  tail call void asm sideeffect "$0 = bbb($1)", "=*m,*m"(i32* %s, i32*
>>>> %r) #0, !srcloc !1
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; CHECK-LABEL: imm:
>>>> +; CHECK-NEXT: .result i32{{$}}
>>>> +; CHECK-NEXT: .local i32{{$}}
>>>> +; CHECK-NEXT: #APP{{$}}
>>>> +; CHECK-NEXT: 0 = ccc(42){{$}}
>>>> +; CHECK-NEXT: #NO_APP{{$}}
>>>> +; CHECK-NEXT: return (get_local 0){{$}}
>>>> +define i32 @imm() {
>>>> +entry:
>>>> +  %0 = tail call i32 asm sideeffect "$0 = ccc($1)", "=r,i"(i32 42) #0,
>>>> !srcloc !2
>>>> +  ret i32 %0
>>>> +}
>>>> +
>>>> +attributes #0 = { nounwind }
>>>> +
>>>> +!0 = !{i32 47}
>>>> +!1 = !{i32 145}
>>>> +!2 = !{i32 231}
>>>>
>>>>
>>>> _______________________________________________
>>>> llvm-commits mailing list
>>>> llvm-commits at lists.llvm.org
>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151117/5c4a5707/attachment.html>


More information about the llvm-commits mailing list