Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
}

bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
if (!I.isPreISelOpcode()) {
return true;
}

if (selectImpl(I, *CoverageInfo))
return true;

Expand Down
19 changes: 19 additions & 0 deletions llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "WebAssemblyLegalizerInfo.h"
#include "WebAssemblySubtarget.h"

#define DEBUG_TYPE "wasm-legalinfo"

Expand All @@ -19,5 +20,23 @@ using namespace LegalizeActions;

WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
const WebAssemblySubtarget &ST) {
using namespace TargetOpcode;

const LLT s32 = LLT::scalar(32);
const LLT s64 = LLT::scalar(64);

getActionDefinitionsBuilder({G_CONSTANT, G_ADD, G_AND})
.legalFor({s32, s64})
.widenScalarToNextPow2(0)
.clampScalar(0, s32, s64);

getActionDefinitionsBuilder({G_ASHR, G_SHL})
.legalFor({{s32, s32}, {s64, s64}})
.widenScalarToNextPow2(0)
.clampScalar(0, s32, s64)
.scalarSameSizeAs(1, 0);

getActionDefinitionsBuilder(G_SEXT_INREG).lower();

getLegacyLegalizerInfo().computeTables();
}
94 changes: 92 additions & 2 deletions llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,47 @@

#include "WebAssemblyRegisterBankInfo.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssemblyRegisterInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"

#define GET_TARGET_REGBANK_IMPL

#include "WebAssemblyGenRegisterBank.inc"

namespace llvm {
namespace WebAssembly {} // namespace WebAssembly
namespace WebAssembly {
enum PartialMappingIdx {
PMI_None = -1,
PMI_I32 = 1,
PMI_I64,
PMI_Min = PMI_I32,
};

enum ValueMappingIdx {
InvalidIdx = 0,
I32Idx = 1,
I64Idx = 5,
};

const RegisterBankInfo::PartialMapping PartMappings[]{{0, 32, I32RegBank},
{0, 64, I64RegBank}};

const RegisterBankInfo::ValueMapping ValueMappings[] = {
// invalid
{nullptr, 0},
// up to 4 operands as I32
{&PartMappings[PMI_I32 - PMI_Min], 1},
{&PartMappings[PMI_I32 - PMI_Min], 1},
{&PartMappings[PMI_I32 - PMI_Min], 1},
{&PartMappings[PMI_I32 - PMI_Min], 1},
// up to 4 operands as I64
{&PartMappings[PMI_I64 - PMI_Min], 1},
{&PartMappings[PMI_I64 - PMI_Min], 1},
{&PartMappings[PMI_I64 - PMI_Min], 1},
{&PartMappings[PMI_I64 - PMI_Min], 1},
};
} // namespace WebAssembly
} // namespace llvm

using namespace llvm;
Expand All @@ -30,5 +63,62 @@ WebAssemblyRegisterBankInfo::WebAssemblyRegisterBankInfo(

const RegisterBankInfo::InstructionMapping &
WebAssemblyRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
return getInvalidInstructionMapping();
unsigned Opc = MI.getOpcode();
const MachineFunction &MF = *MI.getParent()->getParent();
const MachineRegisterInfo &MRI = MF.getRegInfo();

if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) ||
Opc == TargetOpcode::G_PHI) {
const RegisterBankInfo::InstructionMapping &Mapping =
getInstrMappingImpl(MI);
if (Mapping.isValid())
return Mapping;
}

const unsigned NumOperands = MI.getNumOperands();
const ValueMapping *OperandsMapping = nullptr;
unsigned MappingID = DefaultMappingID;

#ifndef NDEBUG
// Check if LLT sizes match sizes of available register banks.
for (const MachineOperand &Op : MI.operands()) {
if (!Op.isReg())
continue;

LLT RegTy = MRI.getType(Op.getReg());

if (RegTy.isScalar() &&
(RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
return getInvalidInstructionMapping();

if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
return getInvalidInstructionMapping();
}
#endif

const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
unsigned Op0Size = Op0Ty.getSizeInBits();

auto &Op0IntValueMapping =
WebAssembly::ValueMappings[Op0Size == 64 ? WebAssembly::I64Idx
: WebAssembly::I32Idx];

using namespace TargetOpcode;
switch (Opc) {
case G_ADD:
case G_AND:
case G_ASHR:
case G_SHL:
OperandsMapping = &Op0IntValueMapping;
break;
case G_CONSTANT:
OperandsMapping = getOperandsMapping({&Op0IntValueMapping, nullptr});
break;
}

if (!OperandsMapping)
return getInvalidInstructionMapping();

return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
NumOperands);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s

---
name: and_i32
alignment: 1
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $arguments

; CHECK-LABEL: name: and_i32
; CHECK: liveins: $arguments
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
; CHECK-NEXT: [[AND_I32_:%[0-9]+]]:i32 = AND_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
; CHECK-NEXT: RETURN [[AND_I32_]], implicit-def $arguments
%0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
%1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
%2:i32regbank(s32) = G_AND %0, %1
RETURN %2(s32), implicit-def $arguments
...

---
name: and_i64
alignment: 1
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $arguments

; CHECK-LABEL: name: and_i64
; CHECK: liveins: $arguments
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
; CHECK-NEXT: [[AND_I64_:%[0-9]+]]:i64 = AND_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
; CHECK-NEXT: RETURN [[AND_I64_]], implicit-def $arguments
%0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
%1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
%2:i64regbank(s64) = G_AND %0, %1
RETURN %2(s64), implicit-def $arguments
...

---
name: shl_i32
alignment: 1
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $arguments

; CHECK-LABEL: name: shl_i32
; CHECK: liveins: $arguments
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
; CHECK-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 5, implicit-def dead $arguments
; CHECK-NEXT: [[SHL_I32_:%[0-9]+]]:i32 = SHL_I32 [[ARGUMENT_i32_]], [[CONST_I32_]], implicit-def dead $arguments
; CHECK-NEXT: RETURN [[SHL_I32_]], implicit-def $arguments
%0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
%1:i32regbank(s32) = G_CONSTANT i32 5
%2:i32regbank(s32) = G_SHL %0, %1
RETURN %2(s32), implicit-def $arguments
...

---
name: shl_i64
alignment: 1
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $arguments

; CHECK-LABEL: name: shl_i64
; CHECK: liveins: $arguments
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
; CHECK-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 37, implicit-def dead $arguments
; CHECK-NEXT: [[SHL_I64_:%[0-9]+]]:i64 = SHL_I64 [[ARGUMENT_i64_]], [[CONST_I64_]], implicit-def dead $arguments
; CHECK-NEXT: RETURN [[SHL_I64_]], implicit-def $arguments
%0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
%1:i64regbank(s64) = G_CONSTANT i64 37
%2:i64regbank(s64) = G_SHL %0, %1
RETURN %2(s64), implicit-def $arguments
...

---
name: ashr_i32
alignment: 1
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $arguments

; CHECK-LABEL: name: ashr_i32
; CHECK: liveins: $arguments
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
; CHECK-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 5, implicit-def dead $arguments
; CHECK-NEXT: [[SHR_S_I32_:%[0-9]+]]:i32 = SHR_S_I32 [[ARGUMENT_i32_]], [[CONST_I32_]], implicit-def dead $arguments
; CHECK-NEXT: RETURN [[SHR_S_I32_]], implicit-def $arguments
%0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
%1:i32regbank(s32) = G_CONSTANT i32 5
%2:i32regbank(s32) = G_ASHR %0, %1
RETURN %2(s32), implicit-def $arguments
...

---
name: ashr_i64
alignment: 1
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $arguments

; CHECK-LABEL: name: ashr_i64
; CHECK: liveins: $arguments
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
; CHECK-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 37, implicit-def dead $arguments
; CHECK-NEXT: [[SHR_S_I64_:%[0-9]+]]:i64 = SHR_S_I64 [[ARGUMENT_i64_]], [[CONST_I64_]], implicit-def dead $arguments
; CHECK-NEXT: RETURN [[SHR_S_I64_]], implicit-def $arguments
%0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
%1:i64regbank(s64) = G_CONSTANT i64 37
%2:i64regbank(s64) = G_ASHR %0, %1
RETURN %2(s64), implicit-def $arguments
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s

---
name: add_i32
alignment: 1
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $arguments

; CHECK-LABEL: name: add_i32
; CHECK: liveins: $arguments
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
; CHECK-NEXT: [[ADD_I32_:%[0-9]+]]:i32 = ADD_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
; CHECK-NEXT: RETURN [[ADD_I32_]], implicit-def $arguments
%0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
%1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
%2:i32regbank(s32) = G_ADD %0, %1
RETURN %2(s32), implicit-def $arguments
...

---
name: add_i64
alignment: 1
legalized: true
regBankSelected: true
tracksRegLiveness: true
body: |
bb.1.entry:
liveins: $arguments

; CHECK-LABEL: name: add_i64
; CHECK: liveins: $arguments
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
; CHECK-NEXT: [[ADD_I64_:%[0-9]+]]:i64 = ADD_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
; CHECK-NEXT: RETURN [[ADD_I64_]], implicit-def $arguments
%0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
%1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
%2:i64regbank(s64) = G_ADD %0, %1
RETURN %2(s64), implicit-def $arguments
...
Loading
Loading