diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp index d6eee444af992..463d3977c329d 100644 --- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp +++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp @@ -84,6 +84,10 @@ WebAssemblyInstructionSelector::WebAssemblyInstructionSelector( } bool WebAssemblyInstructionSelector::select(MachineInstr &I) { + if (!I.isPreISelOpcode()) { + return true; + } + if (selectImpl(I, *CoverageInfo)) return true; diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp index 82b8a48266e31..ecbaf79db751d 100644 --- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp +++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "WebAssemblyLegalizerInfo.h" +#include "WebAssemblySubtarget.h" #define DEBUG_TYPE "wasm-legalinfo" @@ -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(); } diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp index ff0bc298dc1da..e5fd8338c873a 100644 --- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp +++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp @@ -13,6 +13,8 @@ #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 @@ -20,7 +22,38 @@ #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; @@ -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); } diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir new file mode 100644 index 0000000000000..c1c111606d15f --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir @@ -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 +... diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/int-arithmetic.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/int-arithmetic.mir new file mode 100644 index 0000000000000..60c916c372636 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/int-arithmetic.mir @@ -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 +... diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/add.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/add.mir new file mode 100644 index 0000000000000..0d12b749e461e --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/add.mir @@ -0,0 +1,200 @@ +# 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=legalizer -verify-machineinstrs %s -o - | FileCheck %s + +--- +name: add_i8_zext +alignment: 1 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: add_i8_zext + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; CHECK-NEXT: [[AND:%[0-9]+]]:i32(s32) = G_AND [[ADD]], [[C]] + ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments + %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %0:_(s8) = G_TRUNC %2(s32) + %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %1:_(s8) = G_TRUNC %3(s32) + %4:_(s8) = G_ADD %0, %1 + %5:i32(s32) = G_ZEXT %4(s8) + RETURN %5(s32), implicit-def $arguments +... + +--- +name: add_i8_sext +alignment: 1 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: add_i8_sext + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD]], [[C]](s32) + ; CHECK-NEXT: [[ASHR:%[0-9]+]]:i32(s32) = G_ASHR [[SHL]], [[C]](s32) + ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments + %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %0:_(s8) = G_TRUNC %2(s32) + %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %1:_(s8) = G_TRUNC %3(s32) + %4:_(s8) = G_ADD %0, %1 + %5:i32(s32) = G_SEXT %4(s8) + RETURN %5(s32), implicit-def $arguments +... + +--- +name: add_i8_aext +alignment: 1 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: add_i8_aext + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments + %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %0:_(s8) = G_TRUNC %2(s32) + %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %1:_(s8) = G_TRUNC %3(s32) + %4:_(s8) = G_ADD %0, %1 + %5:i32(s32) = G_ANYEXT %4(s8) + RETURN %5(s32), implicit-def $arguments +... + +--- +name: add_i16_zext +alignment: 1 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: add_i16_zext + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; CHECK-NEXT: [[AND:%[0-9]+]]:i32(s32) = G_AND [[ADD]], [[C]] + ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments + %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %0:_(s16) = G_TRUNC %2(s32) + %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %1:_(s16) = G_TRUNC %3(s32) + %4:_(s16) = G_ADD %0, %1 + %5:i32(s32) = G_ZEXT %4(s16) + RETURN %5(s32), implicit-def $arguments +... + +--- +name: add_i16_sext +alignment: 1 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: add_i16_sext + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD]], [[C]](s32) + ; CHECK-NEXT: [[ASHR:%[0-9]+]]:i32(s32) = G_ASHR [[SHL]], [[C]](s32) + ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments + %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %0:_(s16) = G_TRUNC %2(s32) + %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %1:_(s16) = G_TRUNC %3(s32) + %4:_(s16) = G_ADD %0, %1 + %5:i32(s32) = G_SEXT %4(s16) + RETURN %5(s32), implicit-def $arguments +... + +--- +name: add_i16_aext +alignment: 1 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: add_i16_aext + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments + %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %0:_(s16) = G_TRUNC %2(s32) + %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %1:_(s16) = G_TRUNC %3(s32) + %4:_(s16) = G_ADD %0, %1 + %5:i32(s32) = G_ANYEXT %4(s16) + RETURN %5(s32), implicit-def $arguments +... + +--- +name: add_i32 +alignment: 1 +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(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: RETURN [[ADD]](s32), implicit-def $arguments + %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %2:_(s32) = G_ADD %0, %1 + RETURN %2(s32), implicit-def $arguments +... + +--- +name: add_i64 +alignment: 1 +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(s64) = ARGUMENT_i64 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]] + ; CHECK-NEXT: RETURN [[ADD]](s64), implicit-def $arguments + %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments + %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments + %2:_(s64) = G_ADD %0, %1 + RETURN %2(s64), implicit-def $arguments +... diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir new file mode 100644 index 0000000000000..157ef5b9034c2 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir @@ -0,0 +1,134 @@ +# 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=regbankselect -verify-machineinstrs %s -o - | FileCheck %s + +--- +name: and_i32 +alignment: 1 +legalized: 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(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[AND:%[0-9]+]]:i32regbank(s32) = G_AND [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments + %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %2:_(s32) = G_AND %0, %1 + RETURN %2(s32), implicit-def $arguments +... + +--- +name: and_i64 +alignment: 1 +legalized: 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(s64) = ARGUMENT_i64 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments + ; CHECK-NEXT: [[AND:%[0-9]+]]:i64regbank(s64) = G_AND [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]] + ; CHECK-NEXT: RETURN [[AND]](s64), implicit-def $arguments + %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments + %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments + %2:_(s64) = G_AND %0, %1 + RETURN %2(s64), implicit-def $arguments +... + +--- +name: shl_i32 +alignment: 1 +legalized: 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(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[C:%[0-9]+]]:i32regbank(s32) = G_CONSTANT i32 5 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:i32regbank(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32) + ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments + %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %1:_(s32) = G_CONSTANT i32 5 + %2:_(s32) = G_SHL %0, %1 + RETURN %2(s32), implicit-def $arguments +... + +--- +name: shl_i64 +alignment: 1 +legalized: 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(s64) = ARGUMENT_i64 0, implicit $arguments + ; CHECK-NEXT: [[C:%[0-9]+]]:i64regbank(s64) = G_CONSTANT i64 37 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:i64regbank(s64) = G_SHL [[ARGUMENT_i64_]], [[C]](s64) + ; CHECK-NEXT: RETURN [[SHL]](s64), implicit-def $arguments + %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments + %1:_(s64) = G_CONSTANT i64 37 + %2:_(s64) = G_SHL %0, %1 + RETURN %2(s64), implicit-def $arguments +... + +--- +name: ashr_i32 +alignment: 1 +legalized: 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(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[C:%[0-9]+]]:i32regbank(s32) = G_CONSTANT i32 5 + ; CHECK-NEXT: [[ASHR:%[0-9]+]]:i32regbank(s32) = G_ASHR [[ARGUMENT_i32_]], [[C]](s32) + ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments + %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %1:_(s32) = G_CONSTANT i32 5 + %2:_(s32) = G_ASHR %0, %1 + RETURN %2(s32), implicit-def $arguments +... + +--- +name: ashr_i64 +alignment: 1 +legalized: 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(s64) = ARGUMENT_i64 0, implicit $arguments + ; CHECK-NEXT: [[C:%[0-9]+]]:i64regbank(s64) = G_CONSTANT i64 37 + ; CHECK-NEXT: [[ASHR:%[0-9]+]]:i64regbank(s64) = G_ASHR [[ARGUMENT_i64_]], [[C]](s64) + ; CHECK-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments + %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments + %1:_(s64) = G_CONSTANT i64 37 + %2:_(s64) = G_ASHR %0, %1 + RETURN %2(s64), implicit-def $arguments +... diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/int-arithmetic.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/int-arithmetic.mir new file mode 100644 index 0000000000000..1a2515d4b9abe --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/int-arithmetic.mir @@ -0,0 +1,46 @@ +# 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=regbankselect -verify-machineinstrs %s -o - | FileCheck %s + +--- +name: add_i32 +alignment: 1 +legalized: 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(s32) = ARGUMENT_i32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:i32regbank(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]] + ; CHECK-NEXT: RETURN [[ADD]](s32), implicit-def $arguments + %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments + %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments + %2:_(s32) = G_ADD %0, %1 + RETURN %2(s32), implicit-def $arguments +... + +--- +name: add_i64 +alignment: 1 +legalized: 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(s64) = ARGUMENT_i64 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments + ; CHECK-NEXT: [[ADD:%[0-9]+]]:i64regbank(s64) = G_ADD [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]] + ; CHECK-NEXT: RETURN [[ADD]](s64), implicit-def $arguments + %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments + %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments + %2:_(s64) = G_ADD %0, %1 + RETURN %2(s64), implicit-def $arguments +...