2008-01-06 09:35:39 +08:00
|
|
|
//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
|
2005-04-22 08:00:37 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2005-04-22 08:00:37 +08:00
|
|
|
//
|
2003-10-21 04:20:30 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2003-10-06 03:27:59 +08:00
|
|
|
//
|
2008-01-06 09:35:39 +08:00
|
|
|
// This class wraps target description classes used by the various code
|
2003-10-06 03:27:59 +08:00
|
|
|
// generation TableGen backends. This makes it easier to access the data and
|
|
|
|
// provides a single place that needs to check it for validity. All of these
|
2012-10-26 04:33:17 +08:00
|
|
|
// classes abort on error conditions.
|
2003-10-06 03:27:59 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2004-08-01 12:04:35 +08:00
|
|
|
#include "CodeGenTarget.h"
|
2017-12-21 03:36:28 +08:00
|
|
|
#include "CodeGenDAGPatterns.h"
|
2006-03-25 03:49:31 +08:00
|
|
|
#include "CodeGenIntrinsics.h"
|
2012-07-07 12:00:00 +08:00
|
|
|
#include "CodeGenSchedule.h"
|
2010-03-28 04:32:26 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2012-12-04 18:37:14 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2004-10-04 03:34:31 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2019-02-12 07:02:02 +08:00
|
|
|
#include "llvm/Support/Timer.h"
|
2012-12-04 18:37:14 +08:00
|
|
|
#include "llvm/TableGen/Error.h"
|
|
|
|
#include "llvm/TableGen/Record.h"
|
2019-02-12 07:02:02 +08:00
|
|
|
#include "llvm/TableGen/TableGenBackend.h"
|
2005-10-14 11:54:49 +08:00
|
|
|
#include <algorithm>
|
2004-08-01 11:55:39 +08:00
|
|
|
using namespace llvm;
|
2003-11-12 06:41:34 +08:00
|
|
|
|
2017-03-27 21:15:13 +08:00
|
|
|
cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
|
|
|
|
cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
|
|
|
|
|
2009-07-29 08:02:19 +08:00
|
|
|
static cl::opt<unsigned>
|
2017-03-27 21:15:13 +08:00
|
|
|
AsmParserNum("asmparsernum", cl::init(0),
|
|
|
|
cl::desc("Make -gen-asm-parser emit assembly parser #N"),
|
|
|
|
cl::cat(AsmParserCat));
|
2009-07-29 08:02:19 +08:00
|
|
|
|
2004-10-04 03:34:31 +08:00
|
|
|
static cl::opt<unsigned>
|
2017-03-27 21:15:13 +08:00
|
|
|
AsmWriterNum("asmwriternum", cl::init(0),
|
|
|
|
cl::desc("Make -gen-asm-writer emit assembly writer #N"),
|
|
|
|
cl::cat(AsmWriterCat));
|
2004-10-04 03:34:31 +08:00
|
|
|
|
2009-08-12 04:47:22 +08:00
|
|
|
/// getValueType - Return the MVT::SimpleValueType that the specified TableGen
|
2008-06-06 20:08:01 +08:00
|
|
|
/// record corresponds to.
|
2009-08-12 04:47:22 +08:00
|
|
|
MVT::SimpleValueType llvm::getValueType(Record *Rec) {
|
|
|
|
return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
|
2003-10-06 03:27:59 +08:00
|
|
|
}
|
|
|
|
|
2016-05-26 02:07:40 +08:00
|
|
|
StringRef llvm::getName(MVT::SimpleValueType T) {
|
2003-10-06 03:27:59 +08:00
|
|
|
switch (T) {
|
2009-08-12 04:47:22 +08:00
|
|
|
case MVT::Other: return "UNKNOWN";
|
|
|
|
case MVT::iPTR: return "TLI.getPointerTy()";
|
|
|
|
case MVT::iPTRAny: return "TLI.getPointerTy()";
|
2009-07-11 06:25:24 +08:00
|
|
|
default: return getEnumName(T);
|
2003-10-06 03:27:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-26 02:07:40 +08:00
|
|
|
StringRef llvm::getEnumName(MVT::SimpleValueType T) {
|
2003-10-06 03:27:59 +08:00
|
|
|
switch (T) {
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::Other: return "MVT::Other";
|
|
|
|
case MVT::i1: return "MVT::i1";
|
|
|
|
case MVT::i8: return "MVT::i8";
|
|
|
|
case MVT::i16: return "MVT::i16";
|
|
|
|
case MVT::i32: return "MVT::i32";
|
|
|
|
case MVT::i64: return "MVT::i64";
|
|
|
|
case MVT::i128: return "MVT::i128";
|
2015-01-23 04:14:38 +08:00
|
|
|
case MVT::Any: return "MVT::Any";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::iAny: return "MVT::iAny";
|
|
|
|
case MVT::fAny: return "MVT::fAny";
|
|
|
|
case MVT::vAny: return "MVT::vAny";
|
2011-12-20 08:02:33 +08:00
|
|
|
case MVT::f16: return "MVT::f16";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::f32: return "MVT::f32";
|
|
|
|
case MVT::f64: return "MVT::f64";
|
|
|
|
case MVT::f80: return "MVT::f80";
|
|
|
|
case MVT::f128: return "MVT::f128";
|
2009-08-12 04:47:22 +08:00
|
|
|
case MVT::ppcf128: return "MVT::ppcf128";
|
2010-09-08 04:03:56 +08:00
|
|
|
case MVT::x86mmx: return "MVT::x86mmx";
|
2010-12-21 10:38:05 +08:00
|
|
|
case MVT::Glue: return "MVT::Glue";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::isVoid: return "MVT::isVoid";
|
2017-05-18 19:29:41 +08:00
|
|
|
case MVT::v1i1: return "MVT::v1i1";
|
2012-09-20 06:47:07 +08:00
|
|
|
case MVT::v2i1: return "MVT::v2i1";
|
|
|
|
case MVT::v4i1: return "MVT::v4i1";
|
|
|
|
case MVT::v8i1: return "MVT::v8i1";
|
|
|
|
case MVT::v16i1: return "MVT::v16i1";
|
2012-12-24 18:03:57 +08:00
|
|
|
case MVT::v32i1: return "MVT::v32i1";
|
|
|
|
case MVT::v64i1: return "MVT::v64i1";
|
2017-12-15 03:05:21 +08:00
|
|
|
case MVT::v128i1: return "MVT::v128i1";
|
2015-11-24 23:50:22 +08:00
|
|
|
case MVT::v512i1: return "MVT::v512i1";
|
|
|
|
case MVT::v1024i1: return "MVT::v1024i1";
|
2013-09-24 10:47:27 +08:00
|
|
|
case MVT::v1i8: return "MVT::v1i8";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v2i8: return "MVT::v2i8";
|
|
|
|
case MVT::v4i8: return "MVT::v4i8";
|
|
|
|
case MVT::v8i8: return "MVT::v8i8";
|
|
|
|
case MVT::v16i8: return "MVT::v16i8";
|
|
|
|
case MVT::v32i8: return "MVT::v32i8";
|
2012-12-24 18:03:57 +08:00
|
|
|
case MVT::v64i8: return "MVT::v64i8";
|
2015-11-24 23:50:22 +08:00
|
|
|
case MVT::v128i8: return "MVT::v128i8";
|
|
|
|
case MVT::v256i8: return "MVT::v256i8";
|
2012-09-20 06:47:07 +08:00
|
|
|
case MVT::v1i16: return "MVT::v1i16";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v2i16: return "MVT::v2i16";
|
2019-08-16 02:58:25 +08:00
|
|
|
case MVT::v3i16: return "MVT::v3i16";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v4i16: return "MVT::v4i16";
|
|
|
|
case MVT::v8i16: return "MVT::v8i16";
|
|
|
|
case MVT::v16i16: return "MVT::v16i16";
|
2012-12-24 18:03:57 +08:00
|
|
|
case MVT::v32i16: return "MVT::v32i16";
|
2015-11-24 23:50:22 +08:00
|
|
|
case MVT::v64i16: return "MVT::v64i16";
|
|
|
|
case MVT::v128i16: return "MVT::v128i16";
|
2012-09-20 06:47:07 +08:00
|
|
|
case MVT::v1i32: return "MVT::v1i32";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v2i32: return "MVT::v2i32";
|
2019-03-18 06:56:38 +08:00
|
|
|
case MVT::v3i32: return "MVT::v3i32";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v4i32: return "MVT::v4i32";
|
2019-03-18 06:56:38 +08:00
|
|
|
case MVT::v5i32: return "MVT::v5i32";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v8i32: return "MVT::v8i32";
|
2012-09-20 06:47:07 +08:00
|
|
|
case MVT::v16i32: return "MVT::v16i32";
|
2015-11-24 23:50:22 +08:00
|
|
|
case MVT::v32i32: return "MVT::v32i32";
|
|
|
|
case MVT::v64i32: return "MVT::v64i32";
|
2019-07-07 12:47:37 +08:00
|
|
|
case MVT::v128i32: return "MVT::v128i32";
|
|
|
|
case MVT::v256i32: return "MVT::v256i32";
|
|
|
|
case MVT::v512i32: return "MVT::v512i32";
|
|
|
|
case MVT::v1024i32: return "MVT::v1024i32";
|
|
|
|
case MVT::v2048i32: return "MVT::v2048i32";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v1i64: return "MVT::v1i64";
|
|
|
|
case MVT::v2i64: return "MVT::v2i64";
|
|
|
|
case MVT::v4i64: return "MVT::v4i64";
|
|
|
|
case MVT::v8i64: return "MVT::v8i64";
|
2012-09-20 06:47:07 +08:00
|
|
|
case MVT::v16i64: return "MVT::v16i64";
|
2015-11-24 23:50:22 +08:00
|
|
|
case MVT::v32i64: return "MVT::v32i64";
|
2015-04-18 00:11:05 +08:00
|
|
|
case MVT::v1i128: return "MVT::v1i128";
|
2012-01-13 07:14:13 +08:00
|
|
|
case MVT::v2f16: return "MVT::v2f16";
|
2019-08-16 02:58:25 +08:00
|
|
|
case MVT::v3f16: return "MVT::v3f16";
|
2013-10-03 11:29:21 +08:00
|
|
|
case MVT::v4f16: return "MVT::v4f16";
|
2013-08-14 06:34:26 +08:00
|
|
|
case MVT::v8f16: return "MVT::v8f16";
|
2019-08-31 01:34:29 +08:00
|
|
|
case MVT::v16f16: return "MVT::v16f16";
|
|
|
|
case MVT::v32f16: return "MVT::v32f16";
|
2013-09-24 10:47:27 +08:00
|
|
|
case MVT::v1f32: return "MVT::v1f32";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v2f32: return "MVT::v2f32";
|
2019-03-18 06:56:38 +08:00
|
|
|
case MVT::v3f32: return "MVT::v3f32";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v4f32: return "MVT::v4f32";
|
2019-03-18 06:56:38 +08:00
|
|
|
case MVT::v5f32: return "MVT::v5f32";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v8f32: return "MVT::v8f32";
|
2012-12-24 18:03:57 +08:00
|
|
|
case MVT::v16f32: return "MVT::v16f32";
|
2019-07-07 12:47:37 +08:00
|
|
|
case MVT::v32f32: return "MVT::v32f32";
|
|
|
|
case MVT::v64f32: return "MVT::v64f32";
|
|
|
|
case MVT::v128f32: return "MVT::v128f32";
|
|
|
|
case MVT::v256f32: return "MVT::v256f32";
|
|
|
|
case MVT::v512f32: return "MVT::v512f32";
|
|
|
|
case MVT::v1024f32: return "MVT::v1024f32";
|
|
|
|
case MVT::v2048f32: return "MVT::v2048f32";
|
2013-09-24 10:47:27 +08:00
|
|
|
case MVT::v1f64: return "MVT::v1f64";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::v2f64: return "MVT::v2f64";
|
|
|
|
case MVT::v4f64: return "MVT::v4f64";
|
2012-12-24 18:03:57 +08:00
|
|
|
case MVT::v8f64: return "MVT::v8f64";
|
2017-05-18 19:29:41 +08:00
|
|
|
case MVT::nxv1i1: return "MVT::nxv1i1";
|
2017-04-20 21:36:58 +08:00
|
|
|
case MVT::nxv2i1: return "MVT::nxv2i1";
|
|
|
|
case MVT::nxv4i1: return "MVT::nxv4i1";
|
|
|
|
case MVT::nxv8i1: return "MVT::nxv8i1";
|
|
|
|
case MVT::nxv16i1: return "MVT::nxv16i1";
|
|
|
|
case MVT::nxv32i1: return "MVT::nxv32i1";
|
|
|
|
case MVT::nxv1i8: return "MVT::nxv1i8";
|
|
|
|
case MVT::nxv2i8: return "MVT::nxv2i8";
|
|
|
|
case MVT::nxv4i8: return "MVT::nxv4i8";
|
|
|
|
case MVT::nxv8i8: return "MVT::nxv8i8";
|
|
|
|
case MVT::nxv16i8: return "MVT::nxv16i8";
|
|
|
|
case MVT::nxv32i8: return "MVT::nxv32i8";
|
|
|
|
case MVT::nxv1i16: return "MVT::nxv1i16";
|
|
|
|
case MVT::nxv2i16: return "MVT::nxv2i16";
|
|
|
|
case MVT::nxv4i16: return "MVT::nxv4i16";
|
|
|
|
case MVT::nxv8i16: return "MVT::nxv8i16";
|
|
|
|
case MVT::nxv16i16: return "MVT::nxv16i16";
|
|
|
|
case MVT::nxv32i16: return "MVT::nxv32i16";
|
|
|
|
case MVT::nxv1i32: return "MVT::nxv1i32";
|
|
|
|
case MVT::nxv2i32: return "MVT::nxv2i32";
|
|
|
|
case MVT::nxv4i32: return "MVT::nxv4i32";
|
|
|
|
case MVT::nxv8i32: return "MVT::nxv8i32";
|
|
|
|
case MVT::nxv16i32: return "MVT::nxv16i32";
|
|
|
|
case MVT::nxv1i64: return "MVT::nxv1i64";
|
|
|
|
case MVT::nxv2i64: return "MVT::nxv2i64";
|
|
|
|
case MVT::nxv4i64: return "MVT::nxv4i64";
|
|
|
|
case MVT::nxv8i64: return "MVT::nxv8i64";
|
|
|
|
case MVT::nxv16i64: return "MVT::nxv16i64";
|
|
|
|
case MVT::nxv2f16: return "MVT::nxv2f16";
|
|
|
|
case MVT::nxv4f16: return "MVT::nxv4f16";
|
|
|
|
case MVT::nxv8f16: return "MVT::nxv8f16";
|
|
|
|
case MVT::nxv1f32: return "MVT::nxv1f32";
|
|
|
|
case MVT::nxv2f32: return "MVT::nxv2f32";
|
|
|
|
case MVT::nxv4f32: return "MVT::nxv4f32";
|
|
|
|
case MVT::nxv8f32: return "MVT::nxv8f32";
|
|
|
|
case MVT::nxv16f32: return "MVT::nxv16f32";
|
|
|
|
case MVT::nxv1f64: return "MVT::nxv1f64";
|
|
|
|
case MVT::nxv2f64: return "MVT::nxv2f64";
|
|
|
|
case MVT::nxv4f64: return "MVT::nxv4f64";
|
|
|
|
case MVT::nxv8f64: return "MVT::nxv8f64";
|
2015-09-02 21:36:25 +08:00
|
|
|
case MVT::token: return "MVT::token";
|
2009-08-12 04:47:22 +08:00
|
|
|
case MVT::Metadata: return "MVT::Metadata";
|
2010-09-08 02:49:14 +08:00
|
|
|
case MVT::iPTR: return "MVT::iPTR";
|
2009-08-12 04:47:22 +08:00
|
|
|
case MVT::iPTRAny: return "MVT::iPTRAny";
|
2011-11-16 09:02:57 +08:00
|
|
|
case MVT::Untyped: return "MVT::Untyped";
|
2019-07-16 06:49:25 +08:00
|
|
|
case MVT::exnref: return "MVT::exnref";
|
2012-02-05 15:21:30 +08:00
|
|
|
default: llvm_unreachable("ILLEGAL VALUE TYPE!");
|
2003-10-06 03:27:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-06 06:25:12 +08:00
|
|
|
/// getQualifiedName - Return the name of the specified record, with a
|
|
|
|
/// namespace qualifier if the record contains one.
|
|
|
|
///
|
|
|
|
std::string llvm::getQualifiedName(const Record *R) {
|
2011-05-08 05:22:39 +08:00
|
|
|
std::string Namespace;
|
|
|
|
if (R->getValue("Namespace"))
|
2020-01-29 03:23:46 +08:00
|
|
|
Namespace = std::string(R->getValueAsString("Namespace"));
|
|
|
|
if (Namespace.empty())
|
|
|
|
return std::string(R->getName());
|
2016-12-04 13:48:16 +08:00
|
|
|
return Namespace + "::" + R->getName().str();
|
2008-01-06 06:25:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-06 03:27:59 +08:00
|
|
|
/// getTarget - Return the current instance of the Target class.
|
|
|
|
///
|
2011-06-11 02:40:00 +08:00
|
|
|
CodeGenTarget::CodeGenTarget(RecordKeeper &records)
|
2017-09-15 00:56:21 +08:00
|
|
|
: Records(records), CGH(records) {
|
2003-10-06 03:27:59 +08:00
|
|
|
std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
|
2004-06-04 22:59:42 +08:00
|
|
|
if (Targets.size() == 0)
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError("ERROR: No 'Target' subclasses defined!");
|
2003-10-06 03:27:59 +08:00
|
|
|
if (Targets.size() != 1)
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError("ERROR: Multiple subclasses of Target defined!");
|
2003-10-06 03:27:59 +08:00
|
|
|
TargetRec = Targets[0];
|
|
|
|
}
|
|
|
|
|
2012-07-07 12:00:00 +08:00
|
|
|
CodeGenTarget::~CodeGenTarget() {
|
|
|
|
}
|
2003-10-06 03:27:59 +08:00
|
|
|
|
2016-12-04 13:48:16 +08:00
|
|
|
const StringRef CodeGenTarget::getName() const {
|
2003-10-06 03:27:59 +08:00
|
|
|
return TargetRec->getName();
|
|
|
|
}
|
|
|
|
|
2017-07-07 14:22:35 +08:00
|
|
|
StringRef CodeGenTarget::getInstNamespace() const {
|
2016-01-18 04:38:18 +08:00
|
|
|
for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) {
|
2010-03-19 09:00:55 +08:00
|
|
|
// Make sure not to pick up "TargetOpcode" by accidentally getting
|
2008-08-21 05:45:57 +08:00
|
|
|
// the namespace off the PHI instruction or something.
|
2014-12-09 16:05:51 +08:00
|
|
|
if (Inst->Namespace != "TargetOpcode")
|
|
|
|
return Inst->Namespace;
|
2008-08-21 05:45:57 +08:00
|
|
|
}
|
|
|
|
|
2010-03-19 09:00:55 +08:00
|
|
|
return "";
|
2008-08-21 05:45:57 +08:00
|
|
|
}
|
|
|
|
|
2003-10-06 03:27:59 +08:00
|
|
|
Record *CodeGenTarget::getInstructionSet() const {
|
|
|
|
return TargetRec->getValueAsDef("InstructionSet");
|
|
|
|
}
|
2003-11-12 06:41:34 +08:00
|
|
|
|
[MachineOperand][Target] MachineOperand::isRenamable semantics changes
Summary:
Add a target option AllowRegisterRenaming that is used to opt in to
post-register-allocation renaming of registers. This is set to 0 by
default, which causes the hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq
fields of all opcodes to be set to 1, causing
MachineOperand::isRenamable to always return false.
Set the AllowRegisterRenaming flag to 1 for all in-tree targets that
have lit tests that were effected by enabling COPY forwarding in
MachineCopyPropagation (AArch64, AMDGPU, ARM, Hexagon, Mips, PowerPC,
RISCV, Sparc, SystemZ and X86).
Add some more comments describing the semantics of the
MachineOperand::isRenamable function and how it is set and maintained.
Change isRenamable to check the operand's opcode
hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq bit directly instead of
relying on it being consistently reflected in the IsRenamable bit
setting.
Clear the IsRenamable bit when changing an operand's register value.
Remove target code that was clearing the IsRenamable bit when changing
registers/opcodes now that this is done conservatively by default.
Change setting of hasExtraSrcRegAllocReq in AMDGPU target to be done in
one place covering all opcodes that have constant pipe read limit
restrictions.
Reviewers: qcolombet, MatzeB
Subscribers: aemerson, arsenm, jyknight, mcrosier, sdardis, nhaehnle, javed.absar, tpr, arichardson, kristof.beyls, kbarton, fedor.sergeev, asb, rbar, johnrusso, simoncook, jordy.potman.lists, apazos, sabuasal, niosHD, escha, nemanjai, llvm-commits
Differential Revision: https://reviews.llvm.org/D43042
llvm-svn: 325931
2018-02-24 02:25:08 +08:00
|
|
|
bool CodeGenTarget::getAllowRegisterRenaming() const {
|
|
|
|
return TargetRec->getValueAsInt("AllowRegisterRenaming");
|
|
|
|
}
|
2010-03-19 08:07:20 +08:00
|
|
|
|
2009-07-29 08:02:19 +08:00
|
|
|
/// getAsmParser - Return the AssemblyParser definition for this target.
|
|
|
|
///
|
|
|
|
Record *CodeGenTarget::getAsmParser() const {
|
|
|
|
std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
|
|
|
|
if (AsmParserNum >= LI.size())
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError("Target does not have an AsmParser #" +
|
|
|
|
Twine(AsmParserNum) + "!");
|
2009-07-29 08:02:19 +08:00
|
|
|
return LI[AsmParserNum];
|
|
|
|
}
|
|
|
|
|
2020-01-06 18:15:44 +08:00
|
|
|
/// getAsmParserVariant - Return the AssemblyParserVariant definition for
|
2012-01-10 03:13:28 +08:00
|
|
|
/// this target.
|
|
|
|
///
|
|
|
|
Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
|
2012-07-07 11:59:51 +08:00
|
|
|
std::vector<Record*> LI =
|
2012-01-10 03:13:28 +08:00
|
|
|
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
|
|
|
|
if (i >= LI.size())
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +
|
|
|
|
"!");
|
2012-01-10 03:13:28 +08:00
|
|
|
return LI[i];
|
|
|
|
}
|
|
|
|
|
2020-01-06 18:15:44 +08:00
|
|
|
/// getAsmParserVariantCount - Return the AssemblyParserVariant definition
|
2012-01-10 03:13:28 +08:00
|
|
|
/// available for this target.
|
|
|
|
///
|
|
|
|
unsigned CodeGenTarget::getAsmParserVariantCount() const {
|
2012-07-07 11:59:51 +08:00
|
|
|
std::vector<Record*> LI =
|
2012-01-10 03:13:28 +08:00
|
|
|
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
|
|
|
|
return LI.size();
|
|
|
|
}
|
|
|
|
|
2004-08-15 06:50:53 +08:00
|
|
|
/// getAsmWriter - Return the AssemblyWriter definition for this target.
|
|
|
|
///
|
|
|
|
Record *CodeGenTarget::getAsmWriter() const {
|
2005-10-29 06:49:02 +08:00
|
|
|
std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
|
|
|
|
if (AsmWriterNum >= LI.size())
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError("Target does not have an AsmWriter #" +
|
|
|
|
Twine(AsmWriterNum) + "!");
|
2005-10-29 06:49:02 +08:00
|
|
|
return LI[AsmWriterNum];
|
2004-08-15 06:50:53 +08:00
|
|
|
}
|
|
|
|
|
2011-06-11 02:40:00 +08:00
|
|
|
CodeGenRegBank &CodeGenTarget::getRegBank() const {
|
|
|
|
if (!RegBank)
|
2019-08-15 23:54:37 +08:00
|
|
|
RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());
|
2011-06-11 02:40:00 +08:00
|
|
|
return *RegBank;
|
|
|
|
}
|
|
|
|
|
2019-08-28 01:47:06 +08:00
|
|
|
Optional<CodeGenRegisterClass *>
|
|
|
|
CodeGenTarget::getSuperRegForSubReg(const ValueTypeByHwMode &ValueTy,
|
|
|
|
CodeGenRegBank &RegBank,
|
|
|
|
const CodeGenSubRegIndex *SubIdx) const {
|
|
|
|
std::vector<CodeGenRegisterClass *> Candidates;
|
|
|
|
auto &RegClasses = RegBank.getRegClasses();
|
|
|
|
|
|
|
|
// Try to find a register class which supports ValueTy, and also contains
|
|
|
|
// SubIdx.
|
|
|
|
for (CodeGenRegisterClass &RC : RegClasses) {
|
|
|
|
// Is there a subclass of this class which contains this subregister index?
|
|
|
|
CodeGenRegisterClass *SubClassWithSubReg = RC.getSubClassWithSubReg(SubIdx);
|
|
|
|
if (!SubClassWithSubReg)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// We have a class. Check if it supports this value type.
|
|
|
|
if (llvm::none_of(SubClassWithSubReg->VTs,
|
|
|
|
[&ValueTy](const ValueTypeByHwMode &ClassVT) {
|
|
|
|
return ClassVT == ValueTy;
|
|
|
|
}))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// We have a register class which supports both the value type and
|
|
|
|
// subregister index. Remember it.
|
|
|
|
Candidates.push_back(SubClassWithSubReg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we didn't find anything, we're done.
|
|
|
|
if (Candidates.empty())
|
|
|
|
return None;
|
|
|
|
|
|
|
|
// Find and return the largest of our candidate classes.
|
|
|
|
llvm::stable_sort(Candidates, [&](const CodeGenRegisterClass *A,
|
|
|
|
const CodeGenRegisterClass *B) {
|
2019-08-29 06:03:05 +08:00
|
|
|
if (A->getMembers().size() > B->getMembers().size())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (A->getMembers().size() < B->getMembers().size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Order by name as a tie-breaker.
|
|
|
|
return StringRef(A->getName()) < B->getName();
|
2019-08-28 01:47:06 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
return Candidates[0];
|
|
|
|
}
|
|
|
|
|
2011-06-28 05:06:21 +08:00
|
|
|
void CodeGenTarget::ReadRegAltNameIndices() const {
|
|
|
|
RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 10:13:45 +08:00
|
|
|
llvm::sort(RegAltNameIndices, LessRecord());
|
2011-06-28 05:06:21 +08:00
|
|
|
}
|
|
|
|
|
2010-11-03 02:10:06 +08:00
|
|
|
/// getRegisterByName - If there is a register with the specific AsmName,
|
|
|
|
/// return it.
|
|
|
|
const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
|
2012-09-12 07:32:17 +08:00
|
|
|
const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName();
|
|
|
|
StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name);
|
|
|
|
if (I == Regs.end())
|
2014-04-15 15:20:03 +08:00
|
|
|
return nullptr;
|
2012-09-12 07:32:17 +08:00
|
|
|
return I->second;
|
2010-11-03 02:10:06 +08:00
|
|
|
}
|
|
|
|
|
2017-09-15 00:56:21 +08:00
|
|
|
std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R)
|
|
|
|
const {
|
2011-06-15 12:50:36 +08:00
|
|
|
const CodeGenRegister *Reg = getRegBank().getReg(R);
|
2017-09-15 00:56:21 +08:00
|
|
|
std::vector<ValueTypeByHwMode> Result;
|
2014-12-04 03:58:41 +08:00
|
|
|
for (const auto &RC : getRegBank().getRegClasses()) {
|
2014-12-04 03:58:45 +08:00
|
|
|
if (RC.contains(Reg)) {
|
2017-09-15 00:56:21 +08:00
|
|
|
ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();
|
2011-06-15 12:50:36 +08:00
|
|
|
Result.insert(Result.end(), InVTs.begin(), InVTs.end());
|
2006-05-16 15:05:30 +08:00
|
|
|
}
|
|
|
|
}
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2010-03-28 04:32:26 +08:00
|
|
|
// Remove duplicates.
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 10:13:45 +08:00
|
|
|
llvm::sort(Result);
|
2010-03-28 04:32:26 +08:00
|
|
|
Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
|
2006-05-16 15:05:30 +08:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-09 05:43:21 +08:00
|
|
|
void CodeGenTarget::ReadLegalValueTypes() const {
|
2014-12-04 03:58:45 +08:00
|
|
|
for (const auto &RC : getRegBank().getRegClasses())
|
|
|
|
LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end());
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2005-10-14 11:54:49 +08:00
|
|
|
// Remove duplicates.
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 10:13:45 +08:00
|
|
|
llvm::sort(LegalValueTypes);
|
2005-10-14 11:54:49 +08:00
|
|
|
LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
|
|
|
|
LegalValueTypes.end()),
|
|
|
|
LegalValueTypes.end());
|
2005-09-09 05:43:21 +08:00
|
|
|
}
|
2004-08-21 12:05:00 +08:00
|
|
|
|
2012-07-07 12:00:00 +08:00
|
|
|
CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
|
|
|
|
if (!SchedModels)
|
2019-08-15 23:54:37 +08:00
|
|
|
SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);
|
2012-07-07 12:00:00 +08:00
|
|
|
return *SchedModels;
|
|
|
|
}
|
2004-08-15 06:50:53 +08:00
|
|
|
|
2004-08-01 13:04:00 +08:00
|
|
|
void CodeGenTarget::ReadInstructions() const {
|
2019-02-12 07:02:02 +08:00
|
|
|
NamedRegionTimer T("Read Instructions", "Time spent reading instructions",
|
|
|
|
"CodeGenTarget", "CodeGenTarget", TimeRegions);
|
2004-08-01 13:04:00 +08:00
|
|
|
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
|
2006-01-27 09:45:06 +08:00
|
|
|
if (Insts.size() <= 2)
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError("No 'Instruction' subclasses defined!");
|
2004-08-01 13:04:00 +08:00
|
|
|
|
2006-01-27 09:45:06 +08:00
|
|
|
// Parse the instructions defined in the .td file.
|
2010-11-01 10:15:23 +08:00
|
|
|
for (unsigned i = 0, e = Insts.size(); i != e; ++i)
|
2019-08-15 23:54:37 +08:00
|
|
|
Instructions[Insts[i]] = std::make_unique<CodeGenInstruction>(Insts[i]);
|
2004-08-01 13:04:00 +08:00
|
|
|
}
|
|
|
|
|
2010-03-19 08:23:20 +08:00
|
|
|
static const CodeGenInstruction *
|
|
|
|
GetInstByName(const char *Name,
|
2014-12-10 14:18:57 +08:00
|
|
|
const DenseMap<const Record*,
|
|
|
|
std::unique_ptr<CodeGenInstruction>> &Insts,
|
2010-12-13 08:23:57 +08:00
|
|
|
RecordKeeper &Records) {
|
2010-03-19 09:07:44 +08:00
|
|
|
const Record *Rec = Records.getDef(Name);
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2014-12-10 14:18:57 +08:00
|
|
|
const auto I = Insts.find(Rec);
|
2014-04-15 15:20:03 +08:00
|
|
|
if (!Rec || I == Insts.end())
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
|
2014-12-10 14:18:57 +08:00
|
|
|
return I->second.get();
|
2010-03-19 09:07:44 +08:00
|
|
|
}
|
|
|
|
|
2018-01-25 06:35:11 +08:00
|
|
|
static const char *const FixedInstrs[] = {
|
|
|
|
#define HANDLE_TARGET_OPCODE(OPC) #OPC,
|
2018-03-24 07:58:27 +08:00
|
|
|
#include "llvm/Support/TargetOpcodes.def"
|
2018-01-25 06:35:11 +08:00
|
|
|
nullptr};
|
|
|
|
|
|
|
|
unsigned CodeGenTarget::getNumFixedInstructions() {
|
|
|
|
return array_lengthof(FixedInstrs) - 1;
|
|
|
|
}
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Return all of the instructions defined by the target, ordered by
|
2014-02-05 15:21:07 +08:00
|
|
|
/// their enum value.
|
2010-03-19 09:00:55 +08:00
|
|
|
void CodeGenTarget::ComputeInstrsByEnum() const {
|
2014-12-10 14:18:57 +08:00
|
|
|
const auto &Insts = getInstructions();
|
2010-07-03 05:44:22 +08:00
|
|
|
for (const char *const *p = FixedInstrs; *p; ++p) {
|
2010-12-13 08:23:57 +08:00
|
|
|
const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
|
2010-07-03 05:44:22 +08:00
|
|
|
assert(Instr && "Missing target independent instruction");
|
|
|
|
assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
|
|
|
|
InstrsByEnum.push_back(Instr);
|
|
|
|
}
|
2010-03-19 09:07:44 +08:00
|
|
|
unsigned EndOfPredefines = InstrsByEnum.size();
|
2018-01-25 06:35:11 +08:00
|
|
|
assert(EndOfPredefines == getNumFixedInstructions() &&
|
|
|
|
"Missing generic opcode");
|
2010-07-03 05:44:22 +08:00
|
|
|
|
2014-12-09 16:05:51 +08:00
|
|
|
for (const auto &I : Insts) {
|
2014-12-10 14:18:57 +08:00
|
|
|
const CodeGenInstruction *CGI = I.second.get();
|
2018-05-24 06:10:21 +08:00
|
|
|
if (CGI->Namespace != "TargetOpcode") {
|
2010-03-19 09:00:55 +08:00
|
|
|
InstrsByEnum.push_back(CGI);
|
2018-05-24 06:10:21 +08:00
|
|
|
if (CGI->TheDef->getValueAsBit("isPseudo"))
|
|
|
|
++NumPseudoInstructions;
|
|
|
|
}
|
2010-03-19 09:00:55 +08:00
|
|
|
}
|
2010-07-03 05:44:22 +08:00
|
|
|
|
|
|
|
assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
|
|
|
|
|
2010-03-19 09:07:44 +08:00
|
|
|
// All of the instructions are now in random order based on the map iteration.
|
2018-05-24 06:10:21 +08:00
|
|
|
llvm::sort(
|
|
|
|
InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
|
|
|
|
[](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
|
|
|
|
const auto &D1 = *Rec1->TheDef;
|
|
|
|
const auto &D2 = *Rec2->TheDef;
|
|
|
|
return std::make_tuple(!D1.getValueAsBit("isPseudo"), D1.getName()) <
|
|
|
|
std::make_tuple(!D2.getValueAsBit("isPseudo"), D2.getName());
|
|
|
|
});
|
2005-01-23 02:58:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-14 13:50:43 +08:00
|
|
|
/// isLittleEndianEncoding - Return whether this target encodes its instruction
|
|
|
|
/// in little-endian format, i.e. bits laid out in the order [0..n]
|
|
|
|
///
|
|
|
|
bool CodeGenTarget::isLittleEndianEncoding() const {
|
|
|
|
return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
|
|
|
|
}
|
|
|
|
|
2013-12-18 06:37:50 +08:00
|
|
|
/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
|
|
|
|
/// encodings, reverse the bit order of all instructions.
|
|
|
|
void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
|
|
|
|
if (!isLittleEndianEncoding())
|
|
|
|
return;
|
|
|
|
|
2019-09-19 21:39:54 +08:00
|
|
|
std::vector<Record *> Insts =
|
|
|
|
Records.getAllDerivedDefinitions("InstructionEncoding");
|
2014-12-09 16:05:51 +08:00
|
|
|
for (Record *R : Insts) {
|
2013-12-18 06:37:50 +08:00
|
|
|
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
|
|
|
|
R->getValueAsBit("isPseudo"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
BitsInit *BI = R->getValueAsBitsInit("Inst");
|
|
|
|
|
|
|
|
unsigned numBits = BI->getNumBits();
|
2016-04-12 14:02:11 +08:00
|
|
|
|
2013-12-18 06:37:50 +08:00
|
|
|
SmallVector<Init *, 16> NewBits(numBits);
|
2016-04-12 14:02:11 +08:00
|
|
|
|
2013-12-18 06:37:50 +08:00
|
|
|
for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
|
|
|
|
unsigned bitSwapIdx = numBits - bit - 1;
|
|
|
|
Init *OrigBit = BI->getBit(bit);
|
|
|
|
Init *BitSwap = BI->getBit(bitSwapIdx);
|
|
|
|
NewBits[bit] = BitSwap;
|
|
|
|
NewBits[bitSwapIdx] = OrigBit;
|
|
|
|
}
|
|
|
|
if (numBits % 2) {
|
|
|
|
unsigned middle = (numBits + 1) / 2;
|
|
|
|
NewBits[middle] = BI->getBit(middle);
|
|
|
|
}
|
|
|
|
|
|
|
|
BitsInit *NewBI = BitsInit::get(NewBits);
|
|
|
|
|
|
|
|
// Update the bits in reversed order so that emitInstrOpBits will get the
|
|
|
|
// correct endianness.
|
|
|
|
R->getValue("Inst")->setValue(NewBI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-24 03:34:41 +08:00
|
|
|
/// guessInstructionProperties - Return true if it's OK to guess instruction
|
|
|
|
/// properties instead of raising an error.
|
|
|
|
///
|
|
|
|
/// This is configurable as a temporary migration aid. It will eventually be
|
|
|
|
/// permanently false.
|
|
|
|
bool CodeGenTarget::guessInstructionProperties() const {
|
|
|
|
return getInstructionSet()->getValueAsBit("guessInstructionProperties");
|
|
|
|
}
|
|
|
|
|
2005-12-08 10:00:36 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ComplexPattern implementation
|
|
|
|
//
|
|
|
|
ComplexPattern::ComplexPattern(Record *R) {
|
2005-12-08 10:14:08 +08:00
|
|
|
Ty = ::getValueType(R->getValueAsDef("Ty"));
|
|
|
|
NumOperands = R->getValueAsInt("NumOperands");
|
2020-01-29 03:23:46 +08:00
|
|
|
SelectFunc = std::string(R->getValueAsString("SelectFunc"));
|
2005-12-08 10:14:08 +08:00
|
|
|
RootNodes = R->getValueAsListOfDefs("RootNodes");
|
2006-10-12 05:02:01 +08:00
|
|
|
|
2016-11-10 07:53:43 +08:00
|
|
|
// FIXME: This is a hack to statically increase the priority of patterns which
|
|
|
|
// maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
|
|
|
|
// possible pattern match we'll need to dynamically calculate the complexity
|
|
|
|
// of all patterns a dag can potentially map to.
|
|
|
|
int64_t RawComplexity = R->getValueAsInt("Complexity");
|
|
|
|
if (RawComplexity == -1)
|
|
|
|
Complexity = NumOperands * 3;
|
|
|
|
else
|
|
|
|
Complexity = RawComplexity;
|
|
|
|
|
2017-12-21 03:36:28 +08:00
|
|
|
// FIXME: Why is this different from parseSDPatternOperatorProperties?
|
2006-10-12 05:02:01 +08:00
|
|
|
// Parse the properties.
|
|
|
|
Properties = 0;
|
|
|
|
std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
|
|
|
|
for (unsigned i = 0, e = PropList.size(); i != e; ++i)
|
|
|
|
if (PropList[i]->getName() == "SDNPHasChain") {
|
|
|
|
Properties |= 1 << SDNPHasChain;
|
2010-12-24 02:28:41 +08:00
|
|
|
} else if (PropList[i]->getName() == "SDNPOptInGlue") {
|
|
|
|
Properties |= 1 << SDNPOptInGlue;
|
2008-01-10 15:59:24 +08:00
|
|
|
} else if (PropList[i]->getName() == "SDNPMayStore") {
|
|
|
|
Properties |= 1 << SDNPMayStore;
|
|
|
|
} else if (PropList[i]->getName() == "SDNPMayLoad") {
|
|
|
|
Properties |= 1 << SDNPMayLoad;
|
|
|
|
} else if (PropList[i]->getName() == "SDNPSideEffect") {
|
|
|
|
Properties |= 1 << SDNPSideEffect;
|
2008-06-25 16:15:39 +08:00
|
|
|
} else if (PropList[i]->getName() == "SDNPMemOperand") {
|
|
|
|
Properties |= 1 << SDNPMemOperand;
|
2010-03-19 13:07:09 +08:00
|
|
|
} else if (PropList[i]->getName() == "SDNPVariadic") {
|
|
|
|
Properties |= 1 << SDNPVariadic;
|
2010-09-22 04:31:19 +08:00
|
|
|
} else if (PropList[i]->getName() == "SDNPWantRoot") {
|
|
|
|
Properties |= 1 << SDNPWantRoot;
|
|
|
|
} else if (PropList[i]->getName() == "SDNPWantParent") {
|
|
|
|
Properties |= 1 << SDNPWantParent;
|
2006-10-12 05:02:01 +08:00
|
|
|
} else {
|
[tablegen] Add locations to many PrintFatalError() calls
Summary:
While working on the GISel Combiner, I noticed I was producing location-less
error messages fairly often and set about fixing this. In the process, I
noticed quite a few places elsewhere in TableGen that also neglected to include
a relevant location.
This patch adds locations to errors that relate to a specific record (or a
field within it) and also have easy access to the relevant location. This is
particularly useful when multiclasses are involved as many of these errors
refer to the full name of a record and it's difficult to guess which substring
is grep-able.
Unfortunately, tablegen currently only supports Record granularity so it's not
currently possible to point at a specific Init so these sometimes point at the
record that caused the error rather than the precise origin of the error.
Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle
Reviewed By: nhaehnle
Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58077
llvm-svn: 353862
2019-02-13 01:36:57 +08:00
|
|
|
PrintFatalError(R->getLoc(), "Unsupported SD Node property '" +
|
|
|
|
PropList[i]->getName() +
|
|
|
|
"' on ComplexPattern '" + R->getName() +
|
|
|
|
"'!");
|
2006-10-12 05:02:01 +08:00
|
|
|
}
|
2005-12-08 10:00:36 +08:00
|
|
|
}
|
2005-12-08 10:14:08 +08:00
|
|
|
|
2006-03-25 03:49:31 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CodeGenIntrinsic Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-11 23:37:16 +08:00
|
|
|
CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
|
2016-07-15 02:08:33 +08:00
|
|
|
std::vector<Record*> Defs = RC.getAllDerivedDefinitions("Intrinsic");
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2016-07-16 00:31:37 +08:00
|
|
|
Intrinsics.reserve(Defs.size());
|
2006-03-28 08:15:00 +08:00
|
|
|
|
2019-12-11 23:37:16 +08:00
|
|
|
for (unsigned I = 0, e = Defs.size(); I != e; ++I)
|
|
|
|
Intrinsics.push_back(CodeGenIntrinsic(Defs[I]));
|
|
|
|
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 10:13:45 +08:00
|
|
|
llvm::sort(Intrinsics,
|
2018-04-07 04:18:05 +08:00
|
|
|
[](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
|
|
|
|
return std::tie(LHS.TargetPrefix, LHS.Name) <
|
|
|
|
std::tie(RHS.TargetPrefix, RHS.Name);
|
|
|
|
});
|
2016-07-16 00:31:37 +08:00
|
|
|
Targets.push_back({"", 0, 0});
|
|
|
|
for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
|
|
|
|
if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
|
|
|
|
Targets.back().Count = I - Targets.back().Offset;
|
|
|
|
Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
|
|
|
|
}
|
|
|
|
Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
|
2006-03-25 03:49:31 +08:00
|
|
|
}
|
|
|
|
|
2008-04-03 08:02:49 +08:00
|
|
|
CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
|
2006-03-25 04:25:01 +08:00
|
|
|
TheDef = R;
|
2020-01-29 03:23:46 +08:00
|
|
|
std::string DefName = std::string(R->getName());
|
[tablegen] Add locations to many PrintFatalError() calls
Summary:
While working on the GISel Combiner, I noticed I was producing location-less
error messages fairly often and set about fixing this. In the process, I
noticed quite a few places elsewhere in TableGen that also neglected to include
a relevant location.
This patch adds locations to errors that relate to a specific record (or a
field within it) and also have easy access to the relevant location. This is
particularly useful when multiclasses are involved as many of these errors
refer to the full name of a record and it's difficult to guess which substring
is grep-able.
Unfortunately, tablegen currently only supports Record granularity so it's not
currently possible to point at a specific Init so these sometimes point at the
record that caused the error rather than the precise origin of the error.
Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle
Reviewed By: nhaehnle
Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58077
llvm-svn: 353862
2019-02-13 01:36:57 +08:00
|
|
|
ArrayRef<SMLoc> DefLoc = R->getLoc();
|
2010-08-06 07:36:21 +08:00
|
|
|
ModRef = ReadWriteMem;
|
2017-12-21 03:36:28 +08:00
|
|
|
Properties = 0;
|
2007-04-01 15:20:02 +08:00
|
|
|
isOverloaded = false;
|
2008-06-17 04:29:38 +08:00
|
|
|
isCommutative = false;
|
2011-05-28 14:31:34 +08:00
|
|
|
canThrow = false;
|
2012-05-28 07:20:41 +08:00
|
|
|
isNoReturn = false;
|
2019-07-17 23:15:43 +08:00
|
|
|
isWillReturn = false;
|
2018-11-15 03:53:41 +08:00
|
|
|
isCold = false;
|
2014-03-19 07:51:07 +08:00
|
|
|
isNoDuplicate = false;
|
2015-05-27 07:48:40 +08:00
|
|
|
isConvergent = false;
|
2017-04-29 04:25:27 +08:00
|
|
|
isSpeculatable = false;
|
2017-04-29 05:01:46 +08:00
|
|
|
hasSideEffects = false;
|
2011-03-11 09:27:24 +08:00
|
|
|
|
|
|
|
if (DefName.size() <= 4 ||
|
2008-11-13 17:08:33 +08:00
|
|
|
std::string(DefName.begin(), DefName.begin() + 4) != "int_")
|
[tablegen] Add locations to many PrintFatalError() calls
Summary:
While working on the GISel Combiner, I noticed I was producing location-less
error messages fairly often and set about fixing this. In the process, I
noticed quite a few places elsewhere in TableGen that also neglected to include
a relevant location.
This patch adds locations to errors that relate to a specific record (or a
field within it) and also have easy access to the relevant location. This is
particularly useful when multiclasses are involved as many of these errors
refer to the full name of a record and it's difficult to guess which substring
is grep-able.
Unfortunately, tablegen currently only supports Record granularity so it's not
currently possible to point at a specific Init so these sometimes point at the
record that caused the error rather than the precise origin of the error.
Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle
Reviewed By: nhaehnle
Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58077
llvm-svn: 353862
2019-02-13 01:36:57 +08:00
|
|
|
PrintFatalError(DefLoc,
|
|
|
|
"Intrinsic '" + DefName + "' does not start with 'int_'!");
|
2008-11-13 17:08:33 +08:00
|
|
|
|
2006-03-25 03:49:31 +08:00
|
|
|
EnumName = std::string(DefName.begin()+4, DefName.end());
|
2008-11-13 17:08:33 +08:00
|
|
|
|
2006-03-25 03:49:31 +08:00
|
|
|
if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field.
|
2020-01-29 03:23:46 +08:00
|
|
|
GCCBuiltinName = std::string(R->getValueAsString("GCCBuiltinName"));
|
2014-07-05 02:42:25 +08:00
|
|
|
if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field.
|
2020-01-29 03:23:46 +08:00
|
|
|
MSBuiltinName = std::string(R->getValueAsString("MSBuiltinName"));
|
2008-11-13 17:08:33 +08:00
|
|
|
|
2020-01-29 03:23:46 +08:00
|
|
|
TargetPrefix = std::string(R->getValueAsString("TargetPrefix"));
|
|
|
|
Name = std::string(R->getValueAsString("LLVMName"));
|
2008-11-13 17:08:33 +08:00
|
|
|
|
2006-03-25 03:49:31 +08:00
|
|
|
if (Name == "") {
|
|
|
|
// If an explicit name isn't specified, derive one from the DefName.
|
|
|
|
Name = "llvm.";
|
2008-11-13 17:08:33 +08:00
|
|
|
|
2006-03-25 03:49:31 +08:00
|
|
|
for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
|
2008-11-13 17:08:33 +08:00
|
|
|
Name += (EnumName[i] == '_') ? '.' : EnumName[i];
|
2006-03-25 03:49:31 +08:00
|
|
|
} else {
|
|
|
|
// Verify it starts with "llvm.".
|
2011-03-11 09:27:24 +08:00
|
|
|
if (Name.size() <= 5 ||
|
2008-11-13 17:08:33 +08:00
|
|
|
std::string(Name.begin(), Name.begin() + 5) != "llvm.")
|
[tablegen] Add locations to many PrintFatalError() calls
Summary:
While working on the GISel Combiner, I noticed I was producing location-less
error messages fairly often and set about fixing this. In the process, I
noticed quite a few places elsewhere in TableGen that also neglected to include
a relevant location.
This patch adds locations to errors that relate to a specific record (or a
field within it) and also have easy access to the relevant location. This is
particularly useful when multiclasses are involved as many of these errors
refer to the full name of a record and it's difficult to guess which substring
is grep-able.
Unfortunately, tablegen currently only supports Record granularity so it's not
currently possible to point at a specific Init so these sometimes point at the
record that caused the error rather than the precise origin of the error.
Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle
Reviewed By: nhaehnle
Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58077
llvm-svn: 353862
2019-02-13 01:36:57 +08:00
|
|
|
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
|
|
|
|
"'s name does not start with 'llvm.'!");
|
2006-03-25 03:49:31 +08:00
|
|
|
}
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2006-03-25 03:49:31 +08:00
|
|
|
// If TargetPrefix is specified, make sure that Name starts with
|
|
|
|
// "llvm.<targetprefix>.".
|
|
|
|
if (!TargetPrefix.empty()) {
|
|
|
|
if (Name.size() < 6+TargetPrefix.size() ||
|
2008-11-13 17:08:33 +08:00
|
|
|
std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
|
|
|
|
!= (TargetPrefix + "."))
|
[tablegen] Add locations to many PrintFatalError() calls
Summary:
While working on the GISel Combiner, I noticed I was producing location-less
error messages fairly often and set about fixing this. In the process, I
noticed quite a few places elsewhere in TableGen that also neglected to include
a relevant location.
This patch adds locations to errors that relate to a specific record (or a
field within it) and also have easy access to the relevant location. This is
particularly useful when multiclasses are involved as many of these errors
refer to the full name of a record and it's difficult to guess which substring
is grep-able.
Unfortunately, tablegen currently only supports Record granularity so it's not
currently possible to point at a specific Init so these sometimes point at the
record that caused the error rather than the precise origin of the error.
Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle
Reviewed By: nhaehnle
Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58077
llvm-svn: 353862
2019-02-13 01:36:57 +08:00
|
|
|
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
|
|
|
|
"' does not start with 'llvm." +
|
|
|
|
TargetPrefix + ".'!");
|
2006-03-25 03:49:31 +08:00
|
|
|
}
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2019-06-13 16:19:33 +08:00
|
|
|
ListInit *RetTypes = R->getValueAsListInit("RetTypes");
|
|
|
|
ListInit *ParamTypes = R->getValueAsListInit("ParamTypes");
|
|
|
|
|
|
|
|
// First collate a list of overloaded types.
|
2009-08-12 04:47:22 +08:00
|
|
|
std::vector<MVT::SimpleValueType> OverloadedVTs;
|
2019-06-13 16:19:33 +08:00
|
|
|
for (ListInit *TypeList : {RetTypes, ParamTypes}) {
|
|
|
|
for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
|
|
|
|
Record *TyEl = TypeList->getElementAsRecord(i);
|
|
|
|
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
|
|
|
|
|
|
|
|
if (TyEl->isSubClassOf("LLVMMatchType"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
|
|
|
|
if (MVT(VT).isOverloaded()) {
|
|
|
|
OverloadedVTs.push_back(VT);
|
|
|
|
isOverloaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the list of return types.
|
|
|
|
ListInit *TypeList = RetTypes;
|
2015-06-02 12:15:57 +08:00
|
|
|
for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
|
2007-02-28 06:08:27 +08:00
|
|
|
Record *TyEl = TypeList->getElementAsRecord(i);
|
2006-03-25 03:49:31 +08:00
|
|
|
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
|
2009-08-12 04:47:22 +08:00
|
|
|
MVT::SimpleValueType VT;
|
2009-01-07 08:09:01 +08:00
|
|
|
if (TyEl->isSubClassOf("LLVMMatchType")) {
|
2009-04-17 05:51:05 +08:00
|
|
|
unsigned MatchTy = TyEl->getValueAsInt("Number");
|
|
|
|
assert(MatchTy < OverloadedVTs.size() &&
|
|
|
|
"Invalid matching number!");
|
|
|
|
VT = OverloadedVTs[MatchTy];
|
2009-01-07 08:09:01 +08:00
|
|
|
// It only makes sense to use the extended and truncated vector element
|
|
|
|
// variants with iAny types; otherwise, if the intrinsic is not
|
|
|
|
// overloaded, all the types can be specified directly.
|
2014-03-28 20:31:39 +08:00
|
|
|
assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
|
|
|
|
!TyEl->isSubClassOf("LLVMTruncatedType")) ||
|
2009-08-12 04:47:22 +08:00
|
|
|
VT == MVT::iAny || VT == MVT::vAny) &&
|
2009-08-11 13:03:38 +08:00
|
|
|
"Expected iAny or vAny type");
|
2009-04-17 05:51:05 +08:00
|
|
|
} else {
|
2009-01-07 08:09:01 +08:00
|
|
|
VT = getValueType(TyEl->getValueAsDef("VT"));
|
2009-04-17 05:51:05 +08:00
|
|
|
}
|
2010-03-24 07:46:27 +08:00
|
|
|
|
|
|
|
// Reject invalid types.
|
|
|
|
if (VT == MVT::isVoid)
|
[tablegen] Add locations to many PrintFatalError() calls
Summary:
While working on the GISel Combiner, I noticed I was producing location-less
error messages fairly often and set about fixing this. In the process, I
noticed quite a few places elsewhere in TableGen that also neglected to include
a relevant location.
This patch adds locations to errors that relate to a specific record (or a
field within it) and also have easy access to the relevant location. This is
particularly useful when multiclasses are involved as many of these errors
refer to the full name of a record and it's difficult to guess which substring
is grep-able.
Unfortunately, tablegen currently only supports Record granularity so it's not
currently possible to point at a specific Init so these sometimes point at the
record that caused the error rather than the precise origin of the error.
Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle
Reviewed By: nhaehnle
Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58077
llvm-svn: 353862
2019-02-13 01:36:57 +08:00
|
|
|
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
|
|
|
|
" has void in result type list!");
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2008-11-13 17:08:33 +08:00
|
|
|
IS.RetVTs.push_back(VT);
|
|
|
|
IS.RetTypeDefs.push_back(TyEl);
|
2006-03-25 03:49:31 +08:00
|
|
|
}
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2008-11-13 17:08:33 +08:00
|
|
|
// Parse the list of parameter types.
|
2019-06-13 16:19:33 +08:00
|
|
|
TypeList = ParamTypes;
|
2015-06-02 12:15:57 +08:00
|
|
|
for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
|
2008-11-13 17:08:33 +08:00
|
|
|
Record *TyEl = TypeList->getElementAsRecord(i);
|
|
|
|
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
|
2009-08-12 04:47:22 +08:00
|
|
|
MVT::SimpleValueType VT;
|
2009-01-07 08:09:01 +08:00
|
|
|
if (TyEl->isSubClassOf("LLVMMatchType")) {
|
|
|
|
unsigned MatchTy = TyEl->getValueAsInt("Number");
|
2018-04-02 01:08:49 +08:00
|
|
|
if (MatchTy >= OverloadedVTs.size()) {
|
|
|
|
PrintError(R->getLoc(),
|
|
|
|
"Parameter #" + Twine(i) + " has out of bounds matching "
|
|
|
|
"number " + Twine(MatchTy));
|
[tablegen] Add locations to many PrintFatalError() calls
Summary:
While working on the GISel Combiner, I noticed I was producing location-less
error messages fairly often and set about fixing this. In the process, I
noticed quite a few places elsewhere in TableGen that also neglected to include
a relevant location.
This patch adds locations to errors that relate to a specific record (or a
field within it) and also have easy access to the relevant location. This is
particularly useful when multiclasses are involved as many of these errors
refer to the full name of a record and it's difficult to guess which substring
is grep-able.
Unfortunately, tablegen currently only supports Record granularity so it's not
currently possible to point at a specific Init so these sometimes point at the
record that caused the error rather than the precise origin of the error.
Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle
Reviewed By: nhaehnle
Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58077
llvm-svn: 353862
2019-02-13 01:36:57 +08:00
|
|
|
PrintFatalError(DefLoc,
|
|
|
|
Twine("ParamTypes is ") + TypeList->getAsString());
|
2018-04-02 01:08:49 +08:00
|
|
|
}
|
2009-04-17 05:51:05 +08:00
|
|
|
VT = OverloadedVTs[MatchTy];
|
2009-01-07 08:09:01 +08:00
|
|
|
// It only makes sense to use the extended and truncated vector element
|
|
|
|
// variants with iAny types; otherwise, if the intrinsic is not
|
|
|
|
// overloaded, all the types can be specified directly.
|
2014-03-28 20:31:39 +08:00
|
|
|
assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
|
2014-12-04 17:40:44 +08:00
|
|
|
!TyEl->isSubClassOf("LLVMTruncatedType") &&
|
2019-01-24 00:00:22 +08:00
|
|
|
!TyEl->isSubClassOf("LLVMScalarOrSameVectorWidth")) ||
|
2009-08-12 04:47:22 +08:00
|
|
|
VT == MVT::iAny || VT == MVT::vAny) &&
|
2009-08-11 13:03:38 +08:00
|
|
|
"Expected iAny or vAny type");
|
2009-01-07 08:09:01 +08:00
|
|
|
} else
|
|
|
|
VT = getValueType(TyEl->getValueAsDef("VT"));
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2010-03-24 07:46:27 +08:00
|
|
|
// Reject invalid types.
|
|
|
|
if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
|
[tablegen] Add locations to many PrintFatalError() calls
Summary:
While working on the GISel Combiner, I noticed I was producing location-less
error messages fairly often and set about fixing this. In the process, I
noticed quite a few places elsewhere in TableGen that also neglected to include
a relevant location.
This patch adds locations to errors that relate to a specific record (or a
field within it) and also have easy access to the relevant location. This is
particularly useful when multiclasses are involved as many of these errors
refer to the full name of a record and it's difficult to guess which substring
is grep-able.
Unfortunately, tablegen currently only supports Record granularity so it's not
currently possible to point at a specific Init so these sometimes point at the
record that caused the error rather than the precise origin of the error.
Reviewers: bogner, aditya_nandakumar, volkan, aemerson, paquette, nhaehnle
Reviewed By: nhaehnle
Subscribers: jdoerfert, nhaehnle, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58077
llvm-svn: 353862
2019-02-13 01:36:57 +08:00
|
|
|
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
|
|
|
|
" has void in result type list!");
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2008-11-13 17:08:33 +08:00
|
|
|
IS.ParamVTs.push_back(VT);
|
|
|
|
IS.ParamTypeDefs.push_back(TyEl);
|
|
|
|
}
|
|
|
|
|
2006-03-25 03:49:31 +08:00
|
|
|
// Parse the intrinsic properties.
|
2016-02-11 02:40:04 +08:00
|
|
|
ListInit *PropList = R->getValueAsListInit("IntrProperties");
|
2015-06-02 12:15:57 +08:00
|
|
|
for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
|
2007-02-28 06:08:27 +08:00
|
|
|
Record *Property = PropList->getElementAsRecord(i);
|
2006-03-25 03:49:31 +08:00
|
|
|
assert(Property->isSubClassOf("IntrinsicProperty") &&
|
|
|
|
"Expected a property!");
|
2011-03-11 09:27:24 +08:00
|
|
|
|
2006-04-11 06:02:59 +08:00
|
|
|
if (Property->getName() == "IntrNoMem")
|
2006-03-25 03:49:31 +08:00
|
|
|
ModRef = NoMem;
|
|
|
|
else if (Property->getName() == "IntrReadMem")
|
2016-04-22 01:48:02 +08:00
|
|
|
ModRef = ModRefBehavior(ModRef & ~MR_Mod);
|
2016-04-20 05:58:33 +08:00
|
|
|
else if (Property->getName() == "IntrWriteMem")
|
2016-04-22 01:48:02 +08:00
|
|
|
ModRef = ModRefBehavior(ModRef & ~MR_Ref);
|
|
|
|
else if (Property->getName() == "IntrArgMemOnly")
|
2016-11-23 03:16:04 +08:00
|
|
|
ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem);
|
|
|
|
else if (Property->getName() == "IntrInaccessibleMemOnly")
|
|
|
|
ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_InaccessibleMem);
|
|
|
|
else if (Property->getName() == "IntrInaccessibleMemOrArgMemOnly")
|
|
|
|
ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem |
|
|
|
|
MR_InaccessibleMem);
|
2008-06-17 04:29:38 +08:00
|
|
|
else if (Property->getName() == "Commutative")
|
|
|
|
isCommutative = true;
|
2011-05-28 14:31:34 +08:00
|
|
|
else if (Property->getName() == "Throws")
|
|
|
|
canThrow = true;
|
2014-03-19 07:51:07 +08:00
|
|
|
else if (Property->getName() == "IntrNoDuplicate")
|
|
|
|
isNoDuplicate = true;
|
2015-05-27 07:48:40 +08:00
|
|
|
else if (Property->getName() == "IntrConvergent")
|
|
|
|
isConvergent = true;
|
2012-05-28 07:20:41 +08:00
|
|
|
else if (Property->getName() == "IntrNoReturn")
|
|
|
|
isNoReturn = true;
|
2019-07-17 23:15:43 +08:00
|
|
|
else if (Property->getName() == "IntrWillReturn")
|
|
|
|
isWillReturn = true;
|
2018-11-15 03:53:41 +08:00
|
|
|
else if (Property->getName() == "IntrCold")
|
|
|
|
isCold = true;
|
2017-04-29 04:25:27 +08:00
|
|
|
else if (Property->getName() == "IntrSpeculatable")
|
|
|
|
isSpeculatable = true;
|
2017-04-29 05:01:46 +08:00
|
|
|
else if (Property->getName() == "IntrHasSideEffects")
|
|
|
|
hasSideEffects = true;
|
2009-01-12 09:12:03 +08:00
|
|
|
else if (Property->isSubClassOf("NoCapture")) {
|
|
|
|
unsigned ArgNo = Property->getValueAsInt("ArgNo");
|
|
|
|
ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture));
|
2019-08-14 16:33:07 +08:00
|
|
|
} else if (Property->isSubClassOf("NoAlias")) {
|
|
|
|
unsigned ArgNo = Property->getValueAsInt("ArgNo");
|
|
|
|
ArgumentAttributes.push_back(std::make_pair(ArgNo, NoAlias));
|
2016-07-11 09:28:42 +08:00
|
|
|
} else if (Property->isSubClassOf("Returned")) {
|
|
|
|
unsigned ArgNo = Property->getValueAsInt("ArgNo");
|
|
|
|
ArgumentAttributes.push_back(std::make_pair(ArgNo, Returned));
|
2013-07-06 08:29:58 +08:00
|
|
|
} else if (Property->isSubClassOf("ReadOnly")) {
|
|
|
|
unsigned ArgNo = Property->getValueAsInt("ArgNo");
|
|
|
|
ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly));
|
2016-07-04 16:01:29 +08:00
|
|
|
} else if (Property->isSubClassOf("WriteOnly")) {
|
|
|
|
unsigned ArgNo = Property->getValueAsInt("ArgNo");
|
|
|
|
ArgumentAttributes.push_back(std::make_pair(ArgNo, WriteOnly));
|
2013-07-06 08:29:58 +08:00
|
|
|
} else if (Property->isSubClassOf("ReadNone")) {
|
|
|
|
unsigned ArgNo = Property->getValueAsInt("ArgNo");
|
|
|
|
ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone));
|
2019-03-13 05:02:54 +08:00
|
|
|
} else if (Property->isSubClassOf("ImmArg")) {
|
|
|
|
unsigned ArgNo = Property->getValueAsInt("ArgNo");
|
|
|
|
ArgumentAttributes.push_back(std::make_pair(ArgNo, ImmArg));
|
2009-01-12 09:12:03 +08:00
|
|
|
} else
|
2012-02-05 15:21:30 +08:00
|
|
|
llvm_unreachable("Unknown property!");
|
2006-03-25 03:49:31 +08:00
|
|
|
}
|
2011-05-28 14:31:34 +08:00
|
|
|
|
2017-12-21 03:36:28 +08:00
|
|
|
// Also record the SDPatternOperator Properties.
|
|
|
|
Properties = parseSDPatternOperatorProperties(R);
|
|
|
|
|
2011-05-28 14:31:34 +08:00
|
|
|
// Sort the argument attributes for later benefit.
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 10:13:45 +08:00
|
|
|
llvm::sort(ArgumentAttributes);
|
2006-03-25 03:49:31 +08:00
|
|
|
}
|
2019-08-21 06:04:10 +08:00
|
|
|
|
|
|
|
bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
|
|
|
|
if (ParamIdx >= IS.ParamVTs.size())
|
|
|
|
return false;
|
|
|
|
MVT ParamType = MVT(IS.ParamVTs[ParamIdx]);
|
|
|
|
return ParamType == MVT::iPTR || ParamType == MVT::iPTRAny;
|
|
|
|
}
|
2020-01-09 04:40:37 +08:00
|
|
|
|
|
|
|
bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {
|
|
|
|
std::pair<unsigned, ArgAttribute> Val = {ParamIdx, ImmArg};
|
|
|
|
return std::binary_search(ArgumentAttributes.begin(),
|
|
|
|
ArgumentAttributes.end(), Val);
|
|
|
|
}
|