Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions llvm/lib/CodeGen/ValueTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,29 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){
default:
if (HandleUnknown) return MVT(MVT::Other);
llvm_unreachable("Unknown type!");
case Type::PointerTyID: {
if (HandleUnknown)
return MVT(MVT::Other);
// A pointer normally cannot be lowered to a value type without a
// DataLayout, so it is an "unknown" type here. The exception is the
// WebAssembly reference types: EVT::getTypeForEVT maps MVT::externref /
// MVT::funcref to opaque pointers in address spaces 10 and 20, and that
// mapping has to be invertible so that DataLayout-free EVT helpers can
// recover the element type of an <N x externref> / <N x funcref> vector
// during type legalization instead of crashing.
//
// Address spaces 10 and 20 are not reserved for WebAssembly, but a target
// only reaches this code with such a pointer if it first produced an
// externref/funcref MVT, which only WebAssembly does.
switch (cast<PointerType>(Ty)->getAddressSpace()) {
case 10:
return MVT(MVT::externref);
case 20:
return MVT(MVT::funcref);
default:
llvm_unreachable("Unknown type!");
}
}
case Type::VoidTyID:
return MVT::isVoid;
case Type::ByteTyID:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
; RUN: opt < %s -passes=slp-vectorizer -mtriple=wasm32-unknown-unknown -S | FileCheck %s

; A WebAssembly reference type cannot be vectorized.
; This used to crash type legalization while the SLP vectorizer was computing
; the cost for a <N x externref> value.

target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-unknown"

%externref = type ptr addrspace(10)

declare %externref @foo()
declare void @bar(%externref)

; Two externref phis that feed two calls are candidates for being gathered into
; a vector but they must be left scalar. Derived the following C code:
;
; __externref_t foo(void);
; void bar(__externref_t);
; void test(int flag, __externref_t ref1, __externref_t ref2) {
; if (flag) {
; ref1 = foo();
; ref2 = foo();
; }
; bar(ref1); bar(ref2);
; }
;
; CHECK-LABEL: @test(
; CHECK-NOT: phi <{{.*}} x ptr addrspace(10)>
; CHECK-NOT: call void @bar(<{{.*}} x ptr addrspace(10)>
; CHECK: ret void
define void @test(i32 %flag, %externref %ref1, %externref %ref2) {
entry:
%c = icmp eq i32 %flag, 0
br i1 %c, label %join, label %then

then:
%a = tail call %externref @foo()
%b = tail call %externref @foo()
br label %join

join:
%p1 = phi %externref [ %a, %then ], [ %ref1, %entry ]
%p2 = phi %externref [ %b, %then ], [ %ref2, %entry ]
tail call void @bar(%externref %p1)
tail call void @bar(%externref %p2)
ret void
}