[llvm-branch-commits] [llvm] 60653e2 - [WebAssembly] Support select and block for reference types
Heejin Ahn via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Dec 1 19:28:10 PST 2020
Author: Heejin Ahn
Date: 2020-12-01T19:16:57-08:00
New Revision: 60653e24b6297f2830b9de649f575840ecb364b6
URL: https://github.com/llvm/llvm-project/commit/60653e24b6297f2830b9de649f575840ecb364b6
DIFF: https://github.com/llvm/llvm-project/commit/60653e24b6297f2830b9de649f575840ecb364b6.diff
LOG: [WebAssembly] Support select and block for reference types
This adds missing `select` instruction support and block return type
support for reference types. Also refactors WebAssemblyInstrRef.td and
rearranges tests in reference-types.s. Tests don't include `exnref`
types, because we currently don't support `exnref` for `ref.null` and
the type will be removed soon anyway.
Reviewed By: tlively, sbc100, wingo
Differential Revision: https://reviews.llvm.org/D92359
Added:
Modified:
llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
llvm/test/MC/WebAssembly/reference-types.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 2920a49ba944..7426d87ccbc7 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -339,6 +339,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
.Case("f32", WebAssembly::BlockType::F32)
.Case("f64", WebAssembly::BlockType::F64)
.Case("v128", WebAssembly::BlockType::V128)
+ .Case("funcref", WebAssembly::BlockType::Funcref)
+ .Case("externref", WebAssembly::BlockType::Externref)
.Case("exnref", WebAssembly::BlockType::Exnref)
.Case("void", WebAssembly::BlockType::Void)
.Default(WebAssembly::BlockType::Invalid);
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
index 08e5567c4841..658c26ec8e28 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
@@ -147,6 +147,10 @@ wasm::ValType WebAssembly::toValType(const MVT &Ty) {
case MVT::v4f32:
case MVT::v2f64:
return wasm::ValType::V128;
+ case MVT::funcref:
+ return wasm::ValType::FUNCREF;
+ case MVT::externref:
+ return wasm::ValType::EXTERNREF;
case MVT::exnref:
return wasm::ValType::EXNREF;
default:
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
index f97b45095c72..fccee4b96ed5 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
@@ -138,6 +138,8 @@ enum class BlockType : unsigned {
F32 = unsigned(wasm::ValType::F32),
F64 = unsigned(wasm::ValType::F64),
V128 = unsigned(wasm::ValType::V128),
+ Externref = unsigned(wasm::ValType::EXTERNREF),
+ Funcref = unsigned(wasm::ValType::FUNCREF),
Exnref = unsigned(wasm::ValType::EXNREF),
// Multivalue blocks (and other non-void blocks) are only emitted when the
// blocks will never be exited and are at the ends of functions (see
@@ -320,6 +322,10 @@ inline bool isArgument(unsigned Opc) {
case WebAssembly::ARGUMENT_v4f32_S:
case WebAssembly::ARGUMENT_v2f64:
case WebAssembly::ARGUMENT_v2f64_S:
+ case WebAssembly::ARGUMENT_funcref:
+ case WebAssembly::ARGUMENT_funcref_S:
+ case WebAssembly::ARGUMENT_externref:
+ case WebAssembly::ARGUMENT_externref_S:
case WebAssembly::ARGUMENT_exnref:
case WebAssembly::ARGUMENT_exnref_S:
return true;
@@ -340,6 +346,10 @@ inline bool isCopy(unsigned Opc) {
case WebAssembly::COPY_F64_S:
case WebAssembly::COPY_V128:
case WebAssembly::COPY_V128_S:
+ case WebAssembly::COPY_FUNCREF:
+ case WebAssembly::COPY_FUNCREF_S:
+ case WebAssembly::COPY_EXTERNREF:
+ case WebAssembly::COPY_EXTERNREF_S:
case WebAssembly::COPY_EXNREF:
case WebAssembly::COPY_EXNREF_S:
return true;
@@ -360,6 +370,10 @@ inline bool isTee(unsigned Opc) {
case WebAssembly::TEE_F64_S:
case WebAssembly::TEE_V128:
case WebAssembly::TEE_V128_S:
+ case WebAssembly::TEE_FUNCREF:
+ case WebAssembly::TEE_FUNCREF_S:
+ case WebAssembly::TEE_EXTERNREF:
+ case WebAssembly::TEE_EXTERNREF_S:
case WebAssembly::TEE_EXNREF:
case WebAssembly::TEE_EXNREF_S:
return true;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index d5ee4b3b9440..5eafeb70c02a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -773,6 +773,10 @@ static unsigned getCopyOpcode(const TargetRegisterClass *RC) {
return WebAssembly::COPY_F64;
if (RC == &WebAssembly::V128RegClass)
return WebAssembly::COPY_V128;
+ if (RC == &WebAssembly::FUNCREFRegClass)
+ return WebAssembly::COPY_FUNCREF;
+ if (RC == &WebAssembly::EXTERNREFRegClass)
+ return WebAssembly::COPY_EXTERNREF;
if (RC == &WebAssembly::EXNREFRegClass)
return WebAssembly::COPY_EXNREF;
llvm_unreachable("Unexpected register class");
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
index e8367d1d6ec0..2101676906ff 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
@@ -96,6 +96,10 @@ static unsigned getDropOpcode(const TargetRegisterClass *RC) {
return WebAssembly::DROP_F64;
if (RC == &WebAssembly::V128RegClass)
return WebAssembly::DROP_V128;
+ if (RC == &WebAssembly::FUNCREFRegClass)
+ return WebAssembly::DROP_FUNCREF;
+ if (RC == &WebAssembly::EXTERNREFRegClass)
+ return WebAssembly::DROP_EXTERNREF;
if (RC == &WebAssembly::EXNREFRegClass)
return WebAssembly::DROP_EXNREF;
llvm_unreachable("Unexpected register class");
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index 495af21c014d..949564e2d542 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -706,6 +706,14 @@ bool WebAssemblyFastISel::fastLowerArguments() {
Opc = WebAssembly::ARGUMENT_v2f64;
RC = &WebAssembly::V128RegClass;
break;
+ case MVT::funcref:
+ Opc = WebAssembly::ARGUMENT_funcref;
+ RC = &WebAssembly::FUNCREFRegClass;
+ break;
+ case MVT::externref:
+ Opc = WebAssembly::ARGUMENT_externref;
+ RC = &WebAssembly::EXTERNREFRegClass;
+ break;
case MVT::exnref:
Opc = WebAssembly::ARGUMENT_exnref;
RC = &WebAssembly::EXNREFRegClass;
@@ -928,6 +936,14 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
Opc = WebAssembly::SELECT_EXNREF;
RC = &WebAssembly::EXNREFRegClass;
break;
+ case MVT::funcref:
+ Opc = WebAssembly::SELECT_FUNCREF;
+ RC = &WebAssembly::FUNCREFRegClass;
+ break;
+ case MVT::externref:
+ Opc = WebAssembly::SELECT_EXTERNREF;
+ RC = &WebAssembly::EXTERNREFRegClass;
+ break;
default:
return false;
}
@@ -1329,6 +1345,8 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
case MVT::v2i64:
case MVT::v4f32:
case MVT::v2f64:
+ case MVT::funcref:
+ case MVT::externref:
case MVT::exnref:
break;
default:
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
index 6fe1fd2b5c5a..615f182af9bb 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
@@ -76,6 +76,10 @@ void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
CopyOpcode = WebAssembly::COPY_F64;
else if (RC == &WebAssembly::V128RegClass)
CopyOpcode = WebAssembly::COPY_V128;
+ else if (RC == &WebAssembly::FUNCREFRegClass)
+ CopyOpcode = WebAssembly::COPY_FUNCREF;
+ else if (RC == &WebAssembly::EXTERNREFRegClass)
+ CopyOpcode = WebAssembly::COPY_EXTERNREF;
else if (RC == &WebAssembly::EXNREFRegClass)
CopyOpcode = WebAssembly::COPY_EXNREF;
else
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
index 32b0e712f8a6..5c4a9168c932 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
@@ -11,27 +11,30 @@
///
//===----------------------------------------------------------------------===//
-defm SELECT_EXNREF : I<(outs EXNREF:$dst),
- (ins EXNREF:$lhs, EXNREF:$rhs, I32:$cond),
- (outs), (ins),
- [(set EXNREF:$dst,
- (select I32:$cond, EXNREF:$lhs, EXNREF:$rhs))],
- "exnref.select\t$dst, $lhs, $rhs, $cond",
- "exnref.select", 0x1b>;
+multiclass REF_I<WebAssemblyRegClass reg, ValueType vt> {
+ defm REF_NULL_#reg : I<(outs reg:$res), (ins HeapType:$heaptype),
+ (outs), (ins HeapType:$heaptype),
+ [],
+ "ref.null\t$res, $heaptype",
+ "ref.null\t$heaptype",
+ 0xd0>,
+ Requires<[HasReferenceTypes]>;
+ defm SELECT_#reg: I<(outs reg:$dst), (ins reg:$lhs, reg:$rhs, I32:$cond),
+ (outs), (ins),
+ [(set reg:$dst,
+ (select I32:$cond, reg:$lhs, reg:$rhs))],
+ vt#".select\t$dst, $lhs, $rhs, $cond",
+ vt#".select", 0x1b>,
+ Requires<[HasReferenceTypes]>;
+}
-def : Pat<(select (i32 (setne I32:$cond, 0)), EXNREF:$lhs, EXNREF:$rhs),
- (SELECT_EXNREF EXNREF:$lhs, EXNREF:$rhs, I32:$cond)>;
-def : Pat<(select (i32 (seteq I32:$cond, 0)), EXNREF:$lhs, EXNREF:$rhs),
- (SELECT_EXNREF EXNREF:$rhs, EXNREF:$lhs, I32:$cond)>;
+defm "" : REF_I<FUNCREF, funcref>;
+defm "" : REF_I<EXTERNREF, externref>;
+defm "" : REF_I<EXNREF, exnref>;
-multiclass REF<WebAssemblyRegClass rt> {
- defm REF_NULL_#rt : I<(outs rt:$res), (ins HeapType:$heaptype),
- (outs), (ins HeapType:$heaptype),
- [],
- "ref.null\t$res, $heaptype",
- "ref.null\t$heaptype",
- 0xd0>;
+foreach reg = [FUNCREF, EXTERNREF, EXNREF] in {
+def : Pat<(select (i32 (setne I32:$cond, 0)), reg:$lhs, reg:$rhs),
+ (!cast<Instruction>("SELECT_"#reg) reg:$lhs, reg:$rhs, I32:$cond)>;
+def : Pat<(select (i32 (seteq I32:$cond, 0)), reg:$lhs, reg:$rhs),
+ (!cast<Instruction>("SELECT_"#reg) reg:$rhs, reg:$lhs, I32:$cond)>;
}
-
-defm "" : REF<FUNCREF>, Requires<[HasReferenceTypes]>;
-defm "" : REF<EXTERNREF>, Requires<[HasReferenceTypes]>;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
index a587c9d23d2b..35f134e78911 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
@@ -111,6 +111,12 @@ static bool maybeRewriteToFallthrough(MachineInstr &MI, MachineBasicBlock &MBB,
case WebAssembly::V128RegClassID:
CopyLocalOpc = WebAssembly::COPY_V128;
break;
+ case WebAssembly::FUNCREFRegClassID:
+ CopyLocalOpc = WebAssembly::COPY_FUNCREF;
+ break;
+ case WebAssembly::EXTERNREFRegClassID:
+ CopyLocalOpc = WebAssembly::COPY_EXTERNREF;
+ break;
case WebAssembly::EXNREFRegClassID:
CopyLocalOpc = WebAssembly::COPY_EXNREF;
break;
diff --git a/llvm/test/MC/WebAssembly/reference-types.s b/llvm/test/MC/WebAssembly/reference-types.s
index cd4d767a3d96..e2154ec73126 100644
--- a/llvm/test/MC/WebAssembly/reference-types.s
+++ b/llvm/test/MC/WebAssembly/reference-types.s
@@ -1,20 +1,53 @@
# RUN: llvm-mc -show-encoding -triple=wasm32-unknown-unknown -mattr=+reference-types < %s | FileCheck %s
# RUN: llvm-mc -show-encoding -triple=wasm64-unknown-unknown -mattr=+reference-types < %s | FileCheck %s
-# CHECK: ref_null_externref:
-# CHECK-NEXT: .functype ref_null_externref () -> (externref)
-# CHECK: ref.null extern # encoding: [0xd0,0x6f]
-# CHECK-NEXT: end_function
-ref_null_externref:
- .functype ref_null_externref () -> (externref)
+# CHECK-LABEL: ref_null_test:
+# CHECK: ref.null func # encoding: [0xd0,0x70]
+# CHECK: ref.null extern # encoding: [0xd0,0x6f]
+ref_null_test:
+ .functype ref_null_test () -> ()
+ ref.null func
+ drop
ref.null extern
+ drop
+ end_function
+
+# CHECK-LABEL: ref_sig_test_funcref:
+# CHECK-NEXT: .functype ref_sig_test_funcref (funcref) -> (funcref)
+ref_sig_test_funcref:
+ .functype ref_sig_test_funcref (funcref) -> (funcref)
+ end_function
+
+# CHECK-LABEL: ref_sig_test_externref:
+# CHECK-NEXT: .functype ref_sig_test_externref (externref) -> (externref)
+ref_sig_test_externref:
+ .functype ref_sig_test_externref (externref) -> (externref)
end_function
-# CHECK: ref_null_funcref:
-# CHECK-NEXT: .functype ref_null_funcref () -> (funcref)
-# CHECK: ref.null func # encoding: [0xd0,0x70]
-# CHECK-NEXT: end_function
-ref_null_funcref:
- .functype ref_null_funcref () -> (funcref)
+# CHECK-LABEL: ref_select_test:
+# CHECK: funcref.select # encoding: [0x1b]
+# CHECK: externref.select # encoding: [0x1b]
+ref_select_test:
+ .functype ref_select_test () -> ()
ref.null func
+ ref.null func
+ i32.const 0
+ funcref.select
+ drop
+ ref.null extern
+ ref.null extern
+ i32.const 0
+ externref.select
+ drop
+ end_function
+
+# CHECK-LABEL: ref_block_test:
+# CHECK: block funcref
+# CHECK: block externref
+ref_block_test:
+ .functype ref_block_test () -> ()
+ block funcref
+ block externref
+ end_block
+ end_block
end_function
More information about the llvm-branch-commits
mailing list