| //===-- RISCVLegalizerInfo.cpp ----------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// This file implements the targeting of the Machinelegalizer class for RISC-V. |
| /// \todo This should be generated by TableGen. |
| //===----------------------------------------------------------------------===// |
| |
| #include "RISCVLegalizerInfo.h" |
| #include "RISCVSubtarget.h" |
| #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" |
| #include "llvm/CodeGen/TargetOpcodes.h" |
| #include "llvm/CodeGen/ValueTypes.h" |
| #include "llvm/IR/DerivedTypes.h" |
| #include "llvm/IR/Type.h" |
| |
| using namespace llvm; |
| |
| RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) { |
| const unsigned XLen = ST.getXLen(); |
| const LLT XLenLLT = LLT::scalar(XLen); |
| const LLT DoubleXLenLLT = LLT::scalar(2 * XLen); |
| const LLT p0 = LLT::pointer(0, XLen); |
| const LLT s8 = LLT::scalar(8); |
| const LLT s16 = LLT::scalar(16); |
| const LLT s32 = LLT::scalar(32); |
| |
| using namespace TargetOpcode; |
| |
| getActionDefinitionsBuilder({G_AND, G_OR, G_XOR}) |
| .legalFor({XLenLLT}) |
| .widenScalarToNextPow2(0) |
| .clampScalar(0, XLenLLT, XLenLLT); |
| |
| getActionDefinitionsBuilder({G_ADD, G_SUB}) |
| .legalFor({s32, XLenLLT}) |
| .widenScalarToNextPow2(0) |
| .clampScalar(0, s32, XLenLLT); |
| |
| getActionDefinitionsBuilder( |
| {G_UADDE, G_UADDO, G_USUBE, G_USUBO}).lower(); |
| |
| getActionDefinitionsBuilder({G_SADDO, G_SSUBO}).minScalar(0, XLenLLT).lower(); |
| |
| getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL}) |
| .legalFor({{s32, s32}, {XLenLLT, XLenLLT}}) |
| .widenScalarToNextPow2(0) |
| .clampScalar(1, s32, XLenLLT) |
| .clampScalar(0, s32, XLenLLT); |
| |
| if (ST.is64Bit()) { |
| getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT}) |
| .legalFor({{XLenLLT, s32}}) |
| .maxScalar(0, XLenLLT); |
| |
| getActionDefinitionsBuilder(G_SEXT_INREG) |
| .customFor({XLenLLT}) |
| .maxScalar(0, XLenLLT) |
| .lower(); |
| } else { |
| getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT}) |
| .maxScalar(0, XLenLLT); |
| |
| getActionDefinitionsBuilder(G_SEXT_INREG) |
| .maxScalar(0, XLenLLT) |
| .lower(); |
| } |
| |
| // Merge/Unmerge |
| for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) { |
| unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1; |
| unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0; |
| getActionDefinitionsBuilder(Op) |
| .widenScalarToNextPow2(LitTyIdx, XLen) |
| .widenScalarToNextPow2(BigTyIdx, XLen) |
| .clampScalar(LitTyIdx, XLenLLT, XLenLLT) |
| .clampScalar(BigTyIdx, XLenLLT, XLenLLT); |
| } |
| |
| getActionDefinitionsBuilder({G_CONSTANT, G_IMPLICIT_DEF}) |
| .legalFor({s32, XLenLLT, p0}) |
| .widenScalarToNextPow2(0) |
| .clampScalar(0, s32, XLenLLT); |
| |
| getActionDefinitionsBuilder(G_ICMP) |
| .legalFor({{XLenLLT, XLenLLT}, {XLenLLT, p0}}) |
| .widenScalarToNextPow2(1) |
| .clampScalar(1, XLenLLT, XLenLLT) |
| .clampScalar(0, XLenLLT, XLenLLT); |
| |
| getActionDefinitionsBuilder(G_SELECT) |
| .legalFor({{XLenLLT, XLenLLT}, {p0, XLenLLT}}) |
| .widenScalarToNextPow2(0) |
| .clampScalar(0, XLenLLT, XLenLLT) |
| .clampScalar(1, XLenLLT, XLenLLT); |
| |
| getActionDefinitionsBuilder({G_LOAD, G_STORE}) |
| .legalForTypesWithMemDesc({{s32, p0, s8, 8}, |
| {s32, p0, s16, 16}, |
| {s32, p0, s32, 32}, |
| {XLenLLT, p0, s8, 8}, |
| {XLenLLT, p0, s16, 16}, |
| {XLenLLT, p0, s32, 32}, |
| {XLenLLT, p0, XLenLLT, XLen}, |
| {p0, p0, XLenLLT, XLen}}) |
| .clampScalar(0, s32, XLenLLT) |
| .lower(); |
| |
| auto &ZExtLoadActions = getActionDefinitionsBuilder(G_ZEXTLOAD) |
| .legalForTypesWithMemDesc({{s32, p0, s8, 8}, |
| {s32, p0, s16, 16}, |
| {XLenLLT, p0, s8, 8}, |
| {XLenLLT, p0, s16, 16}}); |
| if (XLen == 64) |
| ZExtLoadActions.legalForTypesWithMemDesc({{XLenLLT, p0, s32, 32}}); |
| ZExtLoadActions.lower(); |
| |
| getActionDefinitionsBuilder(G_PTR_ADD) |
| .legalFor({{p0, XLenLLT}}); |
| |
| getActionDefinitionsBuilder(G_BRCOND) |
| .legalFor({XLenLLT}) |
| .minScalar(0, XLenLLT); |
| |
| getActionDefinitionsBuilder(G_PHI) |
| .legalFor({p0, XLenLLT}) |
| .widenScalarToNextPow2(0) |
| .clampScalar(0, XLenLLT, XLenLLT); |
| |
| getActionDefinitionsBuilder(G_GLOBAL_VALUE) |
| .legalFor({p0}); |
| |
| if (ST.hasStdExtM() || ST.hasStdExtZmmul()) { |
| getActionDefinitionsBuilder(G_MUL) |
| .legalFor({s32, XLenLLT}) |
| .widenScalarToNextPow2(0) |
| .clampScalar(0, s32, XLenLLT); |
| |
| // clang-format off |
| getActionDefinitionsBuilder({G_SMULH, G_UMULH}) |
| .legalFor({XLenLLT}) |
| .lower(); |
| // clang-format on |
| } else { |
| getActionDefinitionsBuilder(G_MUL) |
| .libcallFor({XLenLLT, DoubleXLenLLT}) |
| .widenScalarToNextPow2(0) |
| .clampScalar(0, XLenLLT, DoubleXLenLLT); |
| |
| getActionDefinitionsBuilder({G_SMULH, G_UMULH}).lowerFor({XLenLLT}); |
| } |
| |
| if (ST.hasStdExtM()) { |
| getActionDefinitionsBuilder({G_UDIV, G_SDIV, G_UREM, G_SREM}) |
| .legalFor({s32, XLenLLT}) |
| .libcallFor({DoubleXLenLLT}) |
| .clampScalar(0, s32, DoubleXLenLLT) |
| .widenScalarToNextPow2(0); |
| } else { |
| getActionDefinitionsBuilder({G_UDIV, G_SDIV, G_UREM, G_SREM}) |
| .libcallFor({XLenLLT, DoubleXLenLLT}) |
| .clampScalar(0, XLenLLT, DoubleXLenLLT) |
| .widenScalarToNextPow2(0); |
| } |
| |
| getActionDefinitionsBuilder(G_ABS).lower(); |
| |
| getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0}); |
| |
| getLegacyLegalizerInfo().computeTables(); |
| } |
| |
| bool RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper, |
| MachineInstr &MI) const { |
| switch (MI.getOpcode()) { |
| default: |
| // No idea what to do. |
| return false; |
| case TargetOpcode::G_SEXT_INREG: { |
| // Source size of 32 is sext.w. |
| int64_t SizeInBits = MI.getOperand(2).getImm(); |
| if (SizeInBits == 32) |
| return true; |
| |
| return Helper.lower(MI, 0, /* Unused hint type */ LLT()) == |
| LegalizerHelper::Legalized; |
| } |
| } |
| |
| llvm_unreachable("expected switch to return"); |
| } |