diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 66ed8b078b808..a5153f577ca04 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -157,6 +157,8 @@ class WebAssemblyFastISel final : public FastISel { MachineMemOperand *MMO); unsigned maskI1Value(unsigned Reg, const Value *V); unsigned getRegForI1Value(const Value *V, const BasicBlock *BB, bool &Not); + unsigned truncate(unsigned Reg, const Value *V, MVT::SimpleValueType From, + MVT::SimpleValueType To); unsigned zeroExtendToI32(unsigned Reg, const Value *V, MVT::SimpleValueType From); unsigned signExtendToI32(unsigned Reg, const Value *V, @@ -519,6 +521,28 @@ unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V, return Right; } +unsigned WebAssemblyFastISel::truncate(unsigned Reg, const Value *V, + MVT::SimpleValueType From, + MVT::SimpleValueType To) { + if (From == MVT::i64) { + if (To == MVT::i64) + return copyValue(Reg); + + if (To == MVT::i1 || To == MVT::i8 || To == MVT::i16 || To == MVT::i32) { + Register Result = createResultReg(&WebAssembly::I32RegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, + TII.get(WebAssembly::I32_WRAP_I64), Result) + .addReg(Reg); + return Result; + } + } + + if (From == MVT::i32) + return copyValue(Reg); + + return 0; +} + unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From, MVT::SimpleValueType To) { @@ -988,21 +1012,16 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) { bool WebAssemblyFastISel::selectTrunc(const Instruction *I) { const auto *Trunc = cast(I); - Register Reg = getRegForValue(Trunc->getOperand(0)); + const Value *Op = Trunc->getOperand(0); + MVT::SimpleValueType From = getSimpleType(Op->getType()); + MVT::SimpleValueType To = getLegalType(getSimpleType(Trunc->getType())); + Register In = getRegForValue(Op); + if (In == 0) + return false; + unsigned Reg = truncate(In, Op, From, To); if (Reg == 0) return false; - unsigned FromBitWidth = Trunc->getOperand(0)->getType()->getIntegerBitWidth(); - unsigned ToBitWidth = Trunc->getType()->getIntegerBitWidth(); - - if (ToBitWidth <= 32 && (32 < FromBitWidth && FromBitWidth <= 64)) { - Register Result = createResultReg(&WebAssembly::I32RegClass); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, - TII.get(WebAssembly::I32_WRAP_I64), Result) - .addReg(Reg); - Reg = Result; - } - updateValueMap(Trunc, Reg); return true; } diff --git a/llvm/test/CodeGen/WebAssembly/fast-isel-pr138479.ll b/llvm/test/CodeGen/WebAssembly/fast-isel-pr138479.ll index 2676000b968c3..1eb50d5f9564a 100644 --- a/llvm/test/CodeGen/WebAssembly/fast-isel-pr138479.ll +++ b/llvm/test/CodeGen/WebAssembly/fast-isel-pr138479.ll @@ -1,4 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 -verify-machineinstrs | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=0 -verify-machineinstrs | FileCheck %s target triple = "wasm32-unknown-unknown" @@ -13,3 +14,5 @@ define void @call_trunc_i64_to_i48(i64 %x) { call void @extern48(i48 %x48) ret void } +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CHECK: {{.*}} diff --git a/llvm/test/CodeGen/WebAssembly/fast-isel-simd128.ll b/llvm/test/CodeGen/WebAssembly/fast-isel-simd128.ll new file mode 100644 index 0000000000000..df14e1054d91b --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/fast-isel-simd128.ll @@ -0,0 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -fast-isel -fast-isel-abort=0 -mattr=+simd128 -verify-machineinstrs | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define i8 @pr165438(<4 x i32> %0) { +; CHECK-LABEL: pr165438: +; CHECK: .functype pr165438 (v128) -> (i32) +; CHECK-NEXT: # %bb.0: # %entry +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: i8x16.shuffle 0, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +; CHECK-NEXT: i8x16.extract_lane_u 0 +; CHECK-NEXT: # fallthrough-return +entry: + %conv = trunc <4 x i32> %0 to <4 x i8> + br label %cond.true + + +cond.true: ; preds = %entry + %vecext = extractelement <4 x i8> %conv, i32 0 + ret i8 %vecext +}