[WebAssembly][GlobalISel] G_ADD (and in-reg ext/trunc related) legalization & selection#183694
[WebAssembly][GlobalISel] G_ADD (and in-reg ext/trunc related) legalization & selection#183694QuantumSegfault wants to merge 2 commits intollvm:mainfrom
G_ADD (and in-reg ext/trunc related) legalization & selection#183694Conversation
|
@llvm/pr-subscribers-llvm-globalisel Author: Demetrius Kanios (QuantumSegfault) ChangesThis PR enables The most important change made is getting the boilerplate for RegBankSelect working. Split from #157161. Patch is 28.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/183694.diff 8 Files Affected:
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
index d6eee444af992..01b8b66bfe7b0 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
@@ -48,7 +48,7 @@ class WebAssemblyInstructionSelector : public InstructionSelector {
bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
const WebAssemblyTargetMachine &TM;
- // const WebAssemblySubtarget &STI;
+ const WebAssemblySubtarget &STI;
const WebAssemblyInstrInfo &TII;
const WebAssemblyRegisterInfo &TRI;
const WebAssemblyRegisterBankInfo &RBI;
@@ -71,8 +71,8 @@ class WebAssemblyInstructionSelector : public InstructionSelector {
WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
const WebAssemblyTargetMachine &TM, const WebAssemblySubtarget &STI,
const WebAssemblyRegisterBankInfo &RBI)
- : TM(TM), /*STI(STI),*/ TII(*STI.getInstrInfo()),
- TRI(*STI.getRegisterInfo()), RBI(RBI),
+ : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
+ RBI(RBI),
#define GET_GLOBALISEL_PREDICATES_INIT
#include "WebAssemblyGenGlobalISel.inc"
@@ -84,6 +84,10 @@ WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
}
bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
+ if (!isPreISelGenericOpcode(I.getOpcode())) {
+ 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..10827acb0b16b 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
@@ -13,6 +13,7 @@
#include "WebAssemblyRegisterBankInfo.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "WebAssemblyRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#define GET_TARGET_REGBANK_IMPL
@@ -20,7 +21,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 +62,60 @@ 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;
+ }
+
+ using namespace TargetOpcode;
+
+ const unsigned NumOperands = MI.getNumOperands();
+ const ValueMapping *OperandsMapping = nullptr;
+ unsigned MappingID = DefaultMappingID;
+
+ // Check if LLT sizes match sizes of available register banks.
+ for (const MachineOperand &Op : MI.operands()) {
+ if (Op.isReg()) {
+ 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();
+ }
+ }
+
+ const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
+ unsigned Op0Size = Op0Ty.getSizeInBits();
+
+ auto &Op0IntValueMapping =
+ WebAssembly::ValueMappings[Op0Size == 64 ? WebAssembly::I64Idx
+ : WebAssembly::I32Idx];
+
+ 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)
+ ; CHE...
[truncated]
|
|
@llvm/pr-subscribers-backend-webassembly Author: Demetrius Kanios (QuantumSegfault) ChangesThis PR enables The most important change made is getting the boilerplate for RegBankSelect working. Split from #157161. Patch is 28.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/183694.diff 8 Files Affected:
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
index d6eee444af992..01b8b66bfe7b0 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
@@ -48,7 +48,7 @@ class WebAssemblyInstructionSelector : public InstructionSelector {
bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
const WebAssemblyTargetMachine &TM;
- // const WebAssemblySubtarget &STI;
+ const WebAssemblySubtarget &STI;
const WebAssemblyInstrInfo &TII;
const WebAssemblyRegisterInfo &TRI;
const WebAssemblyRegisterBankInfo &RBI;
@@ -71,8 +71,8 @@ class WebAssemblyInstructionSelector : public InstructionSelector {
WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
const WebAssemblyTargetMachine &TM, const WebAssemblySubtarget &STI,
const WebAssemblyRegisterBankInfo &RBI)
- : TM(TM), /*STI(STI),*/ TII(*STI.getInstrInfo()),
- TRI(*STI.getRegisterInfo()), RBI(RBI),
+ : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
+ RBI(RBI),
#define GET_GLOBALISEL_PREDICATES_INIT
#include "WebAssemblyGenGlobalISel.inc"
@@ -84,6 +84,10 @@ WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
}
bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
+ if (!isPreISelGenericOpcode(I.getOpcode())) {
+ 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..10827acb0b16b 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
@@ -13,6 +13,7 @@
#include "WebAssemblyRegisterBankInfo.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "WebAssemblyRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#define GET_TARGET_REGBANK_IMPL
@@ -20,7 +21,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 +62,60 @@ 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;
+ }
+
+ using namespace TargetOpcode;
+
+ const unsigned NumOperands = MI.getNumOperands();
+ const ValueMapping *OperandsMapping = nullptr;
+ unsigned MappingID = DefaultMappingID;
+
+ // Check if LLT sizes match sizes of available register banks.
+ for (const MachineOperand &Op : MI.operands()) {
+ if (Op.isReg()) {
+ 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();
+ }
+ }
+
+ const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
+ unsigned Op0Size = Op0Ty.getSizeInBits();
+
+ auto &Op0IntValueMapping =
+ WebAssembly::ValueMappings[Op0Size == 64 ? WebAssembly::I64Idx
+ : WebAssembly::I32Idx];
+
+ 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)
+ ; CHE...
[truncated]
|
|
These additions are over 80% test... I've seen regbankselect implemented a couple different ways. I went with something more similar to Mips and RISCV. |
🪟 Windows x64 Test Results
Failed Tests(click on a test name to see its output) LLVMLLVM.ThinLTO/X86/dtlto/imports.llIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
34c6558 to
811bf11
Compare
811bf11 to
f2b76e2
Compare
llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
Outdated
Show resolved
Hide resolved
llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
What's the point of doing this? This code shouldn't really need to defend against illegal types?
There was a problem hiding this comment.
It's a good sanity check. Helps make mistakes in the legalizer (particularly custom lowerings) more evident, rather than letting them past regbankselect (e.g. assigning s8 a i32regbank) and then failing further down the line.
Guard behind #ifndef NDEBUG maybe? Similar to the MF legality checks done before attempting regbankselect?
G_ADD legalization & selectionG_ADD (and in-reg ext/trunc related) legalization & selection
This PR enables
G_ADDand immediate dependencies (relavent ext and trunc related ops) to be fully legalized and selected.The most important change made is getting the boilerplate for RegBankSelect working.
Split from #157161.