From c1e866c7f106668016372d945e397d2b003c6c84 Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Wed, 13 Sep 2017 00:29:06 +0000 Subject: [PATCH] [WebAssembly] Add sign extend instructions from atomics proposal Select them from ISD::SIGN_EXTEND_INREG Differential Revision: https://reviews.llvm.org/D37603 remove spurious change git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313101 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../WebAssembly/WebAssemblyISelLowering.cpp | 8 ++- .../WebAssembly/WebAssemblyInstrConv.td | 18 +++++ test/CodeGen/WebAssembly/signext-inreg.ll | 71 +++++++++++++++++++ 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/WebAssembly/signext-inreg.ll diff --git a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 5615ec184d7..91db3da0926 100644 --- a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -115,8 +115,12 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( // As a special case, these operators use the type to mean the type to // sign-extend from. - for (auto T : {MVT::i1, MVT::i8, MVT::i16, MVT::i32}) - setOperationAction(ISD::SIGN_EXTEND_INREG, T, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + if (!Subtarget->hasAtomics()) { + // The Atomics feature includes signext intructions. + for (auto T : {MVT::i8, MVT::i16, MVT::i32}) + setOperationAction(ISD::SIGN_EXTEND_INREG, T, Expand); + } // Dynamic stack allocation: use the default expansion. setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); diff --git a/lib/Target/WebAssembly/WebAssemblyInstrConv.td b/lib/Target/WebAssembly/WebAssemblyInstrConv.td index 29483ba663d..d2decb23e2b 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrConv.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrConv.td @@ -26,6 +26,24 @@ def I64_EXTEND_U_I32 : I<(outs I64:$dst), (ins I32:$src), [(set I64:$dst, (zext I32:$src))], "i64.extend_u/i32\t$dst, $src", 0xad>; +let Predicates = [HasAtomics] in { +def I32_EXTEND8_S_I32 : I<(outs I32:$dst), (ins I32:$src), + [(set I32:$dst, (sext_inreg I32:$src, i8))], + "i32.extend8_s\t$dst, $src", 0xc0>; +def I32_EXTEND16_S_I32 : I<(outs I32:$dst), (ins I32:$src), + [(set I32:$dst, (sext_inreg I32:$src, i16))], + "i32.extend16_s\t$dst, $src", 0xc1>; +def I64_EXTEND8_S_I64 : I<(outs I64:$dst), (ins I64:$src), + [(set I64:$dst, (sext_inreg I64:$src, i8))], + "i64.extend8_s\t$dst, $src", 0xc2>; +def I64_EXTEND16_S_I64 : I<(outs I64:$dst), (ins I64:$src), + [(set I64:$dst, (sext_inreg I64:$src, i16))], + "i64.extend16_s\t$dst, $src", 0xc3>; +def I64_EXTEND32_S_I64 : I<(outs I64:$dst), (ins I64:$src), + [(set I64:$dst, (sext_inreg I64:$src, i32))], + "i64.extend32_s\t$dst, $src", 0xc4>; +} // Predicates = [HasAtomics] + } // defs = [ARGUMENTS] // Expand a "don't care" extend into zero-extend (chosen over sign-extend diff --git a/test/CodeGen/WebAssembly/signext-inreg.ll b/test/CodeGen/WebAssembly/signext-inreg.ll new file mode 100644 index 00000000000..c97a1bf1b0e --- /dev/null +++ b/test/CodeGen/WebAssembly/signext-inreg.ll @@ -0,0 +1,71 @@ +; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s --check-prefix=NOATOMIC + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +; CHECK-LABEL: i32_extend8_s: +; CHECK-NEXT: .param i32{{$}} +; CHECK-NEXT: .result i32{{$}} +; CHECK-NEXT: i32.extend8_s $push[[NUM:[0-9]+]]=, $0{{$}} +; CHECK-NEXT: return $pop[[NUM]]{{$}} + +; NOATOMIC-LABEL: i32_extend8_s +; NOATOMIC-NOT: i32.extend8_s +define i32 @i32_extend8_s(i8 %x) { + %a = sext i8 %x to i32 + ret i32 %a +} + +; CHECK-LABEL: i32_extend16_s: +; CHECK-NEXT: .param i32{{$}} +; CHECK-NEXT: .result i32{{$}} +; CHECK-NEXT: i32.extend16_s $push[[NUM:[0-9]+]]=, $0{{$}} +; CHECK-NEXT: return $pop[[NUM]]{{$}} + +; NOATOMIC-LABEL: i32_extend16_s +; NOATOMIC-NOT: i32.extend16_s +define i32 @i32_extend16_s(i16 %x) { + %a = sext i16 %x to i32 + ret i32 %a +} + +; CHECK-LABEL: i64_extend8_s: +; CHECK-NEXT: .param i32{{$}} +; CHECK-NEXT: .result i64{{$}} +; CHECK-NEXT: i64.extend_u/i32 $push[[NUM1:[0-9]+]]=, $0{{$}} +; CHECK-NEXT: i64.extend8_s $push[[NUM2:[0-9]+]]=, $pop[[NUM1]]{{$}} +; CHECK-NEXT: return $pop[[NUM2]]{{$}} + +; NOATOMIC-LABEL: i64_extend8_s +; NOATOMIC-NOT: i64.extend8_s +define i64 @i64_extend8_s(i8 %x) { + %a = sext i8 %x to i64 + ret i64 %a +} + +; CHECK-LABEL: i64_extend16_s: +; CHECK-NEXT: .param i32{{$}} +; CHECK-NEXT: .result i64{{$}} +; CHECK-NEXT: i64.extend_u/i32 $push[[NUM1:[0-9]+]]=, $0{{$}} +; CHECK-NEXT: i64.extend16_s $push[[NUM2:[0-9]+]]=, $pop[[NUM1]]{{$}} +; CHECK-NEXT: return $pop[[NUM2]]{{$}} + +; NOATOMIC-LABEL: i64_extend16_s +; NOATOMIC-NOT: i16.extend16_s +define i64 @i64_extend16_s(i16 %x) { + %a = sext i16 %x to i64 + ret i64 %a +} + +; No SIGN_EXTEND_INREG is needed for 32->64 extension. +; CHECK-LABEL: i64_extend32_s: +; CHECK-NEXT: .param i32{{$}} +; CHECK-NEXT: .result i64{{$}} +; CHECK-NEXT: i64.extend_s/i32 $push[[NUM:[0-9]+]]=, $0{{$}} +; CHECK-NEXT: return $pop[[NUM]]{{$}} +define i64 @i64_extend32_s(i32 %x) { + %a = sext i32 %x to i64 + ret i64 %a +} + -- 2.40.0