[llvm] r246500 - WebAssembly: generate load/store

Alexander Kornienko via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 08:45:07 PDT 2015


On Tue, Sep 1, 2015 at 12:24 AM, JF Bastien via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: jfb
> Date: Mon Aug 31 17:24:11 2015
> New Revision: 246500
>
> URL: http://llvm.org/viewvc/llvm-project?rev=246500&view=rev
> Log:
> WebAssembly: generate load/store
>
> Summary: This handles all load/store operations that WebAssembly defines,
> and handles those necessary for C++ such as i1. I left a FIXME for
> outstanding features which aren't required for now.
>
> Reviewers: sunfish
>
> Subscribers: jfb, llvm-commits, dschuff
>
> Added:
>     llvm/trunk/test/CodeGen/WebAssembly/load-ext.ll
>     llvm/trunk/test/CodeGen/WebAssembly/load-store-i1.ll
>     llvm/trunk/test/CodeGen/WebAssembly/load.ll
>     llvm/trunk/test/CodeGen/WebAssembly/store-trunc.ll
>     llvm/trunk/test/CodeGen/WebAssembly/store.ll
> Modified:
>     llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
>     llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
>     llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
>
> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp?rev=246500&r1=246499&r2=246500&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (original)
> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp Mon Aug 31
> 17:24:11 2015
> @@ -40,6 +40,7 @@ using namespace llvm;
>  namespace {
>
>  class WebAssemblyAsmPrinter final : public AsmPrinter {
> +  bool hasAddr64;
>

This variable can be read without being initialized (fixed in r248388, but
you probably need to look at why is it read before being initialized, what
the right initial value is, etc.).

Also, LLVM naming convention is to start data member names with a capital
character.


>    const WebAssemblyInstrInfo *TII;
>
>  public:
> @@ -60,7 +61,9 @@ private:
>    }
>
>    bool runOnMachineFunction(MachineFunction &MF) override {
> -    TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
> +    const auto &Subtarget = MF.getSubtarget<WebAssemblySubtarget>();
> +    hasAddr64 = Subtarget.hasAddr64();
> +    TII = Subtarget.getInstrInfo();
>      return AsmPrinter::runOnMachineFunction(MF);
>    }
>
> @@ -97,23 +100,6 @@ static SmallString<32> OpcodeName(const
>
>  static std::string toSymbol(StringRef S) { return ("$" + S).str(); }
>
> -static const char *toString(const Type *Ty) {
> -  switch (Ty->getTypeID()) {
> -  default: break;
> -  case Type::FloatTyID:  return "f32";
> -  case Type::DoubleTyID: return "f64";
> -  case Type::IntegerTyID:
> -    switch (Ty->getIntegerBitWidth()) {
> -    case 32: return "i32";
> -    case 64: return "i64";
> -    default: break;
> -    }
> -  }
> -  DEBUG(dbgs() << "Invalid type "; Ty->print(dbgs()); dbgs() << '\n');
> -  llvm_unreachable("invalid type");
> -  return "<invalid>";
> -}
> -
>  static std::string toString(const APFloat &FP) {
>    static const size_t BufBytes = 128;
>    char buf[BufBytes];
> @@ -131,6 +117,28 @@ static std::string toString(const APFloa
>    return buf;
>  }
>
> +static const char *toString(const Type *Ty, bool hasAddr64) {
> +  switch (Ty->getTypeID()) {
> +  default: break;
> +  // Treat all pointers as the underlying integer into linear memory.
> +  case Type::PointerTyID: return hasAddr64 ? "i64" : "i32";
> +  case Type::FloatTyID:  return "f32";
> +  case Type::DoubleTyID: return "f64";
> +  case Type::IntegerTyID:
> +    switch (Ty->getIntegerBitWidth()) {
> +    case 8: return "i8";
> +    case 16: return "i16";
> +    case 32: return "i32";
> +    case 64: return "i64";
> +    default: break;
> +    }
> +  }
> +  DEBUG(dbgs() << "Invalid type "; Ty->print(dbgs()); dbgs() << '\n');
> +  llvm_unreachable("invalid type");
> +  return "<invalid>";
> +}
> +
> +
>
>  //===----------------------------------------------------------------------===//
>  // WebAssemblyAsmPrinter Implementation.
>
>  //===----------------------------------------------------------------------===//
> @@ -186,7 +194,8 @@ void WebAssemblyAsmPrinter::EmitGlobalVa
>      return;
>    }
>
> -  OS << "(global " << toSymbol(Name) << ' ' << toString(Init->getType())
> << ' ';
> +  OS << "(global " << toSymbol(Name) << ' '
> +     << toString(Init->getType(), hasAddr64) << ' ';
>    if (const auto *C = dyn_cast<ConstantInt>(Init)) {
>      assert(C->getBitWidth() <= 64 && "Printing wider types
> unimplemented");
>      OS << C->getZExtValue();
> @@ -228,10 +237,10 @@ void WebAssemblyAsmPrinter::EmitFunction
>    raw_svector_ostream OS(Str);
>    const Function *F = MF->getFunction();
>    for (const Argument &A : F->args())
> -    OS << " (param " << toString(A.getType()) << ')';
> +    OS << " (param " << toString(A.getType(), hasAddr64) << ')';
>    const Type *Rt = F->getReturnType();
>    if (!Rt->isVoidTy())
> -    OS << " (result " << toString(Rt) << ')';
> +    OS << " (result " << toString(Rt, hasAddr64) << ')';
>    OS << '\n';
>    OutStreamer->EmitRawText(OS.str());
>  }
>
> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp?rev=246500&r1=246499&r2=246500&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
> (original)
> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp Mon Aug
> 31 17:24:11 2015
> @@ -113,8 +113,6 @@ WebAssemblyTargetLowering::WebAssemblyTa
>    // Compute derived properties from the register classes.
>    computeRegisterProperties(Subtarget->getRegisterInfo());
>
> -  // FIXME: many setOperationAction are missing...
> -
>    setOperationAction(ISD::GlobalAddress, MVTPtr, Custom);
>
>    for (auto T : {MVT::f32, MVT::f64}) {
> @@ -154,6 +152,16 @@ WebAssemblyTargetLowering::WebAssemblyTa
>    setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
>    setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
>    setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);
> +
> +  // WebAssembly doesn't have:
> +  //  - Floating-point extending loads.
> +  //  - Floating-point truncating stores.
> +  //  - i1 extending loads.
> +  setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f64, Expand);
> +  setTruncStoreAction(MVT::f64, MVT::f32, Expand);
> +  for (auto T : MVT::integer_valuetypes())
> +    for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
> +      setLoadExtAction(Ext, T, MVT::i1, Promote);
>  }
>
>  FastISel *WebAssemblyTargetLowering::createFastISel(
>
> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrMemory.td?rev=246500&r1=246499&r2=246500&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrMemory.td (original)
> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrMemory.td Mon Aug 31
> 17:24:11 2015
> @@ -14,37 +14,84 @@
>
>  /*
>   * TODO(jfb): Add the following.
> - * Each has optional alignment and immediate byte offset.
> - *
> - * int32.load_sx[int8]: sign-extend to int32
> - * int32.load_sx[int16]: sign-extend to int32
> - * int32.load_zx[int8]: zero-extend to int32
> - * int32.load_zx[int16]: zero-extend to int32
> - * int32.load[int32]: (no conversion)
> - * int64.load_sx[int8]: sign-extend to int64
> - * int64.load_sx[int16]: sign-extend to int64
> - * int64.load_sx[int32]: sign-extend to int64
> - * int64.load_zx[int8]: zero-extend to int64
> - * int64.load_zx[int16]: zero-extend to int64
> - * int64.load_zx[int32]: zero-extend to int64
> - * int64.load[int64]: (no conversion)
> - * float32.load[float32]: (no conversion)
> - * float64.load[float64]: (no conversion)
> - *
> - * int32.store[int8]: wrap int32 to int8
> - * int32.store[int16]: wrap int32 to int16
> - * int32.store[int32]: (no conversion)
> - * int64.store[int8]: wrap int64 to int8
> - * int64.store[int16]: wrap int64 to int16
> - * int64.store[int32]: wrap int64 to int32
> - * int64.store[int64]: (no conversion)
> - * float32.store[float32]: (no conversion)
> - * float64.store[float64]: (no conversion)
>   *
>   * load_global: load the value of a given global variable
>   * store_global: store a given value to a given global variable
>   */
>
> +// FIXME:
> +//  - HasAddr64
> +//  - WebAssemblyTargetLowering::isLegalAddressingMode
> +//  - WebAssemblyTargetLowering having to do with atomics
> +//  - Each has optional alignment and immediate byte offset.
> +
> +// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have
> i8/i16
> +// local types. These memory-only types instead zero- or sign-extend into
> local
> +// types when loading, and truncate when storing.
> +
> +// Basic load.
> +def LOAD_I32_ : I<(outs Int32:$dst), (ins Int32:$addr),
> +                  [(set Int32:$dst, (load Int32:$addr))]>;
> +def LOAD_I64_ : I<(outs Int64:$dst), (ins Int32:$addr),
> +                  [(set Int64:$dst, (load Int32:$addr))]>;
> +def LOAD_F32_ : I<(outs Float32:$dst), (ins Int32:$addr),
> +                  [(set Float32:$dst, (load Int32:$addr))]>;
> +def LOAD_F64_ : I<(outs Float64:$dst), (ins Int32:$addr),
> +                  [(set Float64:$dst, (load Int32:$addr))]>;
> +
> +// Extending load.
> +def LOAD_SX_I8_I32_  : I<(outs Int32:$dst), (ins Int32:$addr),
> +                         [(set Int32:$dst, (sextloadi8 Int32:$addr))]>;
> +def LOAD_ZX_I8_I32_  : I<(outs Int32:$dst), (ins Int32:$addr),
> +                         [(set Int32:$dst, (zextloadi8 Int32:$addr))]>;
> +def LOAD_SX_I16_I32_ : I<(outs Int32:$dst), (ins Int32:$addr),
> +                         [(set Int32:$dst, (sextloadi16 Int32:$addr))]>;
> +def LOAD_ZX_I16_I32_ : I<(outs Int32:$dst), (ins Int32:$addr),
> +                         [(set Int32:$dst, (zextloadi16 Int32:$addr))]>;
> +def LOAD_SX_I8_I64_  : I<(outs Int64:$dst), (ins Int32:$addr),
> +                         [(set Int64:$dst, (sextloadi8 Int32:$addr))]>;
> +def LOAD_ZX_I8_I64_  : I<(outs Int64:$dst), (ins Int32:$addr),
> +                         [(set Int64:$dst, (zextloadi8 Int32:$addr))]>;
> +def LOAD_SX_I16_I64_ : I<(outs Int64:$dst), (ins Int32:$addr),
> +                         [(set Int64:$dst, (sextloadi16 Int32:$addr))]>;
> +def LOAD_ZX_I16_I64_ : I<(outs Int64:$dst), (ins Int32:$addr),
> +                         [(set Int64:$dst, (zextloadi16 Int32:$addr))]>;
> +def LOAD_SX_I32_I64_ : I<(outs Int64:$dst), (ins Int32:$addr),
> +                         [(set Int64:$dst, (sextloadi32 Int32:$addr))]>;
> +def LOAD_ZX_I32_I64_ : I<(outs Int64:$dst), (ins Int32:$addr),
> +                         [(set Int64:$dst, (zextloadi32 Int32:$addr))]>;
> +
> +// "Don't care" extending load become zero-extending load.
> +def : Pat<(i32 (extloadi8 Int32:$addr)),  (LOAD_ZX_I8_I32_ $addr)>;
> +def : Pat<(i32 (extloadi16 Int32:$addr)), (LOAD_ZX_I16_I32_ $addr)>;
> +def : Pat<(i64 (extloadi8 Int32:$addr)),  (LOAD_ZX_I8_I64_ $addr)>;
> +def : Pat<(i64 (extloadi16 Int32:$addr)), (LOAD_ZX_I16_I64_ $addr)>;
> +def : Pat<(i64 (extloadi32 Int32:$addr)), (LOAD_ZX_I32_I64_ $addr)>;
> +
> +// Basic store.
> +// Note: WebAssembly inverts SelectionDAG's usual operand order.
> +def STORE_I32_  : I<(outs), (ins Int32:$addr, Int32:$val),
> +                    [(store Int32:$val, Int32:$addr)]>;
> +def STORE_I64_  : I<(outs), (ins Int32:$addr, Int64:$val),
> +                    [(store Int64:$val, Int32:$addr)]>;
> +def STORE_F32_  : I<(outs), (ins Int32:$addr, Float32:$val),
> +                    [(store Float32:$val, Int32:$addr)]>;
> +def STORE_F64_  : I<(outs), (ins Int32:$addr, Float64:$val),
> +                    [(store Float64:$val, Int32:$addr)]>;
> +
> +// Truncating store.
> +def STORE_I8_I32  : I<(outs), (ins Int32:$addr, Int32:$val),
> +                      [(truncstorei8 Int32:$val, Int32:$addr)]>;
> +def STORE_I16_I32 : I<(outs), (ins Int32:$addr, Int32:$val),
> +                      [(truncstorei16 Int32:$val, Int32:$addr)]>;
> +def STORE_I8_I64  : I<(outs), (ins Int32:$addr, Int64:$val),
> +                      [(truncstorei8 Int64:$val, Int32:$addr)]>;
> +def STORE_I16_I64 : I<(outs), (ins Int32:$addr, Int64:$val),
> +                      [(truncstorei16 Int64:$val, Int32:$addr)]>;
> +def STORE_I32_I64 : I<(outs), (ins Int32:$addr, Int64:$val),
> +                      [(truncstorei32 Int64:$val, Int32:$addr)]>;
> +
> +// Page size.
>  def page_size_I32 : I<(outs Int32:$dst), (ins),
>                        [(set Int32:$dst, (int_wasm_page_size))]>,
>                      Requires<[HasAddr32]>;
>
> Added: llvm/trunk/test/CodeGen/WebAssembly/load-ext.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/load-ext.ll?rev=246500&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WebAssembly/load-ext.ll (added)
> +++ llvm/trunk/test/CodeGen/WebAssembly/load-ext.ll Mon Aug 31 17:24:11
> 2015
> @@ -0,0 +1,86 @@
> +; RUN: llc < %s -asm-verbose=false | FileCheck %s
> +
> +; Test that extending loads are assembled properly.
> +
> +target datalayout = "e-p:32:32-i64:64-v128:8:128-n32:64-S128"
> +target triple = "wasm32-unknown-unknown"
> +
> +; CHECK-LABEL: (func $sext_i8_i32
> +; CHECK: (setlocal @1 (load_sx_i8_i32 @0))
> +define i32 @sext_i8_i32(i8 *%p) {
> +  %v = load i8, i8* %p
> +  %e = sext i8 %v to i32
> +  ret i32 %e
> +}
> +
> +; CHECK-LABEL: (func $zext_i8_i32
> +; CHECK: (setlocal @1 (load_zx_i8_i32 @0))
> +define i32 @zext_i8_i32(i8 *%p) {
> +  %v = load i8, i8* %p
> +  %e = zext i8 %v to i32
> +  ret i32 %e
> +}
> +
> +; CHECK-LABEL: (func $sext_i16_i32
> +; CHECK: (setlocal @1 (load_sx_i16_i32 @0))
> +define i32 @sext_i16_i32(i16 *%p) {
> +  %v = load i16, i16* %p
> +  %e = sext i16 %v to i32
> +  ret i32 %e
> +}
> +
> +; CHECK-LABEL: (func $zext_i16_i32
> +; CHECK: (setlocal @1 (load_zx_i16_i32 @0))
> +define i32 @zext_i16_i32(i16 *%p) {
> +  %v = load i16, i16* %p
> +  %e = zext i16 %v to i32
> +  ret i32 %e
> +}
> +
> +; CHECK-LABEL: (func $sext_i8_i64
> +; CHECK: (setlocal @1 (load_sx_i8_i64 @0))
> +define i64 @sext_i8_i64(i8 *%p) {
> +  %v = load i8, i8* %p
> +  %e = sext i8 %v to i64
> +  ret i64 %e
> +}
> +
> +; CHECK-LABEL: (func $zext_i8_i64
> +; CHECK: (setlocal @1 (load_zx_i8_i64 @0))
> +define i64 @zext_i8_i64(i8 *%p) {
> +  %v = load i8, i8* %p
> +  %e = zext i8 %v to i64
> +  ret i64 %e
> +}
> +
> +; CHECK-LABEL: (func $sext_i16_i64
> +; CHECK: (setlocal @1 (load_sx_i16_i64 @0))
> +define i64 @sext_i16_i64(i16 *%p) {
> +  %v = load i16, i16* %p
> +  %e = sext i16 %v to i64
> +  ret i64 %e
> +}
> +
> +; CHECK-LABEL: (func $zext_i16_i64
> +; CHECK: (setlocal @1 (load_zx_i16_i64 @0))
> +define i64 @zext_i16_i64(i16 *%p) {
> +  %v = load i16, i16* %p
> +  %e = zext i16 %v to i64
> +  ret i64 %e
> +}
> +
> +; CHECK-LABEL: (func $sext_i32_i64
> +; CHECK: (setlocal @1 (load_sx_i32_i64 @0))
> +define i64 @sext_i32_i64(i32 *%p) {
> +  %v = load i32, i32* %p
> +  %e = sext i32 %v to i64
> +  ret i64 %e
> +}
> +
> +; CHECK-LABEL: (func $zext_i32_i64
> +; CHECK: (setlocal @1 (load_zx_i32_i64 @0))
> +define i64 @zext_i32_i64(i32 *%p) {
> +  %v = load i32, i32* %p
> +  %e = zext i32 %v to i64
> +  ret i64 %e
> +}
>
> Added: llvm/trunk/test/CodeGen/WebAssembly/load-store-i1.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/load-store-i1.ll?rev=246500&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WebAssembly/load-store-i1.ll (added)
> +++ llvm/trunk/test/CodeGen/WebAssembly/load-store-i1.ll Mon Aug 31
> 17:24:11 2015
> @@ -0,0 +1,68 @@
> +; RUN: llc < %s -asm-verbose=false | FileCheck %s
> +
> +; Test that i1 extending loads and truncating stores are assembled
> properly.
> +
> +target datalayout = "e-p:32:32-i64:64-v128:8:128-n32:64-S128"
> +target triple = "wasm32-unknown-unknown"
> +
> +; CHECK-LABEL: (func $load_unsigned_i1_i32
> +; CHECK:      (setlocal @1 (load_zx_i8_i32 @0))
> +; CHECK-NEXT: (return @1)
> +define i32 @load_unsigned_i1_i32(i1* %p) {
> +  %v = load i1, i1* %p
> +  %e = zext i1 %v to i32
> +  ret i32 %e
> +}
> +
> +; CHECK-LABEL: (func $load_signed_i1_i32
> +; CHECK:      (setlocal @1 (load_zx_i8_i32 @0))
> +; CHECK-NEXT: (setlocal @2 (immediate 31))
> +; CHECK-NEXT: (setlocal @3 (shl @1 @2))
> +; CHECK-NEXT: (setlocal @4 (sar @3 @2))
> +; CHECK-NEXT: (return @4)
> +define i32 @load_signed_i1_i32(i1* %p) {
> +  %v = load i1, i1* %p
> +  %e = sext i1 %v to i32
> +  ret i32 %e
> +}
> +
> +; CHECK-LABEL: (func $load_unsigned_i1_i64
> +; CHECK:      (setlocal @1 (load_zx_i8_i64 @0))
> +; CHECK-NEXT: (return @1)
> +define i64 @load_unsigned_i1_i64(i1* %p) {
> +  %v = load i1, i1* %p
> +  %e = zext i1 %v to i64
> +  ret i64 %e
> +}
> +
> +; CHECK-LABEL: (func $load_signed_i1_i64
> +; CHECK:      (setlocal @1 (load_zx_i8_i64 @0))
> +; CHECK-NEXT: (setlocal @2 (immediate 63))
> +; CHECK-NEXT: (setlocal @3 (shl @1 @2))
> +; CHECK-NEXT: (setlocal @4 (sar @3 @2))
> +; CHECK-NEXT: (return @4)
> +define i64 @load_signed_i1_i64(i1* %p) {
> +  %v = load i1, i1* %p
> +  %e = sext i1 %v to i64
> +  ret i64 %e
> +}
> +
> +; CHECK-LABEL: (func $store_i32_i1
> +; CHECK:      (setlocal @2 (immediate 1))
> +; CHECK-NEXT: (setlocal @3 (and @1 @2))
> +; CHECK-NEXT: (store_i8 @0 @3)
> +define void @store_i32_i1(i1* %p, i32 %v) {
> +  %t = trunc i32 %v to i1
> +  store i1 %t, i1* %p
> +  ret void
> +}
> +
> +; CHECK-LABEL: (func $store_i64_i1
> +; CHECK:      (setlocal @2 (immediate 1))
> +; CHECK-NEXT: (setlocal @3 (and @1 @2))
> +; CHECK-NEXT: (store_i8 @0 @3)
> +define void @store_i64_i1(i1* %p, i64 %v) {
> +  %t = trunc i64 %v to i1
> +  store i1 %t, i1* %p
> +  ret void
> +}
>
> Added: llvm/trunk/test/CodeGen/WebAssembly/load.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/load.ll?rev=246500&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WebAssembly/load.ll (added)
> +++ llvm/trunk/test/CodeGen/WebAssembly/load.ll Mon Aug 31 17:24:11 2015
> @@ -0,0 +1,46 @@
> +; RUN: llc < %s -asm-verbose=false | FileCheck %s
> +
> +; Test that basic loads are assembled properly.
> +
> +target datalayout = "e-p:32:32-i64:64-v128:8:128-n32:64-S128"
> +target triple = "wasm32-unknown-unknown"
> +
> +; CHECK-LABEL: (func $ldi32
> +; CHECK-NEXT: (param i32) (result i32)
> +; CHECK-NEXT: (setlocal @0 (argument 0))
> +; CHECK-NEXT: (setlocal @1 (load_i32 @0))
> +; CHECK-NEXT: (return @1)
> +define i32 @ldi32(i32 *%p) {
> +  %v = load i32, i32* %p
> +  ret i32 %v
> +}
> +
> +; CHECK-LABEL: (func $ldi64
> +; CHECK-NEXT: (param i32) (result i64)
> +; CHECK-NEXT: (setlocal @0 (argument 0))
> +; CHECK-NEXT: (setlocal @1 (load_i64 @0))
> +; CHECK-NEXT: (return @1)
> +define i64 @ldi64(i64 *%p) {
> +  %v = load i64, i64* %p
> +  ret i64 %v
> +}
> +
> +; CHECK-LABEL: (func $ldf32
> +; CHECK-NEXT: (param i32) (result f32)
> +; CHECK-NEXT: (setlocal @0 (argument 0))
> +; CHECK-NEXT: (setlocal @1 (load_f32 @0))
> +; CHECK-NEXT: (return @1)
> +define float @ldf32(float *%p) {
> +  %v = load float, float* %p
> +  ret float %v
> +}
> +
> +; CHECK-LABEL: (func $ldf64
> +; CHECK-NEXT: (param i32) (result f64)
> +; CHECK-NEXT: (setlocal @0 (argument 0))
> +; CHECK-NEXT: (setlocal @1 (load_f64 @0))
> +; CHECK-NEXT: (return @1)
> +define double @ldf64(double *%p) {
> +  %v = load double, double* %p
> +  ret double %v
> +}
>
> Added: llvm/trunk/test/CodeGen/WebAssembly/store-trunc.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/store-trunc.ll?rev=246500&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WebAssembly/store-trunc.ll (added)
> +++ llvm/trunk/test/CodeGen/WebAssembly/store-trunc.ll Mon Aug 31 17:24:11
> 2015
> @@ -0,0 +1,46 @@
> +; RUN: llc < %s -asm-verbose=false | FileCheck %s
> +
> +; Test that truncating stores are assembled properly.
> +
> +target datalayout = "e-p:32:32-i64:64-v128:8:128-n32:64-S128"
> +target triple = "wasm32-unknown-unknown"
> +
> +; CHECK-LABEL: (func $trunc_i8_i32
> +; CHECK: (store_i8 @1 @0)
> +define void @trunc_i8_i32(i8 *%p, i32 %v) {
> +  %t = trunc i32 %v to i8
> +  store i8 %t, i8* %p
> +  ret void
> +}
> +
> +; CHECK-LABEL: (func $trunc_i16_i32
> +; CHECK: (store_i16 @1 @0)
> +define void @trunc_i16_i32(i16 *%p, i32 %v) {
> +  %t = trunc i32 %v to i16
> +  store i16 %t, i16* %p
> +  ret void
> +}
> +
> +; CHECK-LABEL: (func $trunc_i8_i64
> +; CHECK: (store_i8 @1 @0)
> +define void @trunc_i8_i64(i8 *%p, i64 %v) {
> +  %t = trunc i64 %v to i8
> +  store i8 %t, i8* %p
> +  ret void
> +}
> +
> +; CHECK-LABEL: (func $trunc_i16_i64
> +; CHECK: (store_i16 @1 @0)
> +define void @trunc_i16_i64(i16 *%p, i64 %v) {
> +  %t = trunc i64 %v to i16
> +  store i16 %t, i16* %p
> +  ret void
> +}
> +
> +; CHECK-LABEL: (func $trunc_i32_i64
> +; CHECK: (store_i32 @1 @0)
> +define void @trunc_i32_i64(i32 *%p, i64 %v) {
> +  %t = trunc i64 %v to i32
> +  store i32 %t, i32* %p
> +  ret void
> +}
>
> Added: llvm/trunk/test/CodeGen/WebAssembly/store.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/store.ll?rev=246500&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WebAssembly/store.ll (added)
> +++ llvm/trunk/test/CodeGen/WebAssembly/store.ll Mon Aug 31 17:24:11 2015
> @@ -0,0 +1,50 @@
> +; RUN: llc < %s -asm-verbose=false | FileCheck %s
> +
> +; Test that basic stores are assembled properly.
> +
> +target datalayout = "e-p:32:32-i64:64-v128:8:128-n32:64-S128"
> +target triple = "wasm32-unknown-unknown"
> +
> +; CHECK-LABEL: (func $sti32
> +; CHECK-NEXT: (param i32) (param i32)
> +; CHECK-NEXT: (setlocal @0 (argument 1))
> +; CHECK-NEXT: (setlocal @1 (argument 0))
> +; CHECK-NEXT: (store_i32 @1 @0)
> +; CHECK-NEXT: (return)
> +define void @sti32(i32 *%p, i32 %v) {
> +  store i32 %v, i32* %p
> +  ret void
> +}
> +
> +; CHECK-LABEL: (func $sti64
> +; CHECK-NEXT: (param i32) (param i64)
> +; CHECK-NEXT: (setlocal @0 (argument 1))
> +; CHECK-NEXT: (setlocal @1 (argument 0))
> +; CHECK-NEXT: (store_i64 @1 @0)
> +; CHECK-NEXT: (return)
> +define void @sti64(i64 *%p, i64 %v) {
> +  store i64 %v, i64* %p
> +  ret void
> +}
> +
> +; CHECK-LABEL: (func $stf32
> +; CHECK-NEXT: (param i32) (param f32)
> +; CHECK-NEXT: (setlocal @0 (argument 1))
> +; CHECK-NEXT: (setlocal @1 (argument 0))
> +; CHECK-NEXT: (store_f32 @1 @0)
> +; CHECK-NEXT: (return)
> +define void @stf32(float *%p, float %v) {
> +  store float %v, float* %p
> +  ret void
> +}
> +
> +; CHECK-LABEL: (func $stf64
> +; CHECK-NEXT: (param i32) (param f64)
> +; CHECK-NEXT: (setlocal @0 (argument 1))
> +; CHECK-NEXT: (setlocal @1 (argument 0))
> +; CHECK-NEXT: (store_f64 @1 @0)
> +; CHECK-NEXT: (return)
> +define void @stf64(double *%p, double %v) {
> +  store double %v, double* %p
> +  ret void
> +}
>
>
> _______________________________________________
> 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/20150923/e9187201/attachment.html>


More information about the llvm-commits mailing list