blob: ded0460f97d6fe7289e5f8957d66292699c3e8d2 [file] [log] [blame]
//===-- VE.h - Top-level interface for VE representation --------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file contains the entry points for global functions defined in the LLVM
// VE back-end.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_VE_VE_H
#define LLVM_LIB_TARGET_VE_VE_H
#include "MCTargetDesc/VEMCTargetDesc.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetMachine.h"
namespace llvm {
class AsmPrinter;
class FunctionPass;
class MCInst;
class MachineInstr;
class PassRegistry;
class VETargetMachine;
FunctionPass *createVEISelDag(VETargetMachine &TM);
FunctionPass *createLVLGenPass();
void initializeVEDAGToDAGISelPass(PassRegistry &);
void LowerVEMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP);
} // namespace llvm
namespace llvm {
// Enums corresponding to VE condition codes, both icc's and fcc's. These
// values must be kept in sync with the ones in the .td file.
namespace VECC {
enum CondCode {
// Integer comparison
CC_IG = 0, // Greater
CC_IL = 1, // Less
CC_INE = 2, // Not Equal
CC_IEQ = 3, // Equal
CC_IGE = 4, // Greater or Equal
CC_ILE = 5, // Less or Equal
// Floating point comparison
CC_AF = 0 + 6, // Never
CC_G = 1 + 6, // Greater
CC_L = 2 + 6, // Less
CC_NE = 3 + 6, // Not Equal
CC_EQ = 4 + 6, // Equal
CC_GE = 5 + 6, // Greater or Equal
CC_LE = 6 + 6, // Less or Equal
CC_NUM = 7 + 6, // Number
CC_NAN = 8 + 6, // NaN
CC_GNAN = 9 + 6, // Greater or NaN
CC_LNAN = 10 + 6, // Less or NaN
CC_NENAN = 11 + 6, // Not Equal or NaN
CC_EQNAN = 12 + 6, // Equal or NaN
CC_GENAN = 13 + 6, // Greater or Equal or NaN
CC_LENAN = 14 + 6, // Less or Equal or NaN
CC_AT = 15 + 6, // Always
UNKNOWN
};
}
// Enums corresponding to VE Rounding Mode. These values must be kept in
// sync with the ones in the .td file.
namespace VERD {
enum RoundingMode {
RD_NONE = 0, // According to PSW
RD_RZ = 8, // Round toward Zero
RD_RP = 9, // Round toward Plus infinity
RD_RM = 10, // Round toward Minus infinity
RD_RN = 11, // Round to Nearest (ties to Even)
RD_RA = 12, // Round to Nearest (ties to Away)
UNKNOWN
};
}
inline static const char *VECondCodeToString(VECC::CondCode CC) {
switch (CC) {
case VECC::CC_IG: return "gt";
case VECC::CC_IL: return "lt";
case VECC::CC_INE: return "ne";
case VECC::CC_IEQ: return "eq";
case VECC::CC_IGE: return "ge";
case VECC::CC_ILE: return "le";
case VECC::CC_AF: return "af";
case VECC::CC_G: return "gt";
case VECC::CC_L: return "lt";
case VECC::CC_NE: return "ne";
case VECC::CC_EQ: return "eq";
case VECC::CC_GE: return "ge";
case VECC::CC_LE: return "le";
case VECC::CC_NUM: return "num";
case VECC::CC_NAN: return "nan";
case VECC::CC_GNAN: return "gtnan";
case VECC::CC_LNAN: return "ltnan";
case VECC::CC_NENAN: return "nenan";
case VECC::CC_EQNAN: return "eqnan";
case VECC::CC_GENAN: return "genan";
case VECC::CC_LENAN: return "lenan";
case VECC::CC_AT: return "at";
default:
llvm_unreachable("Invalid cond code");
}
}
inline static VECC::CondCode stringToVEICondCode(StringRef S) {
return StringSwitch<VECC::CondCode>(S)
.Case("gt", VECC::CC_IG)
.Case("lt", VECC::CC_IL)
.Case("ne", VECC::CC_INE)
.Case("eq", VECC::CC_IEQ)
.Case("ge", VECC::CC_IGE)
.Case("le", VECC::CC_ILE)
.Case("af", VECC::CC_AF)
.Case("at", VECC::CC_AT)
.Case("", VECC::CC_AT)
.Default(VECC::UNKNOWN);
}
inline static VECC::CondCode stringToVEFCondCode(StringRef S) {
return StringSwitch<VECC::CondCode>(S)
.Case("gt", VECC::CC_G)
.Case("lt", VECC::CC_L)
.Case("ne", VECC::CC_NE)
.Case("eq", VECC::CC_EQ)
.Case("ge", VECC::CC_GE)
.Case("le", VECC::CC_LE)
.Case("num", VECC::CC_NUM)
.Case("nan", VECC::CC_NAN)
.Case("gtnan", VECC::CC_GNAN)
.Case("ltnan", VECC::CC_LNAN)
.Case("nenan", VECC::CC_NENAN)
.Case("eqnan", VECC::CC_EQNAN)
.Case("genan", VECC::CC_GENAN)
.Case("lenan", VECC::CC_LENAN)
.Case("af", VECC::CC_AF)
.Case("at", VECC::CC_AT)
.Case("", VECC::CC_AT)
.Default(VECC::UNKNOWN);
}
inline static bool isIntVECondCode(VECC::CondCode CC) {
return CC < VECC::CC_AF;
}
inline static unsigned VECondCodeToVal(VECC::CondCode CC) {
switch (CC) {
case VECC::CC_IG:
return 1;
case VECC::CC_IL:
return 2;
case VECC::CC_INE:
return 3;
case VECC::CC_IEQ:
return 4;
case VECC::CC_IGE:
return 5;
case VECC::CC_ILE:
return 6;
case VECC::CC_AF:
return 0;
case VECC::CC_G:
return 1;
case VECC::CC_L:
return 2;
case VECC::CC_NE:
return 3;
case VECC::CC_EQ:
return 4;
case VECC::CC_GE:
return 5;
case VECC::CC_LE:
return 6;
case VECC::CC_NUM:
return 7;
case VECC::CC_NAN:
return 8;
case VECC::CC_GNAN:
return 9;
case VECC::CC_LNAN:
return 10;
case VECC::CC_NENAN:
return 11;
case VECC::CC_EQNAN:
return 12;
case VECC::CC_GENAN:
return 13;
case VECC::CC_LENAN:
return 14;
case VECC::CC_AT:
return 15;
default:
llvm_unreachable("Invalid cond code");
}
}
/// Convert a DAG integer condition code to a VE ICC condition.
inline static VECC::CondCode intCondCode2Icc(ISD::CondCode CC) {
switch (CC) {
default:
llvm_unreachable("Unknown integer condition code!");
case ISD::SETEQ:
return VECC::CC_IEQ;
case ISD::SETNE:
return VECC::CC_INE;
case ISD::SETLT:
return VECC::CC_IL;
case ISD::SETGT:
return VECC::CC_IG;
case ISD::SETLE:
return VECC::CC_ILE;
case ISD::SETGE:
return VECC::CC_IGE;
case ISD::SETULT:
return VECC::CC_IL;
case ISD::SETULE:
return VECC::CC_ILE;
case ISD::SETUGT:
return VECC::CC_IG;
case ISD::SETUGE:
return VECC::CC_IGE;
}
}
/// Convert a DAG floating point condition code to a VE FCC condition.
inline static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC) {
switch (CC) {
default:
llvm_unreachable("Unknown fp condition code!");
case ISD::SETFALSE:
return VECC::CC_AF;
case ISD::SETEQ:
case ISD::SETOEQ:
return VECC::CC_EQ;
case ISD::SETNE:
case ISD::SETONE:
return VECC::CC_NE;
case ISD::SETLT:
case ISD::SETOLT:
return VECC::CC_L;
case ISD::SETGT:
case ISD::SETOGT:
return VECC::CC_G;
case ISD::SETLE:
case ISD::SETOLE:
return VECC::CC_LE;
case ISD::SETGE:
case ISD::SETOGE:
return VECC::CC_GE;
case ISD::SETO:
return VECC::CC_NUM;
case ISD::SETUO:
return VECC::CC_NAN;
case ISD::SETUEQ:
return VECC::CC_EQNAN;
case ISD::SETUNE:
return VECC::CC_NENAN;
case ISD::SETULT:
return VECC::CC_LNAN;
case ISD::SETUGT:
return VECC::CC_GNAN;
case ISD::SETULE:
return VECC::CC_LENAN;
case ISD::SETUGE:
return VECC::CC_GENAN;
case ISD::SETTRUE:
return VECC::CC_AT;
}
}
inline static VECC::CondCode VEValToCondCode(unsigned Val, bool IsInteger) {
if (IsInteger) {
switch (Val) {
case 0:
return VECC::CC_AF;
case 1:
return VECC::CC_IG;
case 2:
return VECC::CC_IL;
case 3:
return VECC::CC_INE;
case 4:
return VECC::CC_IEQ;
case 5:
return VECC::CC_IGE;
case 6:
return VECC::CC_ILE;
case 15:
return VECC::CC_AT;
}
} else {
switch (Val) {
case 0:
return VECC::CC_AF;
case 1:
return VECC::CC_G;
case 2:
return VECC::CC_L;
case 3:
return VECC::CC_NE;
case 4:
return VECC::CC_EQ;
case 5:
return VECC::CC_GE;
case 6:
return VECC::CC_LE;
case 7:
return VECC::CC_NUM;
case 8:
return VECC::CC_NAN;
case 9:
return VECC::CC_GNAN;
case 10:
return VECC::CC_LNAN;
case 11:
return VECC::CC_NENAN;
case 12:
return VECC::CC_EQNAN;
case 13:
return VECC::CC_GENAN;
case 14:
return VECC::CC_LENAN;
case 15:
return VECC::CC_AT;
}
}
llvm_unreachable("Invalid cond code");
}
inline static const char *VERDToString(VERD::RoundingMode R) {
switch (R) {
case VERD::RD_NONE:
return "";
case VERD::RD_RZ:
return ".rz";
case VERD::RD_RP:
return ".rp";
case VERD::RD_RM:
return ".rm";
case VERD::RD_RN:
return ".rn";
case VERD::RD_RA:
return ".ra";
default:
llvm_unreachable("Invalid branch predicate");
}
}
inline static VERD::RoundingMode stringToVERD(StringRef S) {
return StringSwitch<VERD::RoundingMode>(S)
.Case("", VERD::RD_NONE)
.Case(".rz", VERD::RD_RZ)
.Case(".rp", VERD::RD_RP)
.Case(".rm", VERD::RD_RM)
.Case(".rn", VERD::RD_RN)
.Case(".ra", VERD::RD_RA)
.Default(VERD::UNKNOWN);
}
inline static unsigned VERDToVal(VERD::RoundingMode R) {
switch (R) {
case VERD::RD_NONE:
case VERD::RD_RZ:
case VERD::RD_RP:
case VERD::RD_RM:
case VERD::RD_RN:
case VERD::RD_RA:
return static_cast<unsigned>(R);
default:
break;
}
llvm_unreachable("Invalid branch predicates");
}
inline static VERD::RoundingMode VEValToRD(unsigned Val) {
switch (Val) {
case static_cast<unsigned>(VERD::RD_NONE):
return VERD::RD_NONE;
case static_cast<unsigned>(VERD::RD_RZ):
return VERD::RD_RZ;
case static_cast<unsigned>(VERD::RD_RP):
return VERD::RD_RP;
case static_cast<unsigned>(VERD::RD_RM):
return VERD::RD_RM;
case static_cast<unsigned>(VERD::RD_RN):
return VERD::RD_RN;
case static_cast<unsigned>(VERD::RD_RA):
return VERD::RD_RA;
default:
break;
}
llvm_unreachable("Invalid branch predicates");
}
/// getImmVal - get immediate representation of integer value
inline static uint64_t getImmVal(const ConstantSDNode *N) {
return N->getSExtValue();
}
/// getFpImmVal - get immediate representation of floating point value
inline static uint64_t getFpImmVal(const ConstantFPSDNode *N) {
const APInt &Imm = N->getValueAPF().bitcastToAPInt();
uint64_t Val = Imm.getZExtValue();
if (Imm.getBitWidth() == 32) {
// Immediate value of float place places at higher bits on VE.
Val <<= 32;
}
return Val;
}
// MImm - Special immediate value of sequential bit stream of 0 or 1.
// See VEInstrInfo.td for details.
inline static bool isMImmVal(uint64_t Val) {
if (Val == 0) {
// (0)1 is 0
return true;
}
if (isMask_64(Val)) {
// (m)0 patterns
return true;
}
// (m)1 patterns
return (Val & (UINT64_C(1) << 63)) && isShiftedMask_64(Val);
}
inline static bool isMImm32Val(uint32_t Val) {
if (Val == 0) {
// (0)1 is 0
return true;
}
if (isMask_32(Val)) {
// (m)0 patterns
return true;
}
// (m)1 patterns
return (Val & (UINT32_C(1) << 31)) && isShiftedMask_32(Val);
}
/// val2MImm - Convert an integer immediate value to target MImm immediate.
inline static uint64_t val2MImm(uint64_t Val) {
if (Val == 0)
return 0; // (0)1
if (Val & (UINT64_C(1) << 63))
return countLeadingOnes(Val); // (m)1
return countLeadingZeros(Val) | 0x40; // (m)0
}
/// mimm2Val - Convert a target MImm immediate to an integer immediate value.
inline static uint64_t mimm2Val(uint64_t Val) {
if (Val == 0)
return 0; // (0)1
if ((Val & 0x40) == 0)
return (uint64_t)((INT64_C(1) << 63) >> (Val & 0x3f)); // (m)1
return ((uint64_t)INT64_C(-1) >> (Val & 0x3f)); // (m)0
}
inline unsigned M0(unsigned Val) { return Val + 64; }
inline unsigned M1(unsigned Val) { return Val; }
static const unsigned StandardVectorWidth = 256;
static const unsigned PackedVectorWidth = 512;
} // namespace llvm
#endif