aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/WebAssembly
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-23 17:38:08 +0000
commit320d4fb58b6b1c6a0c7ffeab3d4672d1479d5e17 (patch)
tree4b5e279a6f091bb6bdc639752cf4139dfd7053a4 /contrib/llvm-project/llvm/lib/Target/WebAssembly
parent814cfa6ad43c73de9b8030f241f516dad3f669ef (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/WebAssembly')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp70
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp22
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp21
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h66
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h3
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.h35
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.td8
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp20
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.h1
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp52
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp7
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h6
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISD.def1
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp120
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp211
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h6
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td582
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp29
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.h3
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td333
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td179
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td4
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp28
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp27
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h20
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp22
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp9
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp7
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp39
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h11
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp23
-rw-r--r--contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h10
47 files changed, 814 insertions, 1217 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 7bafa53af2af..1cba0843f891 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -210,6 +210,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
// guarantee that correct order.
enum ParserState {
FileStart,
+ FunctionLabel,
FunctionStart,
FunctionLocals,
Instructions,
@@ -273,11 +274,11 @@ public:
#include "WebAssemblyGenAsmMatcher.inc"
// TODO: This is required to be implemented, but appears unused.
- bool ParseRegister(unsigned & /*RegNo*/, SMLoc & /*StartLoc*/,
+ bool parseRegister(MCRegister & /*RegNo*/, SMLoc & /*StartLoc*/,
SMLoc & /*EndLoc*/) override {
- llvm_unreachable("ParseRegister is not implemented.");
+ llvm_unreachable("parseRegister is not implemented.");
}
- OperandMatchResultTy tryParseRegister(unsigned & /*RegNo*/,
+ OperandMatchResultTy tryParseRegister(MCRegister & /*RegNo*/,
SMLoc & /*StartLoc*/,
SMLoc & /*EndLoc*/) override {
llvm_unreachable("tryParseRegister is not implemented.");
@@ -287,8 +288,8 @@ public:
return Parser.Error(Tok.getLoc(), Msg + Tok.getString());
}
- bool error(const Twine &Msg) {
- return Parser.Error(Lexer.getTok().getLoc(), Msg);
+ bool error(const Twine &Msg, SMLoc Loc = SMLoc()) {
+ return Parser.Error(Loc.isValid() ? Loc : Lexer.getTok().getLoc(), Msg);
}
void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
@@ -336,11 +337,12 @@ public:
return false;
}
- bool ensureEmptyNestingStack() {
+ bool ensureEmptyNestingStack(SMLoc Loc = SMLoc()) {
auto Err = !NestingStack.empty();
while (!NestingStack.empty()) {
error(Twine("Unmatched block construct(s) at function end: ") +
- nestingString(NestingStack.back().NT).first);
+ nestingString(NestingStack.back().NT).first,
+ Loc);
NestingStack.pop_back();
}
return Err;
@@ -835,7 +837,8 @@ public:
auto ElemTypeName = expectIdent();
if (ElemTypeName.empty())
return true;
- Optional<wasm::ValType> ElemType = WebAssembly::parseType(ElemTypeName);
+ std::optional<wasm::ValType> ElemType =
+ WebAssembly::parseType(ElemTypeName);
if (!ElemType)
return error("Unknown type in .tabletype directive: ", ElemTypeTok);
@@ -864,12 +867,24 @@ public:
return true;
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
if (WasmSym->isDefined()) {
- // This .functype indicates a start of a function.
- if (ensureEmptyNestingStack())
- return true;
+ // We push 'Function' either when a label is parsed or a .functype
+ // directive is parsed. The reason it is not easy to do this uniformly
+ // in a single place is,
+ // 1. We can't do this at label parsing time only because there are
+ // cases we don't have .functype directive before a function label,
+ // in which case we don't know if the label is a function at the time
+ // of parsing.
+ // 2. We can't do this at .functype parsing time only because we want to
+ // detect a function started with a label and not ended correctly
+ // without encountering a .functype directive after the label.
+ if (CurrentState != FunctionLabel) {
+ // This .functype indicates a start of a function.
+ if (ensureEmptyNestingStack())
+ return true;
+ push(Function);
+ }
CurrentState = FunctionStart;
LastFunctionLabel = WasmSym;
- push(Function);
}
auto Signature = std::make_unique<wasm::WasmSignature>();
if (parseSignature(Signature.get()))
@@ -1057,7 +1072,7 @@ public:
llvm_unreachable("Implement any new match types added!");
}
- void doBeforeLabelEmit(MCSymbol *Symbol) override {
+ void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override {
// Code below only applies to labels in text sections.
auto CWS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
if (!CWS || !CWS->getKind().isText())
@@ -1067,7 +1082,7 @@ public:
// Unlike other targets, we don't allow data in text sections (labels
// declared with .type @object).
if (WasmSym->getType() == wasm::WASM_SYMBOL_TYPE_DATA) {
- Parser.Error(Parser.getTok().getLoc(),
+ Parser.Error(IDLoc,
"Wasm doesn\'t support data symbols in text sections");
return;
}
@@ -1099,6 +1114,22 @@ public:
// Also generate DWARF for this section if requested.
if (getContext().getGenDwarfForAssembly())
getContext().addGenDwarfSection(WS);
+
+ if (WasmSym->isFunction()) {
+ // We give the location of the label (IDLoc) here, because otherwise the
+ // lexer's next location will be used, which can be confusing. For
+ // example:
+ //
+ // test0: ; This function does not end properly
+ // ...
+ //
+ // test1: ; We would like to point to this line for error
+ // ... . Not this line, which can contain any instruction
+ ensureEmptyNestingStack(IDLoc);
+ CurrentState = FunctionLabel;
+ LastFunctionLabel = Symbol;
+ push(Function);
+ }
}
void onEndOfFunction(SMLoc ErrorLoc) {
@@ -1106,17 +1137,6 @@ public:
TC.endOfFunction(ErrorLoc);
// Reset the type checker state.
TC.Clear();
-
- // Automatically output a .size directive, so it becomes optional for the
- // user.
- if (!LastFunctionLabel) return;
- auto TempSym = getContext().createLinkerPrivateTempSymbol();
- getStreamer().emitLabel(TempSym);
- auto Start = MCSymbolRefExpr::create(LastFunctionLabel, getContext());
- auto End = MCSymbolRefExpr::create(TempSym, getContext());
- auto Expr =
- MCBinaryExpr::create(MCBinaryExpr::Sub, End, Start, getContext());
- getStreamer().emitELFSize(LastFunctionLabel, Expr);
}
void onEndOfFile() override { ensureEmptyNestingStack(); }
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
index d31715e367ec..b323b265b562 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
@@ -74,27 +74,27 @@ bool WebAssemblyAsmTypeCheck::typeError(SMLoc ErrorLoc, const Twine &Msg) {
// which are mostly not helpful.
if (TypeErrorThisFunction)
return true;
- // If we're currently in unreachable code, we surpress errors as well.
+ // If we're currently in unreachable code, we suppress errors completely.
if (Unreachable)
- return true;
+ return false;
TypeErrorThisFunction = true;
dumpTypeStack("current stack: ");
return Parser.Error(ErrorLoc, Msg);
}
bool WebAssemblyAsmTypeCheck::popType(SMLoc ErrorLoc,
- Optional<wasm::ValType> EVT) {
+ std::optional<wasm::ValType> EVT) {
if (Stack.empty()) {
return typeError(ErrorLoc,
EVT ? StringRef("empty stack while popping ") +
- WebAssembly::typeToString(EVT.value())
+ WebAssembly::typeToString(*EVT)
: StringRef("empty stack while popping value"));
}
auto PVT = Stack.pop_back_val();
- if (EVT && EVT.value() != PVT) {
- return typeError(
- ErrorLoc, StringRef("popped ") + WebAssembly::typeToString(PVT) +
- ", expected " + WebAssembly::typeToString(EVT.value()));
+ if (EVT && *EVT != PVT) {
+ return typeError(ErrorLoc,
+ StringRef("popped ") + WebAssembly::typeToString(PVT) +
+ ", expected " + WebAssembly::typeToString(*EVT));
}
return false;
}
@@ -184,7 +184,7 @@ bool WebAssemblyAsmTypeCheck::getGlobal(SMLoc ErrorLoc, const MCInst &Inst,
default:
break;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() +
" missing .globaltype");
@@ -331,7 +331,7 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
const auto &II = MII.get(RegOpc);
// First pop all the uses off the stack and check them.
for (unsigned I = II.getNumOperands(); I > II.getNumDefs(); I--) {
- const auto &Op = II.OpInfo[I - 1];
+ const auto &Op = II.operands()[I - 1];
if (Op.OperandType == MCOI::OPERAND_REGISTER) {
auto VT = WebAssembly::regClassToValType(Op.RegClass);
if (popType(ErrorLoc, VT))
@@ -340,7 +340,7 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
}
// Now push all the defs onto the stack.
for (unsigned I = 0; I < II.getNumDefs(); I++) {
- const auto &Op = II.OpInfo[I];
+ const auto &Op = II.operands()[I];
assert(Op.OperandType == MCOI::OPERAND_REGISTER && "Register expected");
auto VT = WebAssembly::regClassToValType(Op.RegClass);
Stack.push_back(VT);
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
index 3be966b5739c..9c190e6beae7 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
@@ -38,7 +38,7 @@ class WebAssemblyAsmTypeCheck final {
void dumpTypeStack(Twine Msg);
bool typeError(SMLoc ErrorLoc, const Twine &Msg);
- bool popType(SMLoc ErrorLoc, Optional<wasm::ValType> EVT);
+ bool popType(SMLoc ErrorLoc, std::optional<wasm::ValType> EVT);
bool popRefType(SMLoc ErrorLoc);
bool getLocal(SMLoc ErrorLoc, const MCInst &Inst, wasm::ValType &Type);
bool checkEnd(SMLoc ErrorLoc, bool PopVals = false);
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
index ae65a9dc2a4e..1f07b1619b49 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
@@ -45,10 +45,9 @@ class WebAssemblyDisassembler final : public MCDisassembler {
DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream &CStream) const override;
- Optional<DecodeStatus> onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size,
- ArrayRef<uint8_t> Bytes,
- uint64_t Address,
- raw_ostream &CStream) const override;
+ std::optional<DecodeStatus>
+ onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size, ArrayRef<uint8_t> Bytes,
+ uint64_t Address, raw_ostream &CStream) const override;
public:
WebAssemblyDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
@@ -121,29 +120,31 @@ bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes) {
return true;
}
-Optional<MCDisassembler::DecodeStatus> WebAssemblyDisassembler::onSymbolStart(
- SymbolInfoTy &Symbol, uint64_t &Size, ArrayRef<uint8_t> Bytes,
- uint64_t Address, raw_ostream &CStream) const {
+std::optional<MCDisassembler::DecodeStatus>
+WebAssemblyDisassembler::onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes,
+ uint64_t Address,
+ raw_ostream &CStream) const {
Size = 0;
if (Address == 0) {
// Start of a code section: we're parsing only the function count.
int64_t FunctionCount;
if (!nextLEB(FunctionCount, Bytes, Size, false))
- return None;
+ return std::nullopt;
outs() << " # " << FunctionCount << " functions in section.";
} else {
// Parse the start of a single function.
int64_t BodySize, LocalEntryCount;
if (!nextLEB(BodySize, Bytes, Size, false) ||
!nextLEB(LocalEntryCount, Bytes, Size, false))
- return None;
+ return std::nullopt;
if (LocalEntryCount) {
outs() << " .local ";
for (int64_t I = 0; I < LocalEntryCount; I++) {
int64_t Count, Type;
if (!nextLEB(Count, Bytes, Size, false) ||
!nextLEB(Type, Bytes, Size, false))
- return None;
+ return std::nullopt;
for (int64_t J = 0; J < Count; J++) {
if (I || J)
outs() << ", ";
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
index d72bfdbbfb99..b925519e6162 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
@@ -39,10 +39,10 @@ WebAssemblyInstPrinter::WebAssemblyInstPrinter(const MCAsmInfo &MAI,
: MCInstPrinter(MAI, MII, MRI) {}
void WebAssemblyInstPrinter::printRegName(raw_ostream &OS,
- unsigned RegNo) const {
- assert(RegNo != WebAssemblyFunctionInfo::UnusedReg);
+ MCRegister Reg) const {
+ assert(Reg.id() != WebAssemblyFunctionInfo::UnusedReg);
// Note that there's an implicit local.get/local.set here!
- OS << "$" << RegNo;
+ OS << "$" << Reg.id();
}
void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
@@ -240,7 +240,7 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
// See if this operand denotes a basic block target.
if (I < NumFixedOperands) {
// A non-variable_ops operand, check its type.
- if (Desc.OpInfo[I].OperandType != WebAssembly::OPERAND_BASIC_BLOCK)
+ if (Desc.operands()[I].OperandType != WebAssembly::OPERAND_BASIC_BLOCK)
continue;
} else {
// A variable_ops operand, which currently can be immediates (used in
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h
index fe104cbca12e..c81c3a3d9ffa 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h
@@ -35,7 +35,7 @@ public:
WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI);
- void printRegName(raw_ostream &OS, unsigned RegNo) const override;
+ void printRegName(raw_ostream &OS, MCRegister Reg) const override;
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &OS) override;
@@ -51,7 +51,7 @@ public:
// Autogenerated by tblgen.
std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
- static const char *getRegisterName(unsigned RegNo);
+ static const char *getRegisterName(MCRegister Reg);
};
} // end namespace llvm
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
index 6e494b9430f7..cd692f4dda33 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
@@ -92,7 +92,7 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
} else if (MO.isImm()) {
if (I < Desc.getNumOperands()) {
- const MCOperandInfo &Info = Desc.OpInfo[I];
+ const MCOperandInfo &Info = Desc.operands()[I];
LLVM_DEBUG(dbgs() << "Encoding immediate: type="
<< int(Info.OperandType) << "\n");
switch (Info.OperandType) {
@@ -134,7 +134,7 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
uint64_t D = MO.getDFPImm();
support::endian::write<uint64_t>(OS, D, support::little);
} else if (MO.isExpr()) {
- const MCOperandInfo &Info = Desc.OpInfo[I];
+ const MCOperandInfo &Info = Desc.operands()[I];
llvm::MCFixupKind FixupKind;
size_t PaddedSize = 5;
switch (Info.OperandType) {
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
index b5b12200505b..476955e434f2 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
@@ -416,6 +416,72 @@ inline bool isCatch(unsigned Opc) {
}
}
+inline bool isLocalGet(unsigned Opc) {
+ switch (Opc) {
+ case WebAssembly::LOCAL_GET_I32:
+ case WebAssembly::LOCAL_GET_I32_S:
+ case WebAssembly::LOCAL_GET_I64:
+ case WebAssembly::LOCAL_GET_I64_S:
+ case WebAssembly::LOCAL_GET_F32:
+ case WebAssembly::LOCAL_GET_F32_S:
+ case WebAssembly::LOCAL_GET_F64:
+ case WebAssembly::LOCAL_GET_F64_S:
+ case WebAssembly::LOCAL_GET_V128:
+ case WebAssembly::LOCAL_GET_V128_S:
+ case WebAssembly::LOCAL_GET_FUNCREF:
+ case WebAssembly::LOCAL_GET_FUNCREF_S:
+ case WebAssembly::LOCAL_GET_EXTERNREF:
+ case WebAssembly::LOCAL_GET_EXTERNREF_S:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline bool isLocalSet(unsigned Opc) {
+ switch (Opc) {
+ case WebAssembly::LOCAL_SET_I32:
+ case WebAssembly::LOCAL_SET_I32_S:
+ case WebAssembly::LOCAL_SET_I64:
+ case WebAssembly::LOCAL_SET_I64_S:
+ case WebAssembly::LOCAL_SET_F32:
+ case WebAssembly::LOCAL_SET_F32_S:
+ case WebAssembly::LOCAL_SET_F64:
+ case WebAssembly::LOCAL_SET_F64_S:
+ case WebAssembly::LOCAL_SET_V128:
+ case WebAssembly::LOCAL_SET_V128_S:
+ case WebAssembly::LOCAL_SET_FUNCREF:
+ case WebAssembly::LOCAL_SET_FUNCREF_S:
+ case WebAssembly::LOCAL_SET_EXTERNREF:
+ case WebAssembly::LOCAL_SET_EXTERNREF_S:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline bool isLocalTee(unsigned Opc) {
+ switch (Opc) {
+ case WebAssembly::LOCAL_TEE_I32:
+ case WebAssembly::LOCAL_TEE_I32_S:
+ case WebAssembly::LOCAL_TEE_I64:
+ case WebAssembly::LOCAL_TEE_I64_S:
+ case WebAssembly::LOCAL_TEE_F32:
+ case WebAssembly::LOCAL_TEE_F32_S:
+ case WebAssembly::LOCAL_TEE_F64:
+ case WebAssembly::LOCAL_TEE_F64_S:
+ case WebAssembly::LOCAL_TEE_V128:
+ case WebAssembly::LOCAL_TEE_V128_S:
+ case WebAssembly::LOCAL_TEE_FUNCREF:
+ case WebAssembly::LOCAL_TEE_FUNCREF_S:
+ case WebAssembly::LOCAL_TEE_EXTERNREF:
+ case WebAssembly::LOCAL_TEE_EXTERNREF_S:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // end namespace WebAssembly
} // end namespace llvm
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
index f380b2582c65..998905402b39 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
@@ -21,7 +21,7 @@
using namespace llvm;
-Optional<wasm::ValType> WebAssembly::parseType(StringRef Type) {
+std::optional<wasm::ValType> WebAssembly::parseType(StringRef Type) {
// FIXME: can't use StringSwitch because wasm::ValType doesn't have a
// "invalid" value.
if (Type == "i32")
@@ -39,7 +39,7 @@ Optional<wasm::ValType> WebAssembly::parseType(StringRef Type) {
return wasm::ValType::FUNCREF;
if (Type == "externref")
return wasm::ValType::EXTERNREF;
- return Optional<wasm::ValType>();
+ return std::nullopt;
}
WebAssembly::BlockType WebAssembly::parseBlockType(StringRef Type) {
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
index 86211700c70a..33f3bf31595d 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
@@ -15,7 +15,6 @@
#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WEBASSEMBLYTYPEUTILITIES_H
#define LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WEBASSEMBLYTYPEUTILITIES_H
-#include "llvm/ADT/Optional.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/MC/MCSymbolWasm.h"
@@ -89,7 +88,7 @@ inline bool isRefType(wasm::ValType Type) {
// Convert StringRef to ValType / HealType / BlockType
-Optional<wasm::ValType> parseType(StringRef Type);
+std::optional<wasm::ValType> parseType(StringRef Type);
BlockType parseBlockType(StringRef Type);
MVT parseMVT(StringRef Type);
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp
index 277bbee83a6f..a1e0db692390 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp
@@ -58,7 +58,7 @@ bool WebAssembly::isChild(const MachineInstr &MI,
if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
return false;
Register Reg = MO.getReg();
- return Register::isVirtualRegister(Reg) && MFI.isVRegStackified(Reg);
+ return Reg.isVirtual() && MFI.isVRegStackified(Reg);
}
bool WebAssembly::mayThrow(const MachineInstr &MI) {
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.h
index aee8f160f38d..53be8f5b67b4 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.h
@@ -57,31 +57,32 @@ FunctionPass *createWebAssemblyPeephole();
ModulePass *createWebAssemblyMCLowerPrePass();
// PassRegistry initialization declarations.
-void initializeWebAssemblyAddMissingPrototypesPass(PassRegistry &);
-void initializeWebAssemblyLowerEmscriptenEHSjLjPass(PassRegistry &);
void initializeFixFunctionBitcastsPass(PassRegistry &);
void initializeOptimizeReturnedPass(PassRegistry &);
+void initializeWebAssemblyAddMissingPrototypesPass(PassRegistry &);
void initializeWebAssemblyArgumentMovePass(PassRegistry &);
-void initializeWebAssemblySetP2AlignOperandsPass(PassRegistry &);
-void initializeWebAssemblyReplacePhysRegsPass(PassRegistry &);
-void initializeWebAssemblyNullifyDebugValueListsPass(PassRegistry &);
-void initializeWebAssemblyOptimizeLiveIntervalsPass(PassRegistry &);
-void initializeWebAssemblyMemIntrinsicResultsPass(PassRegistry &);
-void initializeWebAssemblyRegStackifyPass(PassRegistry &);
-void initializeWebAssemblyRegColoringPass(PassRegistry &);
-void initializeWebAssemblyFixBrTableDefaultsPass(PassRegistry &);
-void initializeWebAssemblyFixIrreducibleControlFlowPass(PassRegistry &);
-void initializeWebAssemblyLateEHPreparePass(PassRegistry &);
-void initializeWebAssemblyExceptionInfoPass(PassRegistry &);
void initializeWebAssemblyCFGSortPass(PassRegistry &);
void initializeWebAssemblyCFGStackifyPass(PassRegistry &);
+void initializeWebAssemblyDAGToDAGISelPass(PassRegistry &);
+void initializeWebAssemblyDebugFixupPass(PassRegistry &);
+void initializeWebAssemblyExceptionInfoPass(PassRegistry &);
void initializeWebAssemblyExplicitLocalsPass(PassRegistry &);
+void initializeWebAssemblyFixBrTableDefaultsPass(PassRegistry &);
+void initializeWebAssemblyFixIrreducibleControlFlowPass(PassRegistry &);
+void initializeWebAssemblyLateEHPreparePass(PassRegistry &);
void initializeWebAssemblyLowerBrUnlessPass(PassRegistry &);
-void initializeWebAssemblyRegNumberingPass(PassRegistry &);
-void initializeWebAssemblyDebugFixupPass(PassRegistry &);
-void initializeWebAssemblyPeepholePass(PassRegistry &);
-void initializeWebAssemblyMCLowerPrePassPass(PassRegistry &);
+void initializeWebAssemblyLowerEmscriptenEHSjLjPass(PassRegistry &);
void initializeWebAssemblyLowerRefTypesIntPtrConvPass(PassRegistry &);
+void initializeWebAssemblyMCLowerPrePassPass(PassRegistry &);
+void initializeWebAssemblyMemIntrinsicResultsPass(PassRegistry &);
+void initializeWebAssemblyNullifyDebugValueListsPass(PassRegistry &);
+void initializeWebAssemblyOptimizeLiveIntervalsPass(PassRegistry &);
+void initializeWebAssemblyPeepholePass(PassRegistry &);
+void initializeWebAssemblyRegColoringPass(PassRegistry &);
+void initializeWebAssemblyRegNumberingPass(PassRegistry &);
+void initializeWebAssemblyRegStackifyPass(PassRegistry &);
+void initializeWebAssemblyReplacePhysRegsPass(PassRegistry &);
+void initializeWebAssemblySetP2AlignOperandsPass(PassRegistry &);
namespace WebAssembly {
enum TargetIndex {
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.td b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.td
index b83dcf3a8e65..7531d36a74a6 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.td
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssembly.td
@@ -97,7 +97,13 @@ def WebAssemblyInstrInfo : InstrInfo;
def : ProcessorModel<"mvp", NoSchedModel, []>;
// Generic processor: latest stable version.
-def : ProcessorModel<"generic", NoSchedModel, []>;
+//
+// This includes features that have achieved phase 4 of the standards process,
+// and that are expected to work for most users in the current time, with
+// consideration given to available support in relevant engines and tools, and
+// the importance of the features.
+def : ProcessorModel<"generic", NoSchedModel,
+ [FeatureSignExt, FeatureMutableGlobals]>;
// Latest and greatest experimental version of WebAssembly. Bugs included!
def : ProcessorModel<"bleeding-edge", NoSchedModel,
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index bcb6cf1b4e1d..60b1b3f5fc27 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -70,7 +70,7 @@ MVT WebAssemblyAsmPrinter::getRegType(unsigned RegNo) const {
std::string WebAssemblyAsmPrinter::regToString(const MachineOperand &MO) {
Register RegNo = MO.getReg();
- assert(Register::isVirtualRegister(RegNo) &&
+ assert(RegNo.isVirtual() &&
"Unlowered physical register encountered during assembly printing");
assert(!MFI->isVRegStackified(RegNo));
unsigned WAReg = MFI->getWAReg(RegNo);
@@ -272,7 +272,7 @@ MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) {
}
void WebAssemblyAsmPrinter::emitSymbolType(const MCSymbolWasm *Sym) {
- Optional<wasm::WasmSymbolType> WasmTy = Sym->getType();
+ std::optional<wasm::WasmSymbolType> WasmTy = Sym->getType();
if (!WasmTy)
return;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp
index 2257d1562513..497ab5440678 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp
@@ -235,7 +235,7 @@ static void sortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI,
// any blocks deferred because the header didn't dominate them.
for (Entry &E : Entries)
if (E.TheRegion->contains(MBB) && --E.NumBlocksLeft == 0)
- for (auto DeferredBlock : E.Deferred)
+ for (auto *DeferredBlock : E.Deferred)
Ready.push(DeferredBlock);
while (!Entries.empty() && Entries.back().NumBlocksLeft == 0)
Entries.pop_back();
@@ -348,14 +348,14 @@ static void sortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI,
if (Region->isLoop()) {
// Loop header. The loop predecessor should be sorted above, and the
// other predecessors should be backedges below.
- for (auto Pred : MBB.predecessors())
+ for (auto *Pred : MBB.predecessors())
assert(
(Pred->getNumber() < MBB.getNumber() || Region->contains(Pred)) &&
"Loop header predecessors must be loop predecessors or "
"backedges");
} else {
// Exception header. All predecessors should be sorted above.
- for (auto Pred : MBB.predecessors())
+ for (auto *Pred : MBB.predecessors())
assert(Pred->getNumber() < MBB.getNumber() &&
"Non-loop-header predecessors should be topologically sorted");
}
@@ -364,7 +364,7 @@ static void sortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI,
} else {
// Not a region header. All predecessors should be sorted above.
- for (auto Pred : MBB.predecessors())
+ for (auto *Pred : MBB.predecessors())
assert(Pred->getNumber() < MBB.getNumber() &&
"Non-loop-header predecessors should be topologically sorted");
assert(OnStack.count(SRI.getRegionFor(&MBB)) &&
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index d2eb4b29e9fd..70c187af73a5 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -792,7 +792,7 @@ static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB,
for (auto &MI : Split) {
for (auto &MO : MI.explicit_uses()) {
- if (!MO.isReg() || Register::isPhysicalRegister(MO.getReg()))
+ if (!MO.isReg() || MO.getReg().isPhysical())
continue;
if (MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg()))
if (Def->getParent() == &MBB)
@@ -1501,7 +1501,7 @@ void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
std::next(WebAssembly::findCatch(EHPad)->getReverseIterator());
if (NextIt != EHPad->rend())
Worklist.push_back(NextIt);
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
}
case WebAssembly::END_BLOCK:
case WebAssembly::END_LOOP:
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp
index e06e359fc592..9a6acd157a74 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyDebugFixup.cpp
@@ -59,6 +59,24 @@ FunctionPass *llvm::createWebAssemblyDebugFixup() {
return new WebAssemblyDebugFixup();
}
+// At this very end of the compilation pipeline, if any DBG_VALUEs with
+// registers remain, it means they are dangling info which we failed to update
+// when their corresponding def instruction was transformed/moved/splitted etc.
+// Because Wasm cannot access values in LLVM virtual registers in the debugger,
+// these dangling DBG_VALUEs in effect kill the effect of any previous DBG_VALUE
+// associated with the variable, which will appear as "optimized out".
+static void nullifyDanglingDebugValues(MachineBasicBlock &MBB,
+ const TargetInstrInfo *TII) {
+ for (auto &MI : llvm::make_early_inc_range(MBB)) {
+ if (MI.isDebugValue() && MI.getDebugOperand(0).isReg() &&
+ !MI.isUndefDebugValue()) {
+ LLVM_DEBUG(dbgs() << "Warning: dangling DBG_VALUE nullified: " << MI
+ << "\n");
+ MI.getDebugOperand(0).setReg(Register());
+ }
+ }
+}
+
bool WebAssemblyDebugFixup::runOnMachineFunction(MachineFunction &MF) {
LLVM_DEBUG(dbgs() << "********** Debug Fixup **********\n"
"********** Function: "
@@ -135,6 +153,8 @@ bool WebAssemblyDebugFixup::runOnMachineFunction(MachineFunction &MF) {
}
assert(Stack.empty() &&
"WebAssemblyDebugFixup: Stack not empty at end of basic block!");
+
+ nullifyDanglingDebugValues(MBB, TII);
}
return true;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.cpp
index 81fe5395a6de..7e63b6b97632 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.cpp
@@ -80,7 +80,7 @@ void WebAssemblyExceptionInfo::recalculate(
const MachineDominanceFrontier &MDF) {
// Postorder traversal of the dominator tree.
SmallVector<std::unique_ptr<WebAssemblyException>, 8> Exceptions;
- for (auto DomNode : post_order(&MDT)) {
+ for (auto *DomNode : post_order(&MDT)) {
MachineBasicBlock *EHPad = DomNode->getBlock();
if (!EHPad->isEHPad())
continue;
@@ -238,7 +238,7 @@ void WebAssemblyExceptionInfo::recalculate(
}
// Add BBs to exceptions' block vector
- for (auto DomNode : post_order(&MDT)) {
+ for (auto *DomNode : post_order(&MDT)) {
MachineBasicBlock *MBB = DomNode->getBlock();
WebAssemblyException *WE = getExceptionFor(MBB);
for (; WE; WE = WE->getParentException())
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.h
index e330188d2382..3c0add4b53d7 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExceptionInfo.h
@@ -15,7 +15,6 @@
#define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYEXCEPTIONINFO_H
#include "WebAssembly.h"
-#include "llvm/ADT/SetVector.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
namespace llvm {
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index 8ddd414b043a..1bb2d6bf9e79 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -388,7 +388,7 @@ void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
: &WebAssembly::I32RegClass);
unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
: WebAssembly::CONST_I32;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), Reg)
.addImm(0);
Addr.setReg(Reg);
}
@@ -460,12 +460,12 @@ unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
}
Register Imm = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::CONST_I32), Imm)
.addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
Register Result = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::AND_I32), Result)
.addReg(Reg)
.addReg(Imm);
@@ -490,18 +490,18 @@ unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
}
Register Imm = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::CONST_I32), Imm)
.addImm(32 - MVT(From).getSizeInBits());
Register Left = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::SHL_I32), Left)
.addReg(Reg)
.addReg(Imm);
Register Right = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::SHR_S_I32), Right)
.addReg(Left)
.addReg(Imm);
@@ -519,7 +519,7 @@ unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
Reg = zeroExtendToI32(Reg, V, From);
Register Result = createResultReg(&WebAssembly::I64RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
.addReg(Reg);
return Result;
@@ -541,7 +541,7 @@ unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
Reg = signExtendToI32(Reg, V, From);
Register Result = createResultReg(&WebAssembly::I64RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
.addReg(Reg);
return Result;
@@ -580,7 +580,7 @@ unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
Register NotReg = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::EQZ_I32), NotReg)
.addReg(Reg);
return NotReg;
@@ -588,7 +588,7 @@ unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
Register ResultReg = createResultReg(MRI.getRegClass(Reg));
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(WebAssembly::COPY),
ResultReg)
.addReg(Reg);
return ResultReg;
@@ -604,7 +604,7 @@ unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
: &WebAssembly::I32RegClass);
unsigned Opc =
Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
.addFrameIndex(SI->second);
return ResultReg;
}
@@ -623,7 +623,7 @@ unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
: &WebAssembly::I32RegClass);
unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
: WebAssembly::CONST_I32;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
.addGlobalAddress(GV);
return ResultReg;
}
@@ -717,7 +717,7 @@ bool WebAssemblyFastISel::fastLowerArguments() {
return false;
}
Register ResultReg = createResultReg(RC);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
.addImm(I);
updateValueMap(&Arg, ResultReg);
@@ -859,7 +859,7 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
return false;
}
- auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
+ auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc));
if (!IsVoid)
MIB.addReg(ResultReg, RegState::Define);
@@ -886,7 +886,7 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
// as 64-bit for uniformity with other pointer types.
// See also: WebAssemblyISelLowering.cpp: LowerCallResults
if (Subtarget->hasAddr64()) {
- auto Wrap = BuildMI(*FuncInfo.MBB, std::prev(FuncInfo.InsertPt), DbgLoc,
+ auto Wrap = BuildMI(*FuncInfo.MBB, std::prev(FuncInfo.InsertPt), MIMD,
TII.get(WebAssembly::I32_WRAP_I64));
Register Reg32 = createResultReg(&WebAssembly::I32RegClass);
Wrap.addReg(Reg32, RegState::Define);
@@ -961,7 +961,7 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
}
Register ResultReg = createResultReg(RC);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
.addReg(TrueReg)
.addReg(FalseReg)
.addReg(CondReg);
@@ -979,7 +979,7 @@ bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
Register Result = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::I32_WRAP_I64), Result)
.addReg(Reg);
Reg = Result;
@@ -1077,7 +1077,7 @@ bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
return false;
Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
.addReg(LHS)
.addReg(RHS);
updateValueMap(ICmp, ResultReg);
@@ -1138,7 +1138,7 @@ bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
}
Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
.addReg(LHS)
.addReg(RHS);
@@ -1231,7 +1231,7 @@ bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
materializeLoadStoreOperands(Addr);
Register ResultReg = createResultReg(RC);
- auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
+ auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc),
ResultReg);
addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
@@ -1260,7 +1260,7 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) {
switch (getSimpleType(Store->getValueOperand()->getType())) {
case MVT::i1:
VTIsi1 = true;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case MVT::i8:
Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
break;
@@ -1291,7 +1291,7 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) {
if (VTIsi1)
ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
- auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
+ auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc));
addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
@@ -1319,7 +1319,7 @@ bool WebAssemblyFastISel::selectBr(const Instruction *I) {
if (Not)
Opc = WebAssembly::BR_UNLESS;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))
.addMBB(TBB)
.addReg(CondReg);
@@ -1334,7 +1334,7 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
const auto *Ret = cast<ReturnInst>(I);
if (Ret->getNumOperands() == 0) {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::RETURN));
return true;
}
@@ -1379,14 +1379,14 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
if (Reg == 0)
return false;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::RETURN))
.addReg(Reg);
return true;
}
bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::UNREACHABLE));
return true;
}
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp
index 2a4349e02f1b..b3fe110a092b 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp
@@ -141,7 +141,7 @@ static Function *createWrapper(Function *F, FunctionType *Ty) {
if (CastInst::isBitOrNoopPointerCastable(ArgType, ParamType, DL)) {
Instruction *PtrCast =
CastInst::CreateBitOrPointerCast(AI, ParamType, "cast");
- BB->getInstList().push_back(PtrCast);
+ PtrCast->insertInto(BB, BB->end());
Args.push_back(PtrCast);
} else if (ArgType->isStructTy() || ParamType->isStructTy()) {
LLVM_DEBUG(dbgs() << "createWrapper: struct param type in bitcast: "
@@ -181,7 +181,7 @@ static Function *createWrapper(Function *F, FunctionType *Ty) {
DL)) {
Instruction *Cast =
CastInst::CreateBitOrPointerCast(Call, RtnType, "cast");
- BB->getInstList().push_back(Cast);
+ Cast->insertInto(BB, BB->end());
ReturnInst::Create(M->getContext(), Cast, BB);
} else if (RtnType->isStructTy() || ExpectedRtnType->isStructTy()) {
LLVM_DEBUG(dbgs() << "createWrapper: struct return type in bitcast: "
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp
index 83e71d731bfa..6c46673c36bf 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp
@@ -343,7 +343,7 @@ void WebAssemblyFixIrreducibleControlFlow::makeSingleEntryLoop(
BlockVector SortedEntries = getSortedEntries(Entries);
#ifndef NDEBUG
- for (auto Block : SortedEntries)
+ for (auto *Block : SortedEntries)
assert(Block->getNumber() != -1);
if (SortedEntries.size() > 1) {
for (auto I = SortedEntries.begin(), E = SortedEntries.end() - 1; I != E;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
index 01baa3d9389d..e60f1397b993 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
@@ -50,7 +50,7 @@ using namespace llvm;
// SelectionDAGISel::runOnMachineFunction. We have to do it in two places
// because we want to do it while building the selection DAG for uses of alloca,
// but not all alloca instructions are used so we have to follow up afterwards.
-Optional<unsigned>
+std::optional<unsigned>
WebAssemblyFrameLowering::getLocalForStackObject(MachineFunction &MF,
int FrameIndex) {
MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -62,9 +62,8 @@ WebAssemblyFrameLowering::getLocalForStackObject(MachineFunction &MF,
// If not allocated in the object address space, this object will be in
// linear memory.
const AllocaInst *AI = MFI.getObjectAllocation(FrameIndex);
- if (!AI ||
- !WebAssembly::isWasmVarAddressSpace(AI->getType()->getAddressSpace()))
- return None;
+ if (!AI || !WebAssembly::isWasmVarAddressSpace(AI->getAddressSpace()))
+ return std::nullopt;
// Otherwise, allocate this object in the named value stack, outside of linear
// memory.
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
index d30a3fa52d73..528b33e34bee 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
@@ -55,9 +55,9 @@ public:
const DebugLoc &DL) const;
// Returns the index of the WebAssembly local to which the stack object
- // FrameIndex in MF should be allocated, or None.
- static Optional<unsigned> getLocalForStackObject(MachineFunction &MF,
- int FrameIndex);
+ // FrameIndex in MF should be allocated, or std::nullopt.
+ static std::optional<unsigned> getLocalForStackObject(MachineFunction &MF,
+ int FrameIndex);
static unsigned getSPReg(const MachineFunction &MF);
static unsigned getFPReg(const MachineFunction &MF);
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISD.def b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
index a3a33f4a5b3a..b8954f4693f0 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
@@ -46,7 +46,6 @@ HANDLE_NODETYPE(MEMORY_COPY)
HANDLE_NODETYPE(MEMORY_FILL)
// Memory intrinsics
-HANDLE_MEM_NODETYPE(LOAD_SPLAT)
HANDLE_MEM_NODETYPE(GLOBAL_GET)
HANDLE_MEM_NODETYPE(GLOBAL_SET)
HANDLE_MEM_NODETYPE(TABLE_GET)
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
index 7e75989d3def..df79e55ce4b6 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -29,6 +29,7 @@
using namespace llvm;
#define DEBUG_TYPE "wasm-isel"
+#define PASS_NAME "WebAssembly Instruction Selection"
//===--------------------------------------------------------------------===//
/// WebAssembly-specific code to select WebAssembly machine instructions for
@@ -41,14 +42,13 @@ class WebAssemblyDAGToDAGISel final : public SelectionDAGISel {
const WebAssemblySubtarget *Subtarget;
public:
+ static char ID;
+
+ WebAssemblyDAGToDAGISel() = delete;
+
WebAssemblyDAGToDAGISel(WebAssemblyTargetMachine &TM,
CodeGenOpt::Level OptLevel)
- : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {
- }
-
- StringRef getPassName() const override {
- return "WebAssembly Instruction Selection";
- }
+ : SelectionDAGISel(ID, TM, OptLevel), Subtarget(nullptr) {}
bool runOnMachineFunction(MachineFunction &MF) override {
LLVM_DEBUG(dbgs() << "********** ISelDAGToDAG **********\n"
@@ -67,14 +67,26 @@ public:
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
std::vector<SDValue> &OutOps) override;
+ bool SelectAddrOperands32(SDValue Op, SDValue &Offset, SDValue &Addr);
+ bool SelectAddrOperands64(SDValue Op, SDValue &Offset, SDValue &Addr);
+
// Include the pieces autogenerated from the target description.
#include "WebAssemblyGenDAGISel.inc"
private:
// add select functions here...
+
+ bool SelectAddrOperands(MVT AddrType, unsigned ConstOpc, SDValue Op,
+ SDValue &Offset, SDValue &Addr);
+ bool SelectAddrAddOperands(MVT OffsetType, SDValue N, SDValue &Offset,
+ SDValue &Addr);
};
} // end anonymous namespace
+char WebAssemblyDAGToDAGISel::ID;
+
+INITIALIZE_PASS(WebAssemblyDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
+
void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
// Stack objects that should be allocated to locals are hoisted to WebAssembly
// locals when they are first used. However for those without uses, we hoist
@@ -281,6 +293,102 @@ bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
return true;
}
+bool WebAssemblyDAGToDAGISel::SelectAddrAddOperands(MVT OffsetType, SDValue N,
+ SDValue &Offset,
+ SDValue &Addr) {
+ assert(N.getNumOperands() == 2 && "Attempting to fold in a non-binary op");
+
+ // WebAssembly constant offsets are performed as unsigned with infinite
+ // precision, so we need to check for NoUnsignedWrap so that we don't fold an
+ // offset for an add that needs wrapping.
+ if (N.getOpcode() == ISD::ADD && !N.getNode()->getFlags().hasNoUnsignedWrap())
+ return false;
+
+ // Folds constants in an add into the offset.
+ for (size_t i = 0; i < 2; ++i) {
+ SDValue Op = N.getOperand(i);
+ SDValue OtherOp = N.getOperand(i == 0 ? 1 : 0);
+
+ if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op)) {
+ Offset =
+ CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), OffsetType);
+ Addr = OtherOp;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool WebAssemblyDAGToDAGISel::SelectAddrOperands(MVT AddrType,
+ unsigned ConstOpc, SDValue N,
+ SDValue &Offset,
+ SDValue &Addr) {
+ SDLoc DL(N);
+
+ // Fold target global addresses into the offset.
+ if (!TM.isPositionIndependent()) {
+ SDValue Op(N);
+ if (Op.getOpcode() == WebAssemblyISD::Wrapper)
+ Op = Op.getOperand(0);
+
+ if (Op.getOpcode() == ISD::TargetGlobalAddress) {
+ Offset = Op;
+ Addr = SDValue(
+ CurDAG->getMachineNode(ConstOpc, DL, AddrType,
+ CurDAG->getTargetConstant(0, DL, AddrType)),
+ 0);
+ return true;
+ }
+ }
+
+ // Fold anything inside an add into the offset.
+ if (N.getOpcode() == ISD::ADD &&
+ SelectAddrAddOperands(AddrType, N, Offset, Addr))
+ return true;
+
+ // Likewise, treat an 'or' node as an 'add' if the or'ed bits are known to be
+ // zero and fold them into the offset too.
+ if (N.getOpcode() == ISD::OR) {
+ bool OrIsAdd;
+ if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+ OrIsAdd =
+ CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
+ } else {
+ KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
+ KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
+ OrIsAdd = (~Known0.Zero & ~Known1.Zero) == 0;
+ }
+
+ if (OrIsAdd && SelectAddrAddOperands(AddrType, N, Offset, Addr))
+ return true;
+ }
+
+ // Fold constant addresses into the offset.
+ if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
+ Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, AddrType);
+ Addr = SDValue(
+ CurDAG->getMachineNode(ConstOpc, DL, AddrType,
+ CurDAG->getTargetConstant(0, DL, AddrType)),
+ 0);
+ return true;
+ }
+
+ // Else it's a plain old load/store with no offset.
+ Offset = CurDAG->getTargetConstant(0, DL, AddrType);
+ Addr = N;
+ return true;
+}
+
+bool WebAssemblyDAGToDAGISel::SelectAddrOperands32(SDValue Op, SDValue &Offset,
+ SDValue &Addr) {
+ return SelectAddrOperands(MVT::i32, WebAssembly::CONST_I32, Op, Offset, Addr);
+}
+
+bool WebAssemblyDAGToDAGISel::SelectAddrOperands64(SDValue Op, SDValue &Offset,
+ SDValue &Addr) {
+ return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64, Op, Offset, Addr);
+}
+
/// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
/// for instruction scheduling.
FunctionPass *llvm::createWebAssemblyISelDag(WebAssemblyTargetMachine &TM,
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index ab6d6b4f7ef1..94544800a6fb 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -194,6 +194,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
MVT::v2f64})
setOperationAction(ISD::VECTOR_SHUFFLE, T, Custom);
+ // Support splatting
+ for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64,
+ MVT::v2f64})
+ setOperationAction(ISD::SPLAT_VECTOR, T, Legal);
+
// Custom lowering since wasm shifts must have a scalar shift amount
for (auto Op : {ISD::SHL, ISD::SRA, ISD::SRL})
for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64})
@@ -751,12 +756,12 @@ WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
}
-bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
+bool WebAssemblyTargetLowering::isCheapToSpeculateCttz(Type *Ty) const {
// Assume ctz is a relatively cheap operation.
return true;
}
-bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
+bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {
// Assume clz is a relatively cheap operation.
return true;
}
@@ -781,7 +786,7 @@ bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
EVT /*VT*/, unsigned /*AddrSpace*/, Align /*Align*/,
- MachineMemOperand::Flags /*Flags*/, bool *Fast) const {
+ MachineMemOperand::Flags /*Flags*/, unsigned *Fast) const {
// WebAssembly supports unaligned accesses, though it should be declared
// with the p2align attribute on loads and stores which do so, and there
// may be a performance impact. We tell LLVM they're "fast" because
@@ -789,7 +794,7 @@ bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
// of constants, etc.), WebAssembly implementations will either want the
// unaligned access or they'll split anyway.
if (Fast)
- *Fast = true;
+ *Fast = 1;
return true;
}
@@ -1449,88 +1454,16 @@ static bool IsWebAssemblyGlobal(SDValue Op) {
return false;
}
-static Optional<unsigned> IsWebAssemblyLocal(SDValue Op, SelectionDAG &DAG) {
+static std::optional<unsigned> IsWebAssemblyLocal(SDValue Op,
+ SelectionDAG &DAG) {
const FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op);
if (!FI)
- return None;
+ return std::nullopt;
auto &MF = DAG.getMachineFunction();
return WebAssemblyFrameLowering::getLocalForStackObject(MF, FI->getIndex());
}
-static bool IsWebAssemblyTable(SDValue Op) {
- const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
- if (GA && WebAssembly::isWasmVarAddressSpace(GA->getAddressSpace())) {
- const GlobalValue *Value = GA->getGlobal();
- const Type *Ty = Value->getValueType();
-
- if (Ty->isArrayTy() && WebAssembly::isRefType(Ty->getArrayElementType()))
- return true;
- }
- return false;
-}
-
-// This function will accept as Op any access to a table, so Op can
-// be the actual table or an offset into the table.
-static bool IsWebAssemblyTableWithOffset(SDValue Op) {
- if (Op->getOpcode() == ISD::ADD && Op->getNumOperands() == 2)
- return (Op->getOperand(1).getSimpleValueType() == MVT::i32 &&
- IsWebAssemblyTableWithOffset(Op->getOperand(0))) ||
- (Op->getOperand(0).getSimpleValueType() == MVT::i32 &&
- IsWebAssemblyTableWithOffset(Op->getOperand(1)));
-
- return IsWebAssemblyTable(Op);
-}
-
-// Helper for table pattern matching used in LowerStore and LowerLoad
-bool WebAssemblyTargetLowering::MatchTableForLowering(SelectionDAG &DAG,
- const SDLoc &DL,
- const SDValue &Base,
- GlobalAddressSDNode *&GA,
- SDValue &Idx) const {
- // We expect the following graph for a load of the form:
- // table[<var> + <constant offset>]
- //
- // Case 1:
- // externref = load t1
- // t1: i32 = add t2, i32:<constant offset>
- // t2: i32 = add tX, table
- //
- // This is in some cases simplified to just:
- // Case 2:
- // externref = load t1
- // t1: i32 = add t2, i32:tX
- //
- // So, unfortunately we need to check for both cases and if we are in the
- // first case extract the table GlobalAddressNode and build a new node tY
- // that's tY: i32 = add i32:<constant offset>, i32:tX
- //
- if (IsWebAssemblyTable(Base)) {
- GA = cast<GlobalAddressSDNode>(Base);
- Idx = DAG.getConstant(0, DL, MVT::i32);
- } else {
- GA = dyn_cast<GlobalAddressSDNode>(Base->getOperand(0));
- if (GA) {
- // We are in Case 2 above.
- Idx = Base->getOperand(1);
- assert(GA->getNumValues() == 1);
- } else {
- // This might be Case 1 above (or an error)
- SDValue V = Base->getOperand(0);
- GA = dyn_cast<GlobalAddressSDNode>(V->getOperand(1));
-
- if (V->getOpcode() != ISD::ADD || V->getNumOperands() != 2 || !GA)
- return false;
-
- SDValue IdxV = DAG.getNode(ISD::ADD, DL, MVT::i32, Base->getOperand(1),
- V->getOperand(0));
- Idx = IdxV;
- }
- }
-
- return true;
-}
-
SDValue WebAssemblyTargetLowering::LowerStore(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
@@ -1539,26 +1472,6 @@ SDValue WebAssemblyTargetLowering::LowerStore(SDValue Op,
const SDValue &Base = SN->getBasePtr();
const SDValue &Offset = SN->getOffset();
- if (IsWebAssemblyTableWithOffset(Base)) {
- if (!Offset->isUndef())
- report_fatal_error(
- "unexpected offset when loading from webassembly table", false);
-
- SDValue Idx;
- GlobalAddressSDNode *GA;
-
- if (!MatchTableForLowering(DAG, DL, Base, GA, Idx))
- report_fatal_error("failed pattern matching for lowering table store",
- false);
-
- SDVTList Tys = DAG.getVTList(MVT::Other);
- SDValue TableSetOps[] = {SN->getChain(), SDValue(GA, 0), Idx, Value};
- SDValue TableSet =
- DAG.getMemIntrinsicNode(WebAssemblyISD::TABLE_SET, DL, Tys, TableSetOps,
- SN->getMemoryVT(), SN->getMemOperand());
- return TableSet;
- }
-
if (IsWebAssemblyGlobal(Base)) {
if (!Offset->isUndef())
report_fatal_error("unexpected offset when storing to webassembly global",
@@ -1570,7 +1483,7 @@ SDValue WebAssemblyTargetLowering::LowerStore(SDValue Op,
SN->getMemoryVT(), SN->getMemOperand());
}
- if (Optional<unsigned> Local = IsWebAssemblyLocal(Base, DAG)) {
+ if (std::optional<unsigned> Local = IsWebAssemblyLocal(Base, DAG)) {
if (!Offset->isUndef())
report_fatal_error("unexpected offset when storing to webassembly local",
false);
@@ -1581,6 +1494,11 @@ SDValue WebAssemblyTargetLowering::LowerStore(SDValue Op,
return DAG.getNode(WebAssemblyISD::LOCAL_SET, DL, Tys, Ops);
}
+ if (WebAssembly::isWasmVarAddressSpace(SN->getAddressSpace()))
+ report_fatal_error(
+ "Encountered an unlowerable store to the wasm_var address space",
+ false);
+
return Op;
}
@@ -1591,26 +1509,6 @@ SDValue WebAssemblyTargetLowering::LowerLoad(SDValue Op,
const SDValue &Base = LN->getBasePtr();
const SDValue &Offset = LN->getOffset();
- if (IsWebAssemblyTableWithOffset(Base)) {
- if (!Offset->isUndef())
- report_fatal_error(
- "unexpected offset when loading from webassembly table", false);
-
- GlobalAddressSDNode *GA;
- SDValue Idx;
-
- if (!MatchTableForLowering(DAG, DL, Base, GA, Idx))
- report_fatal_error("failed pattern matching for lowering table load",
- false);
-
- SDVTList Tys = DAG.getVTList(LN->getValueType(0), MVT::Other);
- SDValue TableGetOps[] = {LN->getChain(), SDValue(GA, 0), Idx};
- SDValue TableGet =
- DAG.getMemIntrinsicNode(WebAssemblyISD::TABLE_GET, DL, Tys, TableGetOps,
- LN->getMemoryVT(), LN->getMemOperand());
- return TableGet;
- }
-
if (IsWebAssemblyGlobal(Base)) {
if (!Offset->isUndef())
report_fatal_error(
@@ -1622,7 +1520,7 @@ SDValue WebAssemblyTargetLowering::LowerLoad(SDValue Op,
LN->getMemoryVT(), LN->getMemOperand());
}
- if (Optional<unsigned> Local = IsWebAssemblyLocal(Base, DAG)) {
+ if (std::optional<unsigned> Local = IsWebAssemblyLocal(Base, DAG)) {
if (!Offset->isUndef())
report_fatal_error(
"unexpected offset when loading from webassembly local", false);
@@ -1636,6 +1534,11 @@ SDValue WebAssemblyTargetLowering::LowerLoad(SDValue Op,
return Result;
}
+ if (WebAssembly::isWasmVarAddressSpace(LN->getAddressSpace()))
+ report_fatal_error(
+ "Encountered an unlowerable load from the wasm_var address space",
+ false);
+
return Op;
}
@@ -1845,7 +1748,7 @@ SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
// Add an operand for each case.
- for (auto MBB : MBBs)
+ for (auto *MBB : MBBs)
Ops.push_back(DAG.getBasicBlock(MBB));
// Add the first MBB as a dummy default target for now. This will be replaced
@@ -2263,18 +2166,8 @@ SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
return IsConstant(Lane);
};
} else {
- // Use a splat, but possibly a load_splat
- LoadSDNode *SplattedLoad;
- if ((SplattedLoad = dyn_cast<LoadSDNode>(SplatValue)) &&
- SplattedLoad->getMemoryVT() == VecT.getVectorElementType()) {
- Result = DAG.getMemIntrinsicNode(
- WebAssemblyISD::LOAD_SPLAT, DL, DAG.getVTList(VecT),
- {SplattedLoad->getChain(), SplattedLoad->getBasePtr(),
- SplattedLoad->getOffset()},
- SplattedLoad->getMemoryVT(), SplattedLoad->getMemOperand());
- } else {
- Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
- }
+ // Use a splat (which might be selected as a load splat)
+ Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
IsLaneConstructed = [&SplatValue](size_t _, const SDValue &Lane) {
return Lane == SplatValue;
};
@@ -2312,8 +2205,10 @@ WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
// Expand mask indices to byte indices and materialize them as operands
for (int M : Mask) {
for (size_t J = 0; J < LaneBytes; ++J) {
- // Lower undefs (represented by -1 in mask) to zero
- uint64_t ByteIndex = M == -1 ? 0 : (uint64_t)M * LaneBytes + J;
+ // Lower undefs (represented by -1 in mask) to {0..J}, which use a
+ // whole lane of vector input, to allow further reduction at VM. E.g.
+ // match an 8x16 byte shuffle to an equivalent cheaper 32x4 shuffle.
+ uint64_t ByteIndex = M == -1 ? J : (uint64_t)M * LaneBytes + J;
Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
}
}
@@ -2345,11 +2240,16 @@ WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
SelectionDAG &DAG) const {
// Allow constant lane indices, expand variable lane indices
SDNode *IdxNode = Op.getOperand(Op.getNumOperands() - 1).getNode();
- if (isa<ConstantSDNode>(IdxNode) || IdxNode->isUndef())
- return Op;
- else
- // Perform default expansion
- return SDValue();
+ if (isa<ConstantSDNode>(IdxNode) || IdxNode->isUndef()) {
+ // Ensure the index type is i32 to match the tablegen patterns
+ uint64_t Idx = cast<ConstantSDNode>(IdxNode)->getZExtValue();
+ SmallVector<SDValue, 3> Ops(Op.getNode()->ops());
+ Ops[Op.getNumOperands() - 1] =
+ DAG.getConstant(Idx, SDLoc(IdxNode), MVT::i32);
+ return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(), Ops);
+ }
+ // Perform default expansion
+ return SDValue();
}
static SDValue unrollVectorShift(SDValue Op, SelectionDAG &DAG) {
@@ -2456,6 +2356,32 @@ performVECTOR_SHUFFLECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
return DAG.getBitcast(DstType, NewShuffle);
}
+/// Convert ({u,s}itofp vec) --> ({u,s}itofp ({s,z}ext vec)) so it doesn't get
+/// split up into scalar instructions during legalization, and the vector
+/// extending instructions are selected in performVectorExtendCombine below.
+static SDValue
+performVectorExtendToFPCombine(SDNode *N,
+ TargetLowering::DAGCombinerInfo &DCI) {
+ auto &DAG = DCI.DAG;
+ assert(N->getOpcode() == ISD::UINT_TO_FP ||
+ N->getOpcode() == ISD::SINT_TO_FP);
+
+ EVT InVT = N->getOperand(0)->getValueType(0);
+ EVT ResVT = N->getValueType(0);
+ MVT ExtVT;
+ if (ResVT == MVT::v4f32 && (InVT == MVT::v4i16 || InVT == MVT::v4i8))
+ ExtVT = MVT::v4i32;
+ else if (ResVT == MVT::v2f64 && (InVT == MVT::v2i16 || InVT == MVT::v2i8))
+ ExtVT = MVT::v2i32;
+ else
+ return SDValue();
+
+ unsigned Op =
+ N->getOpcode() == ISD::UINT_TO_FP ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND;
+ SDValue Conv = DAG.getNode(Op, SDLoc(N), ExtVT, N->getOperand(0));
+ return DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, Conv);
+}
+
static SDValue
performVectorExtendCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
auto &DAG = DCI.DAG;
@@ -2741,6 +2667,9 @@ WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::SIGN_EXTEND:
case ISD::ZERO_EXTEND:
return performVectorExtendCombine(N, DCI);
+ case ISD::UINT_TO_FP:
+ case ISD::SINT_TO_FP:
+ return performVectorExtendToFPCombine(N, DCI);
case ISD::FP_TO_SINT_SAT:
case ISD::FP_TO_UINT_SAT:
case ISD::FP_ROUND:
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
index d86f2e59e3d2..f70f85fe6ddd 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
@@ -65,14 +65,14 @@ private:
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
StringRef Constraint, MVT VT) const override;
- bool isCheapToSpeculateCttz() const override;
- bool isCheapToSpeculateCtlz() const override;
+ bool isCheapToSpeculateCttz(Type *Ty) const override;
+ bool isCheapToSpeculateCtlz(Type *Ty) const override;
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
unsigned AS,
Instruction *I = nullptr) const override;
bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace, Align Alignment,
MachineMemOperand::Flags Flags,
- bool *Fast) const override;
+ unsigned *Fast) const override;
bool isIntDivCheap(EVT VT, AttributeList Attr) const override;
bool isVectorLoadExtDesirable(SDValue ExtVal) const override;
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td
index ed80ed39f09c..2dbcdd50fb8d 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td
@@ -77,129 +77,29 @@ defm MEMORY_ATOMIC_WAIT64_A64 :
} // mayLoad = 1
} // hasSideEffects = 1
-// Select notifys with no constant offset.
-def NotifyPatNoOffset_A32 :
- Pat<(i32 (int_wasm_memory_atomic_notify I32:$addr, I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A32 0, 0, I32:$addr, I32:$count)>,
+def NotifyPat_A32 :
+ Pat<(i32 (int_wasm_memory_atomic_notify (AddrOps32 offset32_op:$offset, I32:$addr), I32:$count)),
+ (MEMORY_ATOMIC_NOTIFY_A32 0, $offset, $addr, $count)>,
Requires<[HasAddr32, HasAtomics]>;
-def NotifyPatNoOffset_A64 :
- Pat<(i32 (int_wasm_memory_atomic_notify I64:$addr, I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A64 0, 0, I64:$addr, I32:$count)>,
+def NotifyPat_A64 :
+ Pat<(i32 (int_wasm_memory_atomic_notify (AddrOps64 offset64_op:$offset, I64:$addr), I32:$count)),
+ (MEMORY_ATOMIC_NOTIFY_A64 0, $offset, $addr, $count)>,
Requires<[HasAddr64, HasAtomics]>;
-// Select notifys with a constant offset.
-// Pattern with address + immediate offset
-multiclass NotifyPatImmOff<PatFrag operand, string inst> {
- def : Pat<(i32 (int_wasm_memory_atomic_notify (operand I32:$addr, imm:$off),
- I32:$count)),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, I32:$count)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(i32 (int_wasm_memory_atomic_notify (operand I64:$addr, imm:$off),
- I32:$count)),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, I32:$count)>,
- Requires<[HasAddr64, HasAtomics]>;
+multiclass WaitPat<ValueType ty, Intrinsic kind, string inst> {
+ def WaitPat_A32 :
+ Pat<(i32 (kind (AddrOps32 offset32_op:$offset, I32:$addr), ty:$exp, I64:$timeout)),
+ (!cast<NI>(inst#_A32) 0, $offset, $addr, $exp, $timeout)>,
+ Requires<[HasAddr32, HasAtomics]>;
+ def WaitPat_A64 :
+ Pat<(i32 (kind (AddrOps64 offset64_op:$offset, I64:$addr), ty:$exp, I64:$timeout)),
+ (!cast<NI>(inst#_A64) 0, $offset, $addr, $exp, $timeout)>,
+ Requires<[HasAddr64, HasAtomics]>;
}
-defm : NotifyPatImmOff<regPlusImm, "MEMORY_ATOMIC_NOTIFY">;
-defm : NotifyPatImmOff<or_is_add, "MEMORY_ATOMIC_NOTIFY">;
-// Select notifys with just a constant offset.
-def NotifyPatOffsetOnly_A32 :
- Pat<(i32 (int_wasm_memory_atomic_notify imm:$off, I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A32 0, imm:$off, (CONST_I32 0), I32:$count)>,
- Requires<[HasAddr32, HasAtomics]>;
-def NotifyPatOffsetOnly_A64 :
- Pat<(i32 (int_wasm_memory_atomic_notify imm:$off, I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A64 0, imm:$off, (CONST_I64 0), I32:$count)>,
- Requires<[HasAddr64, HasAtomics]>;
-
-def NotifyPatGlobalAddrOffOnly_A32 :
- Pat<(i32 (int_wasm_memory_atomic_notify (WebAssemblyWrapper tglobaladdr:$off),
- I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A32 0, tglobaladdr:$off, (CONST_I32 0), I32:$count)
- >,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
-def NotifyPatGlobalAddrOffOnly_A64 :
- Pat<(i32 (int_wasm_memory_atomic_notify (WebAssemblyWrapper tglobaladdr:$off),
- I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A64 0, tglobaladdr:$off, (CONST_I64 0), I32:$count)
- >,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-
-// Select waits with no constant offset.
-multiclass WaitPatNoOffset<ValueType ty, Intrinsic kind,
- string inst> {
- def : Pat<(i32 (kind I32:$addr, ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A32) 0, 0, I32:$addr, ty:$exp, I64:$timeout)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(i32 (kind I64:$addr, ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$exp, I64:$timeout)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : WaitPatNoOffset<i32, int_wasm_memory_atomic_wait32,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatNoOffset<i64, int_wasm_memory_atomic_wait64,
- "MEMORY_ATOMIC_WAIT64">;
-defm : WaitPatNoOffset<i32, int_wasm_memory_atomic_wait32,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatNoOffset<i64, int_wasm_memory_atomic_wait64,
- "MEMORY_ATOMIC_WAIT64">;
-
-// Select waits with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass WaitPatImmOff<ValueType ty, Intrinsic kind, PatFrag operand,
- string inst> {
- def : Pat<(i32 (kind (operand I32:$addr, imm:$off), ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(i32 (kind (operand I64:$addr, imm:$off), ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : WaitPatImmOff<i32, int_wasm_memory_atomic_wait32, regPlusImm,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatImmOff<i32, int_wasm_memory_atomic_wait32, or_is_add,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatImmOff<i64, int_wasm_memory_atomic_wait64, regPlusImm,
- "MEMORY_ATOMIC_WAIT64">;
-defm : WaitPatImmOff<i64, int_wasm_memory_atomic_wait64, or_is_add,
- "MEMORY_ATOMIC_WAIT64">;
-
-// Select waits with just a constant offset.
-multiclass WaitPatOffsetOnly<ValueType ty, Intrinsic kind, string inst> {
- def : Pat<(i32 (kind imm:$off, ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A32) 0, imm:$off, (CONST_I32 0), ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(i32 (kind imm:$off, ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A64) 0, imm:$off, (CONST_I64 0), ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : WaitPatOffsetOnly<i32, int_wasm_memory_atomic_wait32,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatOffsetOnly<i64, int_wasm_memory_atomic_wait64,
- "MEMORY_ATOMIC_WAIT64">;
-
-multiclass WaitPatGlobalAddrOffOnly<ValueType ty, Intrinsic kind, string inst> {
- def : Pat<(i32 (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$exp,
- I64:$timeout)),
- (!cast<NI>(inst#_A32) 0, tglobaladdr:$off, (CONST_I32 0), ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
- def : Pat<(i32 (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$exp,
- I64:$timeout)),
- (!cast<NI>(inst#_A64) 0, tglobaladdr:$off, (CONST_I64 0), ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-}
-defm : WaitPatGlobalAddrOffOnly<i32, int_wasm_memory_atomic_wait32,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatGlobalAddrOffOnly<i64, int_wasm_memory_atomic_wait64,
- "MEMORY_ATOMIC_WAIT64">;
+defm : WaitPat<i32, int_wasm_memory_atomic_wait32, "MEMORY_ATOMIC_WAIT32">;
+defm : WaitPat<i64, int_wasm_memory_atomic_wait64, "MEMORY_ATOMIC_WAIT64">;
//===----------------------------------------------------------------------===//
// Atomic fences
@@ -226,25 +126,9 @@ multiclass AtomicLoad<WebAssemblyRegClass rc, string name, int atomic_op> {
defm ATOMIC_LOAD_I32 : AtomicLoad<I32, "i32.atomic.load", 0x10>;
defm ATOMIC_LOAD_I64 : AtomicLoad<I64, "i64.atomic.load", 0x11>;
-// Select loads with no constant offset.
-defm : LoadPatNoOffset<i32, atomic_load_32, "ATOMIC_LOAD_I32">;
-defm : LoadPatNoOffset<i64, atomic_load_64, "ATOMIC_LOAD_I64">;
-
-// Select loads with a constant offset.
-
-// Pattern with address + immediate offset
-defm : LoadPatImmOff<i32, atomic_load_32, regPlusImm, "ATOMIC_LOAD_I32">;
-defm : LoadPatImmOff<i64, atomic_load_64, regPlusImm, "ATOMIC_LOAD_I64">;
-defm : LoadPatImmOff<i32, atomic_load_32, or_is_add, "ATOMIC_LOAD_I32">;
-defm : LoadPatImmOff<i64, atomic_load_64, or_is_add, "ATOMIC_LOAD_I64">;
-
-// Select loads with just a constant offset.
-defm : LoadPatOffsetOnly<i32, atomic_load_32, "ATOMIC_LOAD_I32">;
-defm : LoadPatOffsetOnly<i64, atomic_load_64, "ATOMIC_LOAD_I64">;
-
-defm : LoadPatGlobalAddrOffOnly<i32, atomic_load_32, "ATOMIC_LOAD_I32">;
-defm : LoadPatGlobalAddrOffOnly<i64, atomic_load_64, "ATOMIC_LOAD_I64">;
-
+// Select loads
+defm : LoadPat<i32, atomic_load_32, "ATOMIC_LOAD_I32">;
+defm : LoadPat<i64, atomic_load_64, "ATOMIC_LOAD_I64">;
// Extending loads. Note that there are only zero-extending atomic loads, no
// sign-extending loads.
@@ -283,54 +167,18 @@ def sext_aload_8_64 :
def sext_aload_16_64 :
PatFrag<(ops node:$addr), (anyext (i32 (atomic_load_16 node:$addr)))>;
-// Select zero-extending loads with no constant offset.
-defm : LoadPatNoOffset<i64, zext_aload_8_64, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatNoOffset<i64, zext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
-defm : LoadPatNoOffset<i64, zext_aload_32_64, "ATOMIC_LOAD32_U_I64">;
+// Select zero-extending loads
+defm : LoadPat<i64, zext_aload_8_64, "ATOMIC_LOAD8_U_I64">;
+defm : LoadPat<i64, zext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
+defm : LoadPat<i64, zext_aload_32_64, "ATOMIC_LOAD32_U_I64">;
-// Select sign-extending loads with no constant offset
-defm : LoadPatNoOffset<i32, atomic_load_8, "ATOMIC_LOAD8_U_I32">;
-defm : LoadPatNoOffset<i32, atomic_load_16, "ATOMIC_LOAD16_U_I32">;
-defm : LoadPatNoOffset<i64, sext_aload_8_64, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatNoOffset<i64, sext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
+// Select sign-extending loads
+defm : LoadPat<i32, atomic_load_8, "ATOMIC_LOAD8_U_I32">;
+defm : LoadPat<i32, atomic_load_16, "ATOMIC_LOAD16_U_I32">;
+defm : LoadPat<i64, sext_aload_8_64, "ATOMIC_LOAD8_U_I64">;
+defm : LoadPat<i64, sext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
// 32->64 sext load gets selected as i32.atomic.load, i64.extend_i32_s
-// Zero-extending loads with constant offset
-defm : LoadPatImmOff<i64, zext_aload_8_64, regPlusImm, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatImmOff<i64, zext_aload_16_64, regPlusImm, "ATOMIC_LOAD16_U_I64">;
-defm : LoadPatImmOff<i64, zext_aload_32_64, regPlusImm, "ATOMIC_LOAD32_U_I64">;
-defm : LoadPatImmOff<i64, zext_aload_8_64, or_is_add, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatImmOff<i64, zext_aload_16_64, or_is_add, "ATOMIC_LOAD16_U_I64">;
-defm : LoadPatImmOff<i64, zext_aload_32_64, or_is_add, "ATOMIC_LOAD32_U_I64">;
-
-// Sign-extending loads with constant offset
-defm : LoadPatImmOff<i32, atomic_load_8, regPlusImm, "ATOMIC_LOAD8_U_I32">;
-defm : LoadPatImmOff<i32, atomic_load_16, regPlusImm, "ATOMIC_LOAD16_U_I32">;
-defm : LoadPatImmOff<i32, atomic_load_8, or_is_add, "ATOMIC_LOAD8_U_I32">;
-defm : LoadPatImmOff<i32, atomic_load_16, or_is_add, "ATOMIC_LOAD16_U_I32">;
-defm : LoadPatImmOff<i64, sext_aload_8_64, regPlusImm, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatImmOff<i64, sext_aload_16_64, regPlusImm, "ATOMIC_LOAD16_U_I64">;
-defm : LoadPatImmOff<i64, sext_aload_8_64, or_is_add, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatImmOff<i64, sext_aload_16_64, or_is_add, "ATOMIC_LOAD16_U_I64">;
-// No 32->64 patterns, just use i32.atomic.load and i64.extend_s/i64
-
-// Extending loads with just a constant offset
-defm : LoadPatOffsetOnly<i64, zext_aload_8_64, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatOffsetOnly<i64, zext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
-defm : LoadPatOffsetOnly<i64, zext_aload_32_64, "ATOMIC_LOAD32_U_I64">;
-defm : LoadPatOffsetOnly<i32, atomic_load_8, "ATOMIC_LOAD8_U_I32">;
-defm : LoadPatOffsetOnly<i32, atomic_load_16, "ATOMIC_LOAD16_U_I32">;
-defm : LoadPatOffsetOnly<i64, sext_aload_8_64, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatOffsetOnly<i64, sext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
-
-defm : LoadPatGlobalAddrOffOnly<i64, zext_aload_8_64, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, zext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, zext_aload_32_64, "ATOMIC_LOAD32_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i32, atomic_load_8, "ATOMIC_LOAD8_U_I32">;
-defm : LoadPatGlobalAddrOffOnly<i32, atomic_load_16, "ATOMIC_LOAD16_U_I32">;
-defm : LoadPatGlobalAddrOffOnly<i64, sext_aload_8_64, "ATOMIC_LOAD8_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, sext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
-
//===----------------------------------------------------------------------===//
// Atomic stores
@@ -349,57 +197,16 @@ defm ATOMIC_STORE_I64 : AtomicStore<I64, "i64.atomic.store", 0x18>;
// store: (store $val, $ptr)
// atomic_store: (store $ptr, $val)
-
-// Select stores with no constant offset.
-multiclass AStorePatNoOffset<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind I32:$addr, ty:$val),
- (!cast<NI>(inst#_A32) 0, 0, I32:$addr, ty:$val)>,
+multiclass AStorePat<ValueType ty, PatFrag kind, string inst> {
+ def : Pat<(kind (AddrOps32 offset32_op:$offset, I32:$addr), ty:$val),
+ (!cast<NI>(inst#_A32) 0, $offset, $addr, $val)>,
Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(kind I64:$addr, ty:$val),
- (!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$val)>,
+ def : Pat<(kind (AddrOps64 offset64_op:$offset, I64:$addr), ty:$val),
+ (!cast<NI>(inst#_A64) 0, $offset, $addr, $val)>,
Requires<[HasAddr64, HasAtomics]>;
}
-defm : AStorePatNoOffset<i32, atomic_store_32, "ATOMIC_STORE_I32">;
-defm : AStorePatNoOffset<i64, atomic_store_64, "ATOMIC_STORE_I64">;
-
-// Select stores with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass AStorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand,
- string inst> {
- def : Pat<(kind (operand I32:$addr, imm:$off), ty:$val),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, ty:$val)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(kind (operand I64:$addr, imm:$off), ty:$val),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, ty:$val)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : AStorePatImmOff<i32, atomic_store_32, regPlusImm, "ATOMIC_STORE_I32">;
-defm : AStorePatImmOff<i64, atomic_store_64, regPlusImm, "ATOMIC_STORE_I64">;
-
-// Select stores with just a constant offset.
-multiclass AStorePatOffsetOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind imm:$off, ty:$val),
- (!cast<NI>(inst#_A32) 0, imm:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(kind imm:$off, ty:$val),
- (!cast<NI>(inst#_A64) 0, imm:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : AStorePatOffsetOnly<i32, atomic_store_32, "ATOMIC_STORE_I32">;
-defm : AStorePatOffsetOnly<i64, atomic_store_64, "ATOMIC_STORE_I64">;
-
-multiclass AStorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind (WebAssemblyWrapper tglobaladdr:$off), ty:$val),
- (!cast<NI>(inst#_A32) 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
- def : Pat<(kind (WebAssemblyWrapper tglobaladdr:$off), ty:$val),
- (!cast<NI>(inst#_A64) 0, tglobaladdr:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-}
-defm : AStorePatGlobalAddrOffOnly<i32, atomic_store_32, "ATOMIC_STORE_I32">;
-defm : AStorePatGlobalAddrOffOnly<i64, atomic_store_64, "ATOMIC_STORE_I64">;
-
+defm : AStorePat<i32, atomic_store_32, "ATOMIC_STORE_I32">;
+defm : AStorePat<i64, atomic_store_64, "ATOMIC_STORE_I64">;
// Truncating stores.
defm ATOMIC_STORE8_I32 : AtomicStore<I32, "i32.atomic.store8", 0x19>;
@@ -420,43 +227,12 @@ def trunc_astore_8_64 : trunc_astore_64<atomic_store_8>;
def trunc_astore_16_64 : trunc_astore_64<atomic_store_16>;
def trunc_astore_32_64 : trunc_astore_64<atomic_store_32>;
-
// Truncating stores with no constant offset
-defm : AStorePatNoOffset<i32, atomic_store_8, "ATOMIC_STORE8_I32">;
-defm : AStorePatNoOffset<i32, atomic_store_16, "ATOMIC_STORE16_I32">;
-defm : AStorePatNoOffset<i64, trunc_astore_8_64, "ATOMIC_STORE8_I64">;
-defm : AStorePatNoOffset<i64, trunc_astore_16_64, "ATOMIC_STORE16_I64">;
-defm : AStorePatNoOffset<i64, trunc_astore_32_64, "ATOMIC_STORE32_I64">;
-
-// Truncating stores with a constant offset
-defm : AStorePatImmOff<i32, atomic_store_8, regPlusImm, "ATOMIC_STORE8_I32">;
-defm : AStorePatImmOff<i32, atomic_store_16, regPlusImm, "ATOMIC_STORE16_I32">;
-defm : AStorePatImmOff<i64, trunc_astore_8_64, regPlusImm, "ATOMIC_STORE8_I64">;
-defm : AStorePatImmOff<i64, trunc_astore_16_64, regPlusImm,
- "ATOMIC_STORE16_I64">;
-defm : AStorePatImmOff<i64, trunc_astore_32_64, regPlusImm,
- "ATOMIC_STORE32_I64">;
-defm : AStorePatImmOff<i32, atomic_store_8, or_is_add, "ATOMIC_STORE8_I32">;
-defm : AStorePatImmOff<i32, atomic_store_16, or_is_add, "ATOMIC_STORE16_I32">;
-defm : AStorePatImmOff<i64, trunc_astore_8_64, or_is_add, "ATOMIC_STORE8_I64">;
-defm : AStorePatImmOff<i64, trunc_astore_16_64, or_is_add,
- "ATOMIC_STORE16_I64">;
-defm : AStorePatImmOff<i64, trunc_astore_32_64, or_is_add,
- "ATOMIC_STORE32_I64">;
-
-// Truncating stores with just a constant offset
-defm : AStorePatOffsetOnly<i32, atomic_store_8, "ATOMIC_STORE8_I32">;
-defm : AStorePatOffsetOnly<i32, atomic_store_16, "ATOMIC_STORE16_I32">;
-defm : AStorePatOffsetOnly<i64, trunc_astore_8_64, "ATOMIC_STORE8_I64">;
-defm : AStorePatOffsetOnly<i64, trunc_astore_16_64, "ATOMIC_STORE16_I64">;
-defm : AStorePatOffsetOnly<i64, trunc_astore_32_64, "ATOMIC_STORE32_I64">;
-
-defm : AStorePatGlobalAddrOffOnly<i32, atomic_store_8, "ATOMIC_STORE8_I32">;
-defm : AStorePatGlobalAddrOffOnly<i32, atomic_store_16, "ATOMIC_STORE16_I32">;
-defm : AStorePatGlobalAddrOffOnly<i64, trunc_astore_8_64, "ATOMIC_STORE8_I64">;
-defm : AStorePatGlobalAddrOffOnly<i64, trunc_astore_16_64, "ATOMIC_STORE16_I64">;
-defm : AStorePatGlobalAddrOffOnly<i64, trunc_astore_32_64, "ATOMIC_STORE32_I64">;
-
+defm : AStorePat<i32, atomic_store_8, "ATOMIC_STORE8_I32">;
+defm : AStorePat<i32, atomic_store_16, "ATOMIC_STORE16_I32">;
+defm : AStorePat<i64, trunc_astore_8_64, "ATOMIC_STORE8_I64">;
+defm : AStorePat<i64, trunc_astore_16_64, "ATOMIC_STORE16_I64">;
+defm : AStorePat<i64, trunc_astore_32_64, "ATOMIC_STORE32_I64">;
//===----------------------------------------------------------------------===//
// Atomic binary read-modify-writes
@@ -558,64 +334,20 @@ defm ATOMIC_RMW16_U_XCHG_I64 :
defm ATOMIC_RMW32_U_XCHG_I64 :
WebAssemblyBinRMW<I64, "i64.atomic.rmw32.xchg_u", 0x47>;
-// Select binary RMWs with no constant offset.
-multiclass BinRMWPatNoOffset<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind I32:$addr, ty:$val)),
- (!cast<NI>(inst#_A32) 0, 0, I32:$addr, ty:$val)>,
+multiclass BinRMWPat<ValueType ty, PatFrag kind, string inst> {
+ def : Pat<(ty (kind (AddrOps32 offset32_op:$offset, I32:$addr), ty:$val)),
+ (!cast<NI>(inst#_A32) 0, $offset, $addr, $val)>,
Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind I64:$addr, ty:$val)),
- (!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$val)>,
+ def : Pat<(ty (kind (AddrOps64 offset64_op:$offset, I64:$addr), ty:$val)),
+ (!cast<NI>(inst#_A64) 0, $offset, $addr, $val)>,
Requires<[HasAddr64, HasAtomics]>;
}
-// Select binary RMWs with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass BinRMWPatImmOff<ValueType ty, PatFrag kind, PatFrag operand,
- string inst> {
- def : Pat<(ty (kind (operand I32:$addr, imm:$off), ty:$val)),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, ty:$val)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind (operand I64:$addr, imm:$off), ty:$val)),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, ty:$val)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-
-// Select binary RMWs with just a constant offset.
-multiclass BinRMWPatOffsetOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind imm:$off, ty:$val)),
- (!cast<NI>(inst#_A32) 0, imm:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind imm:$off, ty:$val)),
- (!cast<NI>(inst#_A64) 0, imm:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-
-multiclass BinRMWPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$val)),
- (!cast<NI>(inst#_A32) 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$val)),
- (!cast<NI>(inst#_A64) 0, tglobaladdr:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-}
-
// Patterns for various addressing modes.
multiclass BinRMWPattern<PatFrag rmw_32, PatFrag rmw_64, string inst_32,
string inst_64> {
- defm : BinRMWPatNoOffset<i32, rmw_32, inst_32>;
- defm : BinRMWPatNoOffset<i64, rmw_64, inst_64>;
-
- defm : BinRMWPatImmOff<i32, rmw_32, regPlusImm, inst_32>;
- defm : BinRMWPatImmOff<i64, rmw_64, regPlusImm, inst_64>;
- defm : BinRMWPatImmOff<i32, rmw_32, or_is_add, inst_32>;
- defm : BinRMWPatImmOff<i64, rmw_64, or_is_add, inst_64>;
-
- defm : BinRMWPatOffsetOnly<i32, rmw_32, inst_32>;
- defm : BinRMWPatOffsetOnly<i64, rmw_64, inst_64>;
-
- defm : BinRMWPatGlobalAddrOffOnly<i32, rmw_32, inst_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, rmw_64, inst_64>;
+ defm : BinRMWPat<i32, rmw_32, inst_32>;
+ defm : BinRMWPat<i64, rmw_64, inst_64>;
}
defm : BinRMWPattern<atomic_load_add_32, atomic_load_add_64,
@@ -661,66 +393,17 @@ class sext_bin_rmw_16_64<PatFrag kind> : sext_bin_rmw_8_64<kind>;
multiclass BinRMWTruncExtPattern<
PatFrag rmw_8, PatFrag rmw_16, PatFrag rmw_32,
string inst8_32, string inst16_32, string inst8_64, string inst16_64, string inst32_64> {
- // Truncating-extending binary RMWs with no constant offset
- defm : BinRMWPatNoOffset<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatNoOffset<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatNoOffset<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatNoOffset<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>;
- defm : BinRMWPatNoOffset<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : BinRMWPatNoOffset<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatNoOffset<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatNoOffset<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatNoOffset<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>;
-
- // Truncating-extending binary RMWs with a constant offset
- defm : BinRMWPatImmOff<i32, zext_bin_rmw_8_32<rmw_8>, regPlusImm, inst8_32>;
- defm : BinRMWPatImmOff<i32, zext_bin_rmw_16_32<rmw_16>, regPlusImm,
- inst16_32>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_8_64<rmw_8>, regPlusImm, inst8_64>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_16_64<rmw_16>, regPlusImm,
- inst16_64>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_32_64<rmw_32>, regPlusImm,
- inst32_64>;
- defm : BinRMWPatImmOff<i32, zext_bin_rmw_8_32<rmw_8>, or_is_add, inst8_32>;
- defm : BinRMWPatImmOff<i32, zext_bin_rmw_16_32<rmw_16>, or_is_add, inst16_32>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_8_64<rmw_8>, or_is_add, inst8_64>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_16_64<rmw_16>, or_is_add, inst16_64>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_32_64<rmw_32>, or_is_add, inst32_64>;
-
- defm : BinRMWPatImmOff<i32, sext_bin_rmw_8_32<rmw_8>, regPlusImm, inst8_32>;
- defm : BinRMWPatImmOff<i32, sext_bin_rmw_16_32<rmw_16>, regPlusImm,
- inst16_32>;
- defm : BinRMWPatImmOff<i64, sext_bin_rmw_8_64<rmw_8>, regPlusImm, inst8_64>;
- defm : BinRMWPatImmOff<i64, sext_bin_rmw_16_64<rmw_16>, regPlusImm,
- inst16_64>;
- defm : BinRMWPatImmOff<i32, sext_bin_rmw_8_32<rmw_8>, or_is_add, inst8_32>;
- defm : BinRMWPatImmOff<i32, sext_bin_rmw_16_32<rmw_16>, or_is_add, inst16_32>;
- defm : BinRMWPatImmOff<i64, sext_bin_rmw_8_64<rmw_8>, or_is_add, inst8_64>;
- defm : BinRMWPatImmOff<i64, sext_bin_rmw_16_64<rmw_16>, or_is_add, inst16_64>;
-
- // Truncating-extending binary RMWs with just a constant offset
- defm : BinRMWPatOffsetOnly<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatOffsetOnly<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatOffsetOnly<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatOffsetOnly<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>;
- defm : BinRMWPatOffsetOnly<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : BinRMWPatOffsetOnly<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatOffsetOnly<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatOffsetOnly<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatOffsetOnly<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>;
-
- defm : BinRMWPatGlobalAddrOffOnly<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : BinRMWPatGlobalAddrOffOnly<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>;
+ // Truncating-extending binary RMWs
+ defm : BinRMWPat<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>;
+ defm : BinRMWPat<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>;
+ defm : BinRMWPat<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>;
+ defm : BinRMWPat<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>;
+ defm : BinRMWPat<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>;
+
+ defm : BinRMWPat<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>;
+ defm : BinRMWPat<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>;
+ defm : BinRMWPat<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>;
+ defm : BinRMWPat<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>;
}
defm : BinRMWTruncExtPattern<
@@ -792,70 +475,17 @@ defm ATOMIC_RMW16_U_CMPXCHG_I64 :
defm ATOMIC_RMW32_U_CMPXCHG_I64 :
WebAssemblyTerRMW<I64, "i64.atomic.rmw32.cmpxchg_u", 0x4e>;
-// Select ternary RMWs with no constant offset.
-multiclass TerRMWPatNoOffset<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind I32:$addr, ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A32) 0, 0, I32:$addr, ty:$exp, ty:$new)>,
+multiclass TerRMWPat<ValueType ty, PatFrag kind, string inst> {
+ def : Pat<(ty (kind (AddrOps32 offset32_op:$offset, I32:$addr), ty:$exp, ty:$new)),
+ (!cast<NI>(inst#_A32) 0, $offset, $addr, $exp, $new)>,
Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind I64:$addr, ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$exp, ty:$new)>,
+ def : Pat<(ty (kind (AddrOps64 offset64_op:$offset, I64:$addr), ty:$exp, ty:$new)),
+ (!cast<NI>(inst#_A64) 0, $offset, $addr, $exp, $new)>,
Requires<[HasAddr64, HasAtomics]>;
}
-// Select ternary RMWs with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass TerRMWPatImmOff<ValueType ty, PatFrag kind, PatFrag operand,
- string inst> {
- def : Pat<(ty (kind (operand I32:$addr, imm:$off), ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, ty:$exp, ty:$new)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind (operand I64:$addr, imm:$off), ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, ty:$exp, ty:$new)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-
-// Select ternary RMWs with just a constant offset.
-multiclass TerRMWPatOffsetOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind imm:$off, ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A32) 0, imm:$off, (CONST_I32 0), ty:$exp,
- ty:$new)>;
- def : Pat<(ty (kind imm:$off, ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A64) 0, imm:$off, (CONST_I64 0), ty:$exp,
- ty:$new)>;
-}
-
-multiclass TerRMWPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A32) 0, tglobaladdr:$off, (CONST_I32 0), ty:$exp,
- ty:$new)>,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A64) 0, tglobaladdr:$off, (CONST_I64 0), ty:$exp,
- ty:$new)>,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-}
-
-// Patterns for various addressing modes.
-multiclass TerRMWPattern<PatFrag rmw_32, PatFrag rmw_64, string inst_32,
- string inst_64> {
- defm : TerRMWPatNoOffset<i32, rmw_32, inst_32>;
- defm : TerRMWPatNoOffset<i64, rmw_64, inst_64>;
-
- defm : TerRMWPatImmOff<i32, rmw_32, regPlusImm, inst_32>;
- defm : TerRMWPatImmOff<i64, rmw_64, regPlusImm, inst_64>;
- defm : TerRMWPatImmOff<i32, rmw_32, or_is_add, inst_32>;
- defm : TerRMWPatImmOff<i64, rmw_64, or_is_add, inst_64>;
-
- defm : TerRMWPatOffsetOnly<i32, rmw_32, inst_32>;
- defm : TerRMWPatOffsetOnly<i64, rmw_64, inst_64>;
-
- defm : TerRMWPatGlobalAddrOffOnly<i32, rmw_32, inst_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, rmw_64, inst_64>;
-}
-
-defm : TerRMWPattern<atomic_cmp_swap_32, atomic_cmp_swap_64,
- "ATOMIC_RMW_CMPXCHG_I32", "ATOMIC_RMW_CMPXCHG_I64">;
+defm : TerRMWPat<i32, atomic_cmp_swap_32, "ATOMIC_RMW_CMPXCHG_I32">;
+defm : TerRMWPat<i64, atomic_cmp_swap_64, "ATOMIC_RMW_CMPXCHG_I64">;
// Truncating & zero-extending ternary RMW patterns.
// DAG legalization & optimization before instruction selection may introduce
@@ -893,75 +523,13 @@ class sext_ter_rmw_8_64<PatFrag kind> :
class sext_ter_rmw_16_64<PatFrag kind> : sext_ter_rmw_8_64<kind>;
// 32->64 sext RMW gets selected as i32.atomic.rmw.***, i64.extend_i32_s
-// Patterns for various addressing modes for truncating-extending ternary RMWs.
-multiclass TerRMWTruncExtPattern<
- PatFrag rmw_8, PatFrag rmw_16, PatFrag rmw_32,
- string inst8_32, string inst16_32, string inst8_64, string inst16_64,
- string inst32_64> {
- // Truncating-extending ternary RMWs with no constant offset
- defm : TerRMWPatNoOffset<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatNoOffset<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatNoOffset<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatNoOffset<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>;
- defm : TerRMWPatNoOffset<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : TerRMWPatNoOffset<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatNoOffset<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatNoOffset<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatNoOffset<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>;
-
- // Truncating-extending ternary RMWs with a constant offset
- defm : TerRMWPatImmOff<i32, zext_ter_rmw_8_32<rmw_8>, regPlusImm, inst8_32>;
- defm : TerRMWPatImmOff<i32, zext_ter_rmw_16_32<rmw_16>, regPlusImm,
- inst16_32>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_8_64<rmw_8>, regPlusImm, inst8_64>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_16_64<rmw_16>, regPlusImm,
- inst16_64>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_32_64<rmw_32>, regPlusImm,
- inst32_64>;
- defm : TerRMWPatImmOff<i32, zext_ter_rmw_8_32<rmw_8>, or_is_add, inst8_32>;
- defm : TerRMWPatImmOff<i32, zext_ter_rmw_16_32<rmw_16>, or_is_add, inst16_32>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_8_64<rmw_8>, or_is_add, inst8_64>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_16_64<rmw_16>, or_is_add, inst16_64>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_32_64<rmw_32>, or_is_add, inst32_64>;
-
- defm : TerRMWPatImmOff<i32, sext_ter_rmw_8_32<rmw_8>, regPlusImm, inst8_32>;
- defm : TerRMWPatImmOff<i32, sext_ter_rmw_16_32<rmw_16>, regPlusImm,
- inst16_32>;
- defm : TerRMWPatImmOff<i64, sext_ter_rmw_8_64<rmw_8>, regPlusImm, inst8_64>;
- defm : TerRMWPatImmOff<i64, sext_ter_rmw_16_64<rmw_16>, regPlusImm,
- inst16_64>;
- defm : TerRMWPatImmOff<i32, sext_ter_rmw_8_32<rmw_8>, or_is_add, inst8_32>;
- defm : TerRMWPatImmOff<i32, sext_ter_rmw_16_32<rmw_16>, or_is_add, inst16_32>;
- defm : TerRMWPatImmOff<i64, sext_ter_rmw_8_64<rmw_8>, or_is_add, inst8_64>;
- defm : TerRMWPatImmOff<i64, sext_ter_rmw_16_64<rmw_16>, or_is_add, inst16_64>;
-
- // Truncating-extending ternary RMWs with just a constant offset
- defm : TerRMWPatOffsetOnly<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatOffsetOnly<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatOffsetOnly<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatOffsetOnly<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>;
- defm : TerRMWPatOffsetOnly<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : TerRMWPatOffsetOnly<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatOffsetOnly<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatOffsetOnly<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatOffsetOnly<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>;
-
- defm : TerRMWPatGlobalAddrOffOnly<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : TerRMWPatGlobalAddrOffOnly<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>;
-}
+defm : TerRMWPat<i32, zext_ter_rmw_8_32<atomic_cmp_swap_8>, "ATOMIC_RMW8_U_CMPXCHG_I32">;
+defm : TerRMWPat<i32, zext_ter_rmw_16_32<atomic_cmp_swap_16>, "ATOMIC_RMW16_U_CMPXCHG_I32">;
+defm : TerRMWPat<i64, zext_ter_rmw_8_64<atomic_cmp_swap_8>, "ATOMIC_RMW8_U_CMPXCHG_I64">;
+defm : TerRMWPat<i64, zext_ter_rmw_16_64<atomic_cmp_swap_16>, "ATOMIC_RMW16_U_CMPXCHG_I64">;
+defm : TerRMWPat<i64, zext_ter_rmw_32_64<atomic_cmp_swap_32>, "ATOMIC_RMW32_U_CMPXCHG_I64">;
-defm : TerRMWTruncExtPattern<
- atomic_cmp_swap_8, atomic_cmp_swap_16, atomic_cmp_swap_32,
- "ATOMIC_RMW8_U_CMPXCHG_I32", "ATOMIC_RMW16_U_CMPXCHG_I32",
- "ATOMIC_RMW8_U_CMPXCHG_I64", "ATOMIC_RMW16_U_CMPXCHG_I64",
- "ATOMIC_RMW32_U_CMPXCHG_I64">;
+defm : TerRMWPat<i32, sext_ter_rmw_8_32<atomic_cmp_swap_8>, "ATOMIC_RMW8_U_CMPXCHG_I32">;
+defm : TerRMWPat<i32, sext_ter_rmw_16_32<atomic_cmp_swap_16>, "ATOMIC_RMW16_U_CMPXCHG_I32">;
+defm : TerRMWPat<i64, sext_ter_rmw_8_64<atomic_cmp_swap_8>, "ATOMIC_RMW8_U_CMPXCHG_I64">;
+defm : TerRMWPat<i64, sext_ter_rmw_16_64<atomic_cmp_swap_16>, "ATOMIC_RMW16_U_CMPXCHG_I64">;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
index d7720604d6dc..b2dd656ccdda 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
@@ -197,10 +197,37 @@ WebAssemblyInstrInfo::getSerializableTargetIndices() const {
{WebAssembly::TI_OPERAND_STACK, "wasm-operand-stack"},
{WebAssembly::TI_GLOBAL_RELOC, "wasm-global-reloc"},
{WebAssembly::TI_LOCAL_INDIRECT, "wasm-local-indirect"}};
- return makeArrayRef(TargetIndices);
+ return ArrayRef(TargetIndices);
}
const MachineOperand &
WebAssemblyInstrInfo::getCalleeOperand(const MachineInstr &MI) const {
return WebAssembly::getCalleeOp(MI);
}
+
+// This returns true when the instruction defines a value of a TargetIndex
+// operand that can be tracked by offsets. For Wasm, this returns true for only
+// local.set/local.tees. This is currently used by LiveDebugValues analysis.
+//
+// These are not included:
+// - In theory we need to add global.set here too, but we don't have global
+// indices at this point because they are relocatable and we address them by
+// names until linking, so we don't have 'offsets' (which are used to store
+// local/global indices) to deal with in LiveDebugValues. And we don't
+// associate debug info in values in globals anyway.
+// - All other value-producing instructions, i.e. instructions with defs, can
+// define values in the Wasm stack, which is represented by TI_OPERAND_STACK
+// TargetIndex. But they don't have offset info within the instruction itself,
+// and debug info analysis for them is handled separately in
+// WebAssemblyDebugFixup pass, so we don't worry about them here.
+bool WebAssemblyInstrInfo::isExplicitTargetIndexDef(const MachineInstr &MI,
+ int &Index,
+ int64_t &Offset) const {
+ unsigned Opc = MI.getOpcode();
+ if (WebAssembly::isLocalSet(Opc) || WebAssembly::isLocalTee(Opc)) {
+ Index = WebAssembly::TI_LOCAL;
+ Offset = MI.explicit_uses().begin()->getImm();
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.h
index 29d700bdf83f..c1e1a790c60e 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.h
@@ -69,6 +69,9 @@ public:
getSerializableTargetIndices() const override;
const MachineOperand &getCalleeOperand(const MachineInstr &MI) const override;
+
+ bool isExplicitTargetIndexDef(const MachineInstr &MI, int &Index,
+ int64_t &Offset) const override;
};
} // end namespace llvm
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
index d5bb9e9e48b4..01c0909af72e 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
@@ -19,25 +19,19 @@
// local types. These memory-only types instead zero- or sign-extend into local
// types when loading, and truncate when storing.
-// WebAssembly constant offsets are performed as unsigned with infinite
-// precision, so we need to check for NoUnsignedWrap so that we don't fold an
-// offset for an add that needs wrapping.
-def regPlusImm : PatFrag<(ops node:$addr, node:$off),
- (add node:$addr, node:$off),
- [{ return N->getFlags().hasNoUnsignedWrap(); }]>;
-
-// Treat an 'or' node as an 'add' if the or'ed bits are known to be zero.
-def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
- if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
- return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
-
- KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
- KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
- return (~Known0.Zero & ~Known1.Zero) == 0;
-}]>;
-
-// We don't need a regPlusES because external symbols never have constant
-// offsets folded into them, so we can just use add.
+// Address Operands
+
+// These patterns match the static (offset) and dynamic (address stack operand)
+// operands for loads and stores, based on a combination of target global
+// addresses and constants.
+// For example,
+// (load (add tga, x)) -> load offset=tga, addr=x
+// (store v, tga) -> store v, offset=tga, addr=0
+// (load (add const, x)) -> load offset=const, addr=x
+// (store v, const) -> store v, offset=const, addr=0
+// (load x) -> load offset=0, addr=x
+def AddrOps32 : ComplexPattern<i32, 2, "SelectAddrOperands32">;
+def AddrOps64 : ComplexPattern<i64, 2, "SelectAddrOperands64">;
// Defines atomic and non-atomic loads, regular and extending.
multiclass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode,
@@ -66,70 +60,6 @@ defm LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29, []>;
defm LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a, []>;
defm LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b, []>;
-// Select loads with no constant offset.
-multiclass LoadPatNoOffset<ValueType ty, SDPatternOperator kind, string inst> {
- def : Pat<(ty (kind I32:$addr)), (!cast<NI>(inst # "_A32") 0, 0, I32:$addr)>,
- Requires<[HasAddr32]>;
- def : Pat<(ty (kind (i64 I64:$addr))), (!cast<NI>(inst # "_A64") 0, 0, I64:$addr)>,
- Requires<[HasAddr64]>;
-}
-
-defm : LoadPatNoOffset<i32, load, "LOAD_I32">;
-defm : LoadPatNoOffset<i64, load, "LOAD_I64">;
-defm : LoadPatNoOffset<f32, load, "LOAD_F32">;
-defm : LoadPatNoOffset<f64, load, "LOAD_F64">;
-
-// Select loads with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass LoadPatImmOff<ValueType ty, SDPatternOperator kind, PatFrag operand,
- string inst> {
- def : Pat<(ty (kind (operand I32:$addr, imm:$off))),
- (!cast<NI>(inst # "_A32") 0, imm:$off, I32:$addr)>,
- Requires<[HasAddr32]>;
- def : Pat<(ty (kind (operand I64:$addr, imm:$off))),
- (!cast<NI>(inst # "_A64") 0, imm:$off, I64:$addr)>,
- Requires<[HasAddr64]>;
-}
-
-defm : LoadPatImmOff<i32, load, regPlusImm, "LOAD_I32">;
-defm : LoadPatImmOff<i64, load, regPlusImm, "LOAD_I64">;
-defm : LoadPatImmOff<f32, load, regPlusImm, "LOAD_F32">;
-defm : LoadPatImmOff<f64, load, regPlusImm, "LOAD_F64">;
-defm : LoadPatImmOff<i32, load, or_is_add, "LOAD_I32">;
-defm : LoadPatImmOff<i64, load, or_is_add, "LOAD_I64">;
-defm : LoadPatImmOff<f32, load, or_is_add, "LOAD_F32">;
-defm : LoadPatImmOff<f64, load, or_is_add, "LOAD_F64">;
-
-// Select loads with just a constant offset.
-multiclass LoadPatOffsetOnly<ValueType ty, SDPatternOperator kind, string inst> {
- def : Pat<(ty (kind imm:$off)),
- (!cast<NI>(inst # "_A32") 0, imm:$off, (CONST_I32 0))>,
- Requires<[HasAddr32]>;
- def : Pat<(ty (kind imm:$off)),
- (!cast<NI>(inst # "_A64") 0, imm:$off, (CONST_I64 0))>,
- Requires<[HasAddr64]>;
-}
-
-defm : LoadPatOffsetOnly<i32, load, "LOAD_I32">;
-defm : LoadPatOffsetOnly<i64, load, "LOAD_I64">;
-defm : LoadPatOffsetOnly<f32, load, "LOAD_F32">;
-defm : LoadPatOffsetOnly<f64, load, "LOAD_F64">;
-
-multiclass LoadPatGlobalAddrOffOnly<ValueType ty, SDPatternOperator kind, string inst> {
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off))),
- (!cast<NI>(inst # "_A32") 0, tglobaladdr:$off, (CONST_I32 0))>,
- Requires<[IsNotPIC, HasAddr32]>;
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off))),
- (!cast<NI>(inst # "_A64") 0, tglobaladdr:$off, (CONST_I64 0))>,
- Requires<[IsNotPIC, HasAddr64]>;
-}
-
-defm : LoadPatGlobalAddrOffOnly<i32, load, "LOAD_I32">;
-defm : LoadPatGlobalAddrOffOnly<i64, load, "LOAD_I64">;
-defm : LoadPatGlobalAddrOffOnly<f32, load, "LOAD_F32">;
-defm : LoadPatGlobalAddrOffOnly<f64, load, "LOAD_F64">;
-
// Extending load.
defm LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c, []>;
defm LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d, []>;
@@ -142,98 +72,44 @@ defm LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x33, []>;
defm LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34, []>;
defm LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35, []>;
-// Select extending loads with no constant offset.
-defm : LoadPatNoOffset<i32, sextloadi8, "LOAD8_S_I32">;
-defm : LoadPatNoOffset<i32, zextloadi8, "LOAD8_U_I32">;
-defm : LoadPatNoOffset<i32, sextloadi16, "LOAD16_S_I32">;
-defm : LoadPatNoOffset<i32, zextloadi16, "LOAD16_U_I32">;
-defm : LoadPatNoOffset<i64, sextloadi8, "LOAD8_S_I64">;
-defm : LoadPatNoOffset<i64, zextloadi8, "LOAD8_U_I64">;
-defm : LoadPatNoOffset<i64, sextloadi16, "LOAD16_S_I64">;
-defm : LoadPatNoOffset<i64, zextloadi16, "LOAD16_U_I64">;
-defm : LoadPatNoOffset<i64, sextloadi32, "LOAD32_S_I64">;
-defm : LoadPatNoOffset<i64, zextloadi32, "LOAD32_U_I64">;
+// Pattern matching
-// Select extending loads with a constant offset.
-defm : LoadPatImmOff<i32, sextloadi8, regPlusImm, "LOAD8_S_I32">;
-defm : LoadPatImmOff<i32, zextloadi8, regPlusImm, "LOAD8_U_I32">;
-defm : LoadPatImmOff<i32, sextloadi16, regPlusImm, "LOAD16_S_I32">;
-defm : LoadPatImmOff<i32, zextloadi16, regPlusImm, "LOAD16_U_I32">;
-defm : LoadPatImmOff<i64, sextloadi8, regPlusImm, "LOAD8_S_I64">;
-defm : LoadPatImmOff<i64, zextloadi8, regPlusImm, "LOAD8_U_I64">;
-defm : LoadPatImmOff<i64, sextloadi16, regPlusImm, "LOAD16_S_I64">;
-defm : LoadPatImmOff<i64, zextloadi16, regPlusImm, "LOAD16_U_I64">;
-defm : LoadPatImmOff<i64, sextloadi32, regPlusImm, "LOAD32_S_I64">;
-defm : LoadPatImmOff<i64, zextloadi32, regPlusImm, "LOAD32_U_I64">;
+multiclass LoadPat<ValueType ty, SDPatternOperator kind, string Name> {
+ def : Pat<(ty (kind (AddrOps32 offset32_op:$offset, I32:$addr))),
+ (!cast<NI>(Name # "_A32") 0,
+ offset32_op:$offset,
+ I32:$addr)>,
+ Requires<[HasAddr32]>;
-defm : LoadPatImmOff<i32, sextloadi8, or_is_add, "LOAD8_S_I32">;
-defm : LoadPatImmOff<i32, zextloadi8, or_is_add, "LOAD8_U_I32">;
-defm : LoadPatImmOff<i32, sextloadi16, or_is_add, "LOAD16_S_I32">;
-defm : LoadPatImmOff<i32, zextloadi16, or_is_add, "LOAD16_U_I32">;
-defm : LoadPatImmOff<i64, sextloadi8, or_is_add, "LOAD8_S_I64">;
-defm : LoadPatImmOff<i64, zextloadi8, or_is_add, "LOAD8_U_I64">;
-defm : LoadPatImmOff<i64, sextloadi16, or_is_add, "LOAD16_S_I64">;
-defm : LoadPatImmOff<i64, zextloadi16, or_is_add, "LOAD16_U_I64">;
-defm : LoadPatImmOff<i64, sextloadi32, or_is_add, "LOAD32_S_I64">;
-defm : LoadPatImmOff<i64, zextloadi32, or_is_add, "LOAD32_U_I64">;
-
-// Select extending loads with just a constant offset.
-defm : LoadPatOffsetOnly<i32, sextloadi8, "LOAD8_S_I32">;
-defm : LoadPatOffsetOnly<i32, zextloadi8, "LOAD8_U_I32">;
-defm : LoadPatOffsetOnly<i32, sextloadi16, "LOAD16_S_I32">;
-defm : LoadPatOffsetOnly<i32, zextloadi16, "LOAD16_U_I32">;
-
-defm : LoadPatOffsetOnly<i64, sextloadi8, "LOAD8_S_I64">;
-defm : LoadPatOffsetOnly<i64, zextloadi8, "LOAD8_U_I64">;
-defm : LoadPatOffsetOnly<i64, sextloadi16, "LOAD16_S_I64">;
-defm : LoadPatOffsetOnly<i64, zextloadi16, "LOAD16_U_I64">;
-defm : LoadPatOffsetOnly<i64, sextloadi32, "LOAD32_S_I64">;
-defm : LoadPatOffsetOnly<i64, zextloadi32, "LOAD32_U_I64">;
-
-defm : LoadPatGlobalAddrOffOnly<i32, sextloadi8, "LOAD8_S_I32">;
-defm : LoadPatGlobalAddrOffOnly<i32, zextloadi8, "LOAD8_U_I32">;
-defm : LoadPatGlobalAddrOffOnly<i32, sextloadi16, "LOAD16_S_I32">;
-defm : LoadPatGlobalAddrOffOnly<i32, zextloadi16, "LOAD16_U_I32">;
-defm : LoadPatGlobalAddrOffOnly<i64, sextloadi8, "LOAD8_S_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, zextloadi8, "LOAD8_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, sextloadi16, "LOAD16_S_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, zextloadi16, "LOAD16_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, sextloadi32, "LOAD32_S_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, zextloadi32, "LOAD32_U_I64">;
-
-// Resolve "don't care" extending loads to zero-extending loads. This is
-// somewhat arbitrary, but zero-extending is conceptually simpler.
-
-// Select "don't care" extending loads with no constant offset.
-defm : LoadPatNoOffset<i32, extloadi8, "LOAD8_U_I32">;
-defm : LoadPatNoOffset<i32, extloadi16, "LOAD16_U_I32">;
-defm : LoadPatNoOffset<i64, extloadi8, "LOAD8_U_I64">;
-defm : LoadPatNoOffset<i64, extloadi16, "LOAD16_U_I64">;
-defm : LoadPatNoOffset<i64, extloadi32, "LOAD32_U_I64">;
-
-// Select "don't care" extending loads with a constant offset.
-defm : LoadPatImmOff<i32, extloadi8, regPlusImm, "LOAD8_U_I32">;
-defm : LoadPatImmOff<i32, extloadi16, regPlusImm, "LOAD16_U_I32">;
-defm : LoadPatImmOff<i64, extloadi8, regPlusImm, "LOAD8_U_I64">;
-defm : LoadPatImmOff<i64, extloadi16, regPlusImm, "LOAD16_U_I64">;
-defm : LoadPatImmOff<i64, extloadi32, regPlusImm, "LOAD32_U_I64">;
-defm : LoadPatImmOff<i32, extloadi8, or_is_add, "LOAD8_U_I32">;
-defm : LoadPatImmOff<i32, extloadi16, or_is_add, "LOAD16_U_I32">;
-defm : LoadPatImmOff<i64, extloadi8, or_is_add, "LOAD8_U_I64">;
-defm : LoadPatImmOff<i64, extloadi16, or_is_add, "LOAD16_U_I64">;
-defm : LoadPatImmOff<i64, extloadi32, or_is_add, "LOAD32_U_I64">;
+ def : Pat<(ty (kind (AddrOps64 offset64_op:$offset, I64:$addr))),
+ (!cast<NI>(Name # "_A64") 0,
+ offset64_op:$offset,
+ I64:$addr)>,
+ Requires<[HasAddr64]>;
+}
-// Select "don't care" extending loads with just a constant offset.
-defm : LoadPatOffsetOnly<i32, extloadi8, "LOAD8_U_I32">;
-defm : LoadPatOffsetOnly<i32, extloadi16, "LOAD16_U_I32">;
-defm : LoadPatOffsetOnly<i64, extloadi8, "LOAD8_U_I64">;
-defm : LoadPatOffsetOnly<i64, extloadi16, "LOAD16_U_I64">;
-defm : LoadPatOffsetOnly<i64, extloadi32, "LOAD32_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i32, extloadi8, "LOAD8_U_I32">;
-defm : LoadPatGlobalAddrOffOnly<i32, extloadi16, "LOAD16_U_I32">;
-defm : LoadPatGlobalAddrOffOnly<i64, extloadi8, "LOAD8_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, extloadi16, "LOAD16_U_I64">;
-defm : LoadPatGlobalAddrOffOnly<i64, extloadi32, "LOAD32_U_I64">;
+defm : LoadPat<i32, load, "LOAD_I32">;
+defm : LoadPat<i64, load, "LOAD_I64">;
+defm : LoadPat<f32, load, "LOAD_F32">;
+defm : LoadPat<f64, load, "LOAD_F64">;
+
+defm : LoadPat<i32, sextloadi8, "LOAD8_S_I32">;
+defm : LoadPat<i32, sextloadi16, "LOAD16_S_I32">;
+defm : LoadPat<i64, sextloadi8, "LOAD8_S_I64">;
+defm : LoadPat<i64, sextloadi16, "LOAD16_S_I64">;
+defm : LoadPat<i64, sextloadi32, "LOAD32_S_I64">;
+
+defm : LoadPat<i32, zextloadi8, "LOAD8_U_I32">;
+defm : LoadPat<i32, zextloadi16, "LOAD16_U_I32">;
+defm : LoadPat<i64, zextloadi8, "LOAD8_U_I64">;
+defm : LoadPat<i64, zextloadi16, "LOAD16_U_I64">;
+defm : LoadPat<i64, zextloadi32, "LOAD32_U_I64">;
+
+defm : LoadPat<i32, extloadi8, "LOAD8_U_I32">;
+defm : LoadPat<i32, extloadi16, "LOAD16_U_I32">;
+defm : LoadPat<i64, extloadi8, "LOAD8_U_I64">;
+defm : LoadPat<i64, extloadi16, "LOAD16_U_I64">;
+defm : LoadPat<i64, extloadi32, "LOAD32_U_I64">;
// Defines atomic and non-atomic stores, regular and truncating
multiclass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode,
@@ -263,69 +139,25 @@ defm STORE_I64 : WebAssemblyStore<I64, "i64.store", 0x37>;
defm STORE_F32 : WebAssemblyStore<F32, "f32.store", 0x38>;
defm STORE_F64 : WebAssemblyStore<F64, "f64.store", 0x39>;
-// Select stores with no constant offset.
-multiclass StorePatNoOffset<ValueType ty, PatFrag node, string inst> {
- def : Pat<(node ty:$val, I32:$addr),
- (!cast<NI>(inst # "_A32") 0, 0, I32:$addr, ty:$val)>,
- Requires<[HasAddr32]>;
- def : Pat<(node ty:$val, I64:$addr),
- (!cast<NI>(inst # "_A64") 0, 0, I64:$addr, ty:$val)>,
- Requires<[HasAddr64]>;
-}
-
-defm : StorePatNoOffset<i32, store, "STORE_I32">;
-defm : StorePatNoOffset<i64, store, "STORE_I64">;
-defm : StorePatNoOffset<f32, store, "STORE_F32">;
-defm : StorePatNoOffset<f64, store, "STORE_F64">;
-
-// Select stores with a constant offset.
-multiclass StorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand,
- string inst> {
- def : Pat<(kind ty:$val, (operand I32:$addr, imm:$off)),
- (!cast<NI>(inst # "_A32") 0, imm:$off, I32:$addr, ty:$val)>,
- Requires<[HasAddr32]>;
- def : Pat<(kind ty:$val, (operand I64:$addr, imm:$off)),
- (!cast<NI>(inst # "_A64") 0, imm:$off, I64:$addr, ty:$val)>,
- Requires<[HasAddr64]>;
-}
-
-defm : StorePatImmOff<i32, store, regPlusImm, "STORE_I32">;
-defm : StorePatImmOff<i64, store, regPlusImm, "STORE_I64">;
-defm : StorePatImmOff<f32, store, regPlusImm, "STORE_F32">;
-defm : StorePatImmOff<f64, store, regPlusImm, "STORE_F64">;
-defm : StorePatImmOff<i32, store, or_is_add, "STORE_I32">;
-defm : StorePatImmOff<i64, store, or_is_add, "STORE_I64">;
-defm : StorePatImmOff<f32, store, or_is_add, "STORE_F32">;
-defm : StorePatImmOff<f64, store, or_is_add, "STORE_F64">;
-
-// Select stores with just a constant offset.
-multiclass StorePatOffsetOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind ty:$val, imm:$off),
- (!cast<NI>(inst # "_A32") 0, imm:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32]>;
- def : Pat<(kind ty:$val, imm:$off),
- (!cast<NI>(inst # "_A64") 0, imm:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64]>;
+multiclass StorePat<ValueType ty, SDPatternOperator kind, string Name> {
+ def : Pat<(kind ty:$val, (AddrOps32 offset32_op:$offset, I32:$addr)),
+ (!cast<NI>(Name # "_A32") 0,
+ offset32_op:$offset,
+ I32:$addr,
+ ty:$val)>,
+ Requires<[HasAddr32]>;
+ def : Pat<(kind ty:$val, (AddrOps64 offset64_op:$offset, I64:$addr)),
+ (!cast<NI>(Name # "_A64") 0,
+ offset64_op:$offset,
+ I64:$addr,
+ ty:$val)>,
+ Requires<[HasAddr64]>;
}
-defm : StorePatOffsetOnly<i32, store, "STORE_I32">;
-defm : StorePatOffsetOnly<i64, store, "STORE_I64">;
-defm : StorePatOffsetOnly<f32, store, "STORE_F32">;
-defm : StorePatOffsetOnly<f64, store, "STORE_F64">;
-multiclass StorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind ty:$val, (WebAssemblyWrapper tglobaladdr:$off)),
- (!cast<NI>(inst # "_A32") 0, tglobaladdr:$off, (CONST_I32 0),
- ty:$val)>,
- Requires<[IsNotPIC, HasAddr32]>;
- def : Pat<(kind ty:$val, (WebAssemblyWrapper tglobaladdr:$off)),
- (!cast<NI>(inst # "_A64") 0, tglobaladdr:$off, (CONST_I64 0),
- ty:$val)>,
- Requires<[IsNotPIC, HasAddr64]>;
-}
-defm : StorePatGlobalAddrOffOnly<i32, store, "STORE_I32">;
-defm : StorePatGlobalAddrOffOnly<i64, store, "STORE_I64">;
-defm : StorePatGlobalAddrOffOnly<f32, store, "STORE_F32">;
-defm : StorePatGlobalAddrOffOnly<f64, store, "STORE_F64">;
+defm : StorePat<i32, store, "STORE_I32">;
+defm : StorePat<i64, store, "STORE_I64">;
+defm : StorePat<f32, store, "STORE_F32">;
+defm : StorePat<f64, store, "STORE_F64">;
// Truncating store.
defm STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>;
@@ -334,36 +166,11 @@ defm STORE8_I64 : WebAssemblyStore<I64, "i64.store8", 0x3c>;
defm STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>;
defm STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>;
-// Select truncating stores with no constant offset.
-defm : StorePatNoOffset<i32, truncstorei8, "STORE8_I32">;
-defm : StorePatNoOffset<i32, truncstorei16, "STORE16_I32">;
-defm : StorePatNoOffset<i64, truncstorei8, "STORE8_I64">;
-defm : StorePatNoOffset<i64, truncstorei16, "STORE16_I64">;
-defm : StorePatNoOffset<i64, truncstorei32, "STORE32_I64">;
-
-// Select truncating stores with a constant offset.
-defm : StorePatImmOff<i32, truncstorei8, regPlusImm, "STORE8_I32">;
-defm : StorePatImmOff<i32, truncstorei16, regPlusImm, "STORE16_I32">;
-defm : StorePatImmOff<i64, truncstorei8, regPlusImm, "STORE8_I64">;
-defm : StorePatImmOff<i64, truncstorei16, regPlusImm, "STORE16_I64">;
-defm : StorePatImmOff<i64, truncstorei32, regPlusImm, "STORE32_I64">;
-defm : StorePatImmOff<i32, truncstorei8, or_is_add, "STORE8_I32">;
-defm : StorePatImmOff<i32, truncstorei16, or_is_add, "STORE16_I32">;
-defm : StorePatImmOff<i64, truncstorei8, or_is_add, "STORE8_I64">;
-defm : StorePatImmOff<i64, truncstorei16, or_is_add, "STORE16_I64">;
-defm : StorePatImmOff<i64, truncstorei32, or_is_add, "STORE32_I64">;
-
-// Select truncating stores with just a constant offset.
-defm : StorePatOffsetOnly<i32, truncstorei8, "STORE8_I32">;
-defm : StorePatOffsetOnly<i32, truncstorei16, "STORE16_I32">;
-defm : StorePatOffsetOnly<i64, truncstorei8, "STORE8_I64">;
-defm : StorePatOffsetOnly<i64, truncstorei16, "STORE16_I64">;
-defm : StorePatOffsetOnly<i64, truncstorei32, "STORE32_I64">;
-defm : StorePatGlobalAddrOffOnly<i32, truncstorei8, "STORE8_I32">;
-defm : StorePatGlobalAddrOffOnly<i32, truncstorei16, "STORE16_I32">;
-defm : StorePatGlobalAddrOffOnly<i64, truncstorei8, "STORE8_I64">;
-defm : StorePatGlobalAddrOffOnly<i64, truncstorei16, "STORE16_I64">;
-defm : StorePatGlobalAddrOffOnly<i64, truncstorei32, "STORE32_I64">;
+defm : StorePat<i32, truncstorei8, "STORE8_I32">;
+defm : StorePat<i32, truncstorei16, "STORE16_I32">;
+defm : StorePat<i64, truncstorei8, "STORE8_I64">;
+defm : StorePat<i64, truncstorei16, "STORE16_I64">;
+defm : StorePat<i64, truncstorei32, "STORE32_I64">;
multiclass MemoryOps<WebAssemblyRegClass rc, string B> {
// Current memory size.
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index ed3cc7ed1c53..ad2ec40b8b31 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -54,15 +54,6 @@ def ImmI#SIZE : ImmLeaf<i32,
foreach SIZE = [2, 4, 8, 16, 32] in
def LaneIdx#SIZE : ImmLeaf<i32, "return 0 <= Imm && Imm < "#SIZE#";">;
-// Create vector with identical lanes: splat
-def splat2 : PatFrag<(ops node:$x), (build_vector $x, $x)>;
-def splat4 : PatFrag<(ops node:$x), (build_vector $x, $x, $x, $x)>;
-def splat8 : PatFrag<(ops node:$x), (build_vector $x, $x, $x, $x,
- $x, $x, $x, $x)>;
-def splat16 : PatFrag<(ops node:$x),
- (build_vector $x, $x, $x, $x, $x, $x, $x, $x,
- $x, $x, $x, $x, $x, $x, $x, $x)>;
-
class Vec {
ValueType vt;
ValueType int_vt;
@@ -70,6 +61,7 @@ class Vec {
WebAssemblyRegClass lane_rc;
int lane_bits;
ImmLeaf lane_idx;
+ SDPatternOperator lane_load;
PatFrag splat;
string prefix;
Vec split;
@@ -82,7 +74,8 @@ def I8x16 : Vec {
let lane_rc = I32;
let lane_bits = 8;
let lane_idx = LaneIdx16;
- let splat = splat16;
+ let lane_load = extloadi8;
+ let splat = PatFrag<(ops node:$x), (v16i8 (splat_vector (i8 $x)))>;
let prefix = "i8x16";
}
@@ -93,7 +86,8 @@ def I16x8 : Vec {
let lane_rc = I32;
let lane_bits = 16;
let lane_idx = LaneIdx8;
- let splat = splat8;
+ let lane_load = extloadi16;
+ let splat = PatFrag<(ops node:$x), (v8i16 (splat_vector (i16 $x)))>;
let prefix = "i16x8";
let split = I8x16;
}
@@ -105,7 +99,8 @@ def I32x4 : Vec {
let lane_rc = I32;
let lane_bits = 32;
let lane_idx = LaneIdx4;
- let splat = splat4;
+ let lane_load = load;
+ let splat = PatFrag<(ops node:$x), (v4i32 (splat_vector (i32 $x)))>;
let prefix = "i32x4";
let split = I16x8;
}
@@ -117,7 +112,8 @@ def I64x2 : Vec {
let lane_rc = I64;
let lane_bits = 64;
let lane_idx = LaneIdx2;
- let splat = splat2;
+ let lane_load = load;
+ let splat = PatFrag<(ops node:$x), (v2i64 (splat_vector (i64 $x)))>;
let prefix = "i64x2";
let split = I32x4;
}
@@ -129,7 +125,8 @@ def F32x4 : Vec {
let lane_rc = F32;
let lane_bits = 32;
let lane_idx = LaneIdx4;
- let splat = splat4;
+ let lane_load = load;
+ let splat = PatFrag<(ops node:$x), (v4f32 (splat_vector (f32 $x)))>;
let prefix = "f32x4";
}
@@ -140,7 +137,8 @@ def F64x2 : Vec {
let lane_rc = F64;
let lane_bits = 64;
let lane_idx = LaneIdx2;
- let splat = splat2;
+ let lane_load = load;
+ let splat = PatFrag<(ops node:$x), (v2f64 (splat_vector (f64 $x)))>;
let prefix = "f64x2";
}
@@ -167,11 +165,7 @@ defm LOAD_V128_A64 :
// Def load patterns from WebAssemblyInstrMemory.td for vector types
foreach vec = AllVecs in {
-defm : LoadPatNoOffset<vec.vt, load, "LOAD_V128">;
-defm : LoadPatImmOff<vec.vt, load, regPlusImm, "LOAD_V128">;
-defm : LoadPatImmOff<vec.vt, load, or_is_add, "LOAD_V128">;
-defm : LoadPatOffsetOnly<vec.vt, load, "LOAD_V128">;
-defm : LoadPatGlobalAddrOffOnly<vec.vt, load, "LOAD_V128">;
+defm : LoadPat<vec.vt, load, "LOAD_V128">;
}
// v128.loadX_splat
@@ -199,18 +193,11 @@ defm "" : SIMDLoadSplat<16, 8>;
defm "" : SIMDLoadSplat<32, 9>;
defm "" : SIMDLoadSplat<64, 10>;
-def wasm_load_splat_t : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>;
-def wasm_load_splat : SDNode<"WebAssemblyISD::LOAD_SPLAT", wasm_load_splat_t,
- [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
-def load_splat : PatFrag<(ops node:$addr), (wasm_load_splat node:$addr)>;
-
foreach vec = AllVecs in {
-defvar inst = "LOAD"#vec.lane_bits#"_SPLAT";
-defm : LoadPatNoOffset<vec.vt, load_splat, inst>;
-defm : LoadPatImmOff<vec.vt, load_splat, regPlusImm, inst>;
-defm : LoadPatImmOff<vec.vt, load_splat, or_is_add, inst>;
-defm : LoadPatOffsetOnly<vec.vt, load_splat, inst>;
-defm : LoadPatGlobalAddrOffOnly<vec.vt, load_splat, inst>;
+ defvar inst = "LOAD"#vec.lane_bits#"_SPLAT";
+ defm : LoadPat<vec.vt,
+ PatFrag<(ops node:$addr), (splat_vector (vec.lane_vt (vec.lane_load node:$addr)))>,
+ inst>;
}
// Load and extend
@@ -255,11 +242,7 @@ foreach exts = [["sextloadvi", "_S"],
["extloadvi", "_U"]] in {
defvar loadpat = !cast<PatFrag>(exts[0]#vec.split.lane_bits);
defvar inst = "LOAD_EXTEND"#exts[1]#"_"#vec;
-defm : LoadPatNoOffset<vec.vt, loadpat, inst>;
-defm : LoadPatImmOff<vec.vt, loadpat, regPlusImm, inst>;
-defm : LoadPatImmOff<vec.vt, loadpat, or_is_add, inst>;
-defm : LoadPatOffsetOnly<vec.vt, loadpat, inst>;
-defm : LoadPatGlobalAddrOffOnly<vec.vt, loadpat, inst>;
+defm : LoadPat<vec.vt, loadpat, inst>;
}
// Load lane into zero vector
@@ -285,25 +268,19 @@ defm "" : SIMDLoadZero<I32x4, 0x5c>;
defm "" : SIMDLoadZero<I64x2, 0x5d>;
// Use load_zero to load scalars into vectors as well where possible.
-// TODO: i32, i16, and i8 scalars
-def load_scalar :
- PatFrag<(ops node:$addr), (scalar_to_vector (i64 (load $addr)))>;
-defm : LoadPatNoOffset<v2i64, load_scalar, "LOAD_ZERO_I64x2">;
-defm : LoadPatImmOff<v2i64, load_scalar, regPlusImm, "LOAD_ZERO_I64x2">;
-defm : LoadPatImmOff<v2i64, load_scalar, or_is_add, "LOAD_ZERO_I64x2">;
-defm : LoadPatOffsetOnly<v2i64, load_scalar, "LOAD_ZERO_I64x2">;
-defm : LoadPatGlobalAddrOffOnly<v2i64, load_scalar, "LOAD_ZERO_I64x2">;
+// TODO: i16, and i8 scalars
+foreach vec = [I32x4, I64x2] in {
+ defvar inst = "LOAD_ZERO_"#vec;
+ defvar pat = PatFrag<(ops node:$addr), (scalar_to_vector (vec.lane_vt (load $addr)))>;
+ defm : LoadPat<vec.vt, pat, inst>;
+}
// TODO: f32x4 and f64x2 as well
foreach vec = [I32x4, I64x2] in {
defvar inst = "LOAD_ZERO_"#vec;
defvar pat = PatFrag<(ops node:$ptr),
(vector_insert (vec.splat (vec.lane_vt 0)), (vec.lane_vt (load $ptr)), 0)>;
- defm : LoadPatNoOffset<vec.vt, pat, inst>;
- defm : LoadPatImmOff<vec.vt, pat, regPlusImm, inst>;
- defm : LoadPatImmOff<vec.vt, pat, or_is_add, inst>;
- defm : LoadPatOffsetOnly<vec.vt, pat, inst>;
- defm : LoadPatGlobalAddrOffOnly<vec.vt, pat, inst>;
+ defm : LoadPat<vec.vt, pat, inst>;
}
// Load lane
@@ -384,11 +361,7 @@ defm STORE_V128_A64 :
// Def store patterns from WebAssemblyInstrMemory.td for vector types
foreach vec = AllVecs in {
-defm : StorePatNoOffset<vec.vt, store, "STORE_V128">;
-defm : StorePatImmOff<vec.vt, store, regPlusImm, "STORE_V128">;
-defm : StorePatImmOff<vec.vt, store, or_is_add, "STORE_V128">;
-defm : StorePatOffsetOnly<vec.vt, store, "STORE_V128">;
-defm : StorePatGlobalAddrOffOnly<vec.vt, store, "STORE_V128">;
+defm : StorePat<vec.vt, store, "STORE_V128">;
}
// Store lane
@@ -417,13 +390,16 @@ defm "" : SIMDStoreLane<I16x8, 0x59>;
defm "" : SIMDStoreLane<I32x4, 0x5a>;
defm "" : SIMDStoreLane<I64x2, 0x5b>;
-// Select stores with no constant offset.
-multiclass StoreLanePatNoOffset<Vec vec, SDPatternOperator kind> {
- def : Pat<(kind (i32 I32:$addr), (vec.vt V128:$vec), (i32 vec.lane_idx:$idx)),
- (!cast<NI>("STORE_LANE_"#vec#"_A32") 0, 0, imm:$idx, $addr, $vec)>,
+multiclass StoreLanePat<Vec vec, SDPatternOperator kind> {
+ def : Pat<(kind (AddrOps32 offset32_op:$offset, I32:$addr),
+ (vec.vt V128:$vec),
+ (i32 vec.lane_idx:$idx)),
+ (!cast<NI>("STORE_LANE_"#vec#"_A32") 0, $offset, imm:$idx, $addr, $vec)>,
Requires<[HasAddr32]>;
- def : Pat<(kind (i64 I64:$addr), (vec.vt V128:$vec), (i32 vec.lane_idx:$idx)),
- (!cast<NI>("STORE_LANE_"#vec#"_A64") 0, 0, imm:$idx, $addr, $vec)>,
+ def : Pat<(kind (AddrOps64 offset64_op:$offset, I64:$addr),
+ (vec.vt V128:$vec),
+ (i32 vec.lane_idx:$idx)),
+ (!cast<NI>("STORE_LANE_"#vec#"_A64") 0, $offset, imm:$idx, $addr, $vec)>,
Requires<[HasAddr64]>;
}
@@ -442,10 +418,10 @@ def store64_lane :
// TODO: floating point lanes as well
let AddedComplexity = 1 in {
-defm : StoreLanePatNoOffset<I8x16, store8_lane>;
-defm : StoreLanePatNoOffset<I16x8, store16_lane>;
-defm : StoreLanePatNoOffset<I32x4, store32_lane>;
-defm : StoreLanePatNoOffset<I64x2, store64_lane>;
+defm : StoreLanePat<I8x16, store8_lane>;
+defm : StoreLanePat<I16x8, store16_lane>;
+defm : StoreLanePat<I32x4, store32_lane>;
+defm : StoreLanePat<I64x2, store64_lane>;
}
//===----------------------------------------------------------------------===//
@@ -507,6 +483,17 @@ defm "" : ConstVec<F64x2,
(build_vector (f64 fpimm:$i0), (f64 fpimm:$i1)),
"$i0, $i1">;
+// Match splat(x) -> const.v128(x, ..., x)
+foreach vec = AllVecs in {
+ defvar numEls = !div(vec.vt.Size, vec.lane_bits);
+ defvar isFloat = !or(!eq(vec.lane_vt, f32), !eq(vec.lane_vt, f64));
+ defvar immKind = !if(isFloat, fpimm, imm);
+ def : Pat<(vec.splat (vec.lane_vt immKind:$x)),
+ !dag(!cast<NI>("CONST_V128_"#vec),
+ !listsplat((vec.lane_vt immKind:$x), numEls),
+ ?)>;
+}
+
// Shuffle lanes: shuffle
defm SHUFFLE :
SIMD_I<(outs V128:$dst),
@@ -811,6 +798,20 @@ def : Pat<(vec.vt (or (and (vec.vt V128:$c), (vec.vt V128:$v1)),
(and (vnot V128:$c), (vec.vt V128:$v2)))),
(BITSELECT $v1, $v2, $c)>;
+// Bitselect is also equivalent to ((v1 ^ v2) & c) ^ v2
+foreach vec = IntVecs in
+def : Pat<(vec.vt (xor (and (xor (vec.vt V128:$v1), (vec.vt V128:$v2)),
+ (vec.vt V128:$c)),
+ (vec.vt V128:$v2))),
+ (BITSELECT $v1, $v2, $c)>;
+
+// Same pattern with `c` negated so `a` and `b` get swapped.
+foreach vec = IntVecs in
+def : Pat<(vec.vt (xor (and (xor (vec.vt V128:$v1), (vec.vt V128:$v2)),
+ (vnot (vec.vt V128:$c))),
+ (vec.vt V128:$v2))),
+ (BITSELECT $v2, $v1, $c)>;
+
// Also implement vselect in terms of bitselect
foreach vec = AllVecs in
def : Pat<(vec.vt (vselect
@@ -1364,26 +1365,26 @@ defm "" : RelaxedConvert<I32x4, F64x2, int_wasm_relaxed_trunc_unsigned_zero,
"relaxed_trunc_f64x2_u_zero", 0x104>;
//===----------------------------------------------------------------------===//
-// Relaxed Fused Multiply- Add and Subtract (FMA/FMS)
+// Relaxed (Negative) Multiply-Add (madd/nmadd)
//===----------------------------------------------------------------------===//
-multiclass SIMDFM<Vec vec, bits<32> simdopA, bits<32> simdopS> {
- defm FMA_#vec :
+multiclass SIMDMADD<Vec vec, bits<32> simdopA, bits<32> simdopS> {
+ defm MADD_#vec :
RELAXED_I<(outs V128:$dst), (ins V128:$a, V128:$b, V128:$c), (outs), (ins),
- [(set (vec.vt V128:$dst), (int_wasm_fma
+ [(set (vec.vt V128:$dst), (int_wasm_relaxed_madd
(vec.vt V128:$a), (vec.vt V128:$b), (vec.vt V128:$c)))],
- vec.prefix#".relaxed_fma\t$dst, $a, $b, $c",
- vec.prefix#".relaxed_fma", simdopA>;
- defm FMS_#vec :
+ vec.prefix#".relaxed_madd\t$dst, $a, $b, $c",
+ vec.prefix#".relaxed_madd", simdopA>;
+ defm NMADD_#vec :
RELAXED_I<(outs V128:$dst), (ins V128:$a, V128:$b, V128:$c), (outs), (ins),
- [(set (vec.vt V128:$dst), (int_wasm_fms
+ [(set (vec.vt V128:$dst), (int_wasm_relaxed_nmadd
(vec.vt V128:$a), (vec.vt V128:$b), (vec.vt V128:$c)))],
- vec.prefix#".relaxed_fms\t$dst, $a, $b, $c",
- vec.prefix#".relaxed_fms", simdopS>;
+ vec.prefix#".relaxed_nmadd\t$dst, $a, $b, $c",
+ vec.prefix#".relaxed_nmadd", simdopS>;
}
-defm "" : SIMDFM<F32x4, 0x105, 0x106>;
-defm "" : SIMDFM<F64x2, 0x107, 0x108>;
+defm "" : SIMDMADD<F32x4, 0x105, 0x106>;
+defm "" : SIMDMADD<F64x2, 0x107, 0x108>;
//===----------------------------------------------------------------------===//
// Laneselect
@@ -1392,7 +1393,7 @@ defm "" : SIMDFM<F64x2, 0x107, 0x108>;
multiclass SIMDLANESELECT<Vec vec, bits<32> op> {
defm LANESELECT_#vec :
RELAXED_I<(outs V128:$dst), (ins V128:$a, V128:$b, V128:$c), (outs), (ins),
- [(set (vec.vt V128:$dst), (int_wasm_laneselect
+ [(set (vec.vt V128:$dst), (int_wasm_relaxed_laneselect
(vec.vt V128:$a), (vec.vt V128:$b), (vec.vt V128:$c)))],
vec.prefix#".relaxed_laneselect\t$dst, $a, $b, $c",
vec.prefix#".relaxed_laneselect", op>;
@@ -1440,15 +1441,27 @@ defm RELAXED_Q15MULR_S :
defm RELAXED_DOT :
RELAXED_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), (outs), (ins),
- [(set (v8i16 V128:$dst), (int_wasm_dot_i8x16_i7x16_signed
+ [(set (v8i16 V128:$dst), (int_wasm_relaxed_dot_i8x16_i7x16_signed
(v16i8 V128:$lhs), (v16i8 V128:$rhs)))],
- "i16x8.dot_i8x16_i7x16_s\t$dst, $lhs, $rhs",
- "i16x8.dot_i8x16_i7x16_s", 0x112>;
+ "i16x8.relaxed_dot_i8x16_i7x16_s\t$dst, $lhs, $rhs",
+ "i16x8.relaxed_dot_i8x16_i7x16_s", 0x112>;
defm RELAXED_DOT_ADD :
RELAXED_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs, V128:$acc),
(outs), (ins),
- [(set (v4i32 V128:$dst), (int_wasm_dot_i8x16_i7x16_add_signed
+ [(set (v4i32 V128:$dst), (int_wasm_relaxed_dot_i8x16_i7x16_add_signed
(v16i8 V128:$lhs), (v16i8 V128:$rhs), (v4i32 V128:$acc)))],
- "i32x4.dot_i8x16_i7x16_add_s\t$dst, $lhs, $rhs, $acc",
- "i32x4.dot_i8x16_i7x16_add_s", 0x113>;
+ "i32x4.relaxed_dot_i8x16_i7x16_add_s\t$dst, $lhs, $rhs, $acc",
+ "i32x4.relaxed_dot_i8x16_i7x16_add_s", 0x113>;
+
+//===----------------------------------------------------------------------===//
+// Relaxed BFloat16 dot product
+//===----------------------------------------------------------------------===//
+
+defm RELAXED_DOT_BFLOAT :
+ RELAXED_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs, V128:$acc),
+ (outs), (ins),
+ [(set (v4f32 V128:$dst), (int_wasm_relaxed_dot_bf16x8_add_f32
+ (v8i16 V128:$lhs), (v8i16 V128:$rhs), (v4f32 V128:$acc)))],
+ "f32x4.relaxed_dot_bf16x8_add_f32\t$dst, $lhs, $rhs, $acc",
+ "f32x4.relaxed_dot_bf16x8_add_f32", 0x114>;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
index 1fd00bf1cbc8..069ce5e3bc94 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
@@ -24,7 +24,7 @@ multiclass TABLE<WebAssemblyRegClass rc, string suffix> {
let mayLoad = 1 in
defm TABLE_GET_#rc : I<(outs rc:$res), (ins table32_op:$table, I32:$i),
(outs), (ins table32_op:$table),
- [],
+ [(set rc:$res, (!cast<Intrinsic>("int_wasm_table_get_" # suffix) (WebAssemblyWrapper tglobaladdr:$table), I32:$i))],
"table.get\t$res, $table, $i",
"table.get\t$table",
0x25>;
@@ -32,7 +32,7 @@ multiclass TABLE<WebAssemblyRegClass rc, string suffix> {
let mayStore = 1 in
defm TABLE_SET_#rc : I<(outs), (ins table32_op:$table, I32:$i, rc:$val),
(outs), (ins table32_op:$table),
- [],
+ [(!cast<Intrinsic>("int_wasm_table_set_" # suffix) (WebAssemblyWrapper tglobaladdr:$table), I32:$i, rc:$val)],
"table.set\t$table, $i, $val",
"table.set\t$table",
0x26>;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index 7a1a769c6b16..5faa098b94ad 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -545,15 +545,13 @@ Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallBase *CI) {
ArgAttributes.push_back(InvokeAL.getParamAttrs(I));
AttrBuilder FnAttrs(CI->getContext(), InvokeAL.getFnAttrs());
- if (FnAttrs.contains(Attribute::AllocSize)) {
+ if (auto Args = FnAttrs.getAllocSizeArgs()) {
// The allocsize attribute (if any) referes to parameters by index and needs
// to be adjusted.
- unsigned SizeArg;
- Optional<unsigned> NEltArg;
- std::tie(SizeArg, NEltArg) = FnAttrs.getAllocSizeArgs();
+ auto [SizeArg, NEltArg] = *Args;
SizeArg += 1;
if (NEltArg)
- NEltArg = NEltArg.value() + 1;
+ NEltArg = *NEltArg + 1;
FnAttrs.addAllocSizeAttr(SizeArg, NEltArg);
}
// In case the callee has 'noreturn' attribute, We need to remove it, because
@@ -775,7 +773,7 @@ void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp(
// Output parameter assignment
Label = LabelPHI;
EndBB = EndBB1;
- LongjmpResult = IRB.CreateCall(GetTempRet0F, None, "longjmp_result");
+ LongjmpResult = IRB.CreateCall(GetTempRet0F, std::nullopt, "longjmp_result");
}
void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &F) {
@@ -1227,9 +1225,9 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &F) {
// Create a call to __cxa_find_matching_catch_N function
Function *FMCF = getFindMatchingCatch(M, FMCArgs.size());
CallInst *FMCI = IRB.CreateCall(FMCF, FMCArgs, "fmc");
- Value *Undef = UndefValue::get(LPI->getType());
- Value *Pair0 = IRB.CreateInsertValue(Undef, FMCI, 0, "pair0");
- Value *TempRet0 = IRB.CreateCall(GetTempRet0F, None, "tempret0");
+ Value *Poison = PoisonValue::get(LPI->getType());
+ Value *Pair0 = IRB.CreateInsertValue(Poison, FMCI, 0, "pair0");
+ Value *TempRet0 = IRB.CreateCall(GetTempRet0F, std::nullopt, "tempret0");
Value *Pair1 = IRB.CreateInsertValue(Pair0, TempRet0, 1, "pair1");
LPI->replaceAllUsesWith(Pair1);
@@ -1290,9 +1288,11 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) {
"setjmpTableSize", Entry->getTerminator());
SetjmpTableSize->setDebugLoc(FirstDL);
// setjmpTable = (int *) malloc(40);
- Instruction *SetjmpTable = CallInst::CreateMalloc(
- SetjmpTableSize, IRB.getInt32Ty(), IRB.getInt32Ty(), IRB.getInt32(40),
- nullptr, nullptr, "setjmpTable");
+ Type *IntPtrTy = getAddrIntType(&M);
+ Constant *size = ConstantInt::get(IntPtrTy, 40);
+ Instruction *SetjmpTable =
+ CallInst::CreateMalloc(SetjmpTableSize, IntPtrTy, IRB.getInt32Ty(), size,
+ nullptr, nullptr, "setjmpTable");
SetjmpTable->setDebugLoc(FirstDL);
// CallInst::CreateMalloc may return a bitcast instruction if the result types
// mismatch. We need to set the debug loc for the original call too.
@@ -1355,7 +1355,7 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) {
Instruction *NewSetjmpTable =
IRB.CreateCall(SaveSetjmpF, Args, "setjmpTable");
Instruction *NewSetjmpTableSize =
- IRB.CreateCall(GetTempRet0F, None, "setjmpTableSize");
+ IRB.CreateCall(GetTempRet0F, std::nullopt, "setjmpTableSize");
SetjmpTableInsts.push_back(NewSetjmpTable);
SetjmpTableSizeInsts.push_back(NewSetjmpTableSize);
ToErase.push_back(CI);
@@ -1630,7 +1630,7 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForEmscriptenSjLj(
// Create switch instruction
IRB.SetInsertPoint(EndBB);
- IRB.SetCurrentDebugLocation(EndBB->getInstList().back().getDebugLoc());
+ IRB.SetCurrentDebugLocation(EndBB->back().getDebugLoc());
SwitchInst *SI = IRB.CreateSwitch(Label, Tail, SetjmpRetPHIs.size());
// -1 means no longjmp happened, continue normally (will hit the default
// switch case). 0 means a longjmp that is not ours to handle, needs a
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
index e8b3542df12f..85ece58f98b3 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -194,7 +194,7 @@ void WebAssemblyMCInstLower::lower(const MachineInstr *MI,
case MachineOperand::MO_Immediate: {
unsigned DescIndex = I - NumVariadicDefs;
if (DescIndex < Desc.NumOperands) {
- const MCOperandInfo &Info = Desc.OpInfo[DescIndex];
+ const MCOperandInfo &Info = Desc.operands()[DescIndex];
if (Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
SmallVector<wasm::ValType, 4> Returns;
SmallVector<wasm::ValType, 4> Params;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp
index 96284687971c..7207fbeb305a 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp
@@ -28,10 +28,9 @@ MachineFunctionInfo *WebAssemblyFunctionInfo::clone(
BumpPtrAllocator &Allocator, MachineFunction &DestMF,
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
const {
- WebAssemblyFunctionInfo *Clone =
- DestMF.cloneInfo<WebAssemblyFunctionInfo>(*this);
- Clone->MF = &DestMF;
- return Clone;
+ // TODO: Implement cloning for WasmEHFuncInfo. This will have invalid block
+ // references.
+ return DestMF.cloneInfo<WebAssemblyFunctionInfo>(*this);
}
void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
@@ -122,11 +121,8 @@ llvm::signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
}
yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
- const llvm::WebAssemblyFunctionInfo &MFI)
+ const llvm::MachineFunction &MF, const llvm::WebAssemblyFunctionInfo &MFI)
: CFGStackified(MFI.isCFGStackified()) {
- auto *EHInfo = MFI.getWasmEHFuncInfo();
- const llvm::MachineFunction &MF = MFI.getMachineFunction();
-
for (auto VT : MFI.getParams())
Params.push_back(EVT(VT).getEVTString());
for (auto VT : MFI.getResults())
@@ -134,7 +130,8 @@ yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
// MFI.getWasmEHFuncInfo() is non-null only for functions with the
// personality function.
- if (EHInfo) {
+
+ if (auto *EHInfo = MF.getWasmEHFuncInfo()) {
// SrcToUnwindDest can contain stale mappings in case BBs are removed in
// optimizations, in case, for example, they are unreachable. We should not
// include their info.
@@ -155,15 +152,19 @@ void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
}
void WebAssemblyFunctionInfo::initializeBaseYamlFields(
- const yaml::WebAssemblyFunctionInfo &YamlMFI) {
+ MachineFunction &MF, const yaml::WebAssemblyFunctionInfo &YamlMFI) {
CFGStackified = YamlMFI.CFGStackified;
for (auto VT : YamlMFI.Params)
addParam(WebAssembly::parseMVT(VT.Value));
for (auto VT : YamlMFI.Results)
addResult(WebAssembly::parseMVT(VT.Value));
- if (WasmEHInfo) {
+
+ // FIXME: WasmEHInfo is defined in the MachineFunction, but serialized
+ // here. Either WasmEHInfo should be moved out of MachineFunction, or the
+ // serialization handling should be moved to MachineFunction.
+ if (WasmEHFuncInfo *WasmEHInfo = MF.getWasmEHFuncInfo()) {
for (auto KV : YamlMFI.SrcToUnwindDest)
- WasmEHInfo->setUnwindDest(MF->getBlockNumbered(KV.first),
- MF->getBlockNumbered(KV.second));
+ WasmEHInfo->setUnwindDest(MF.getBlockNumbered(KV.first),
+ MF.getBlockNumbered(KV.second));
}
}
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
index 619617049bb2..7622164449a5 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
@@ -31,8 +31,6 @@ struct WebAssemblyFunctionInfo;
/// This class is derived from MachineFunctionInfo and contains private
/// WebAssembly-specific information for each MachineFunction.
class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
- const MachineFunction *MF;
-
std::vector<MVT> Params;
std::vector<MVT> Results;
std::vector<MVT> Locals;
@@ -66,12 +64,9 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
// Function properties.
bool CFGStackified = false;
- // Catchpad unwind destination info for wasm EH.
- WasmEHFuncInfo *WasmEHInfo = nullptr;
-
public:
- explicit WebAssemblyFunctionInfo(MachineFunction &MF_)
- : MF(&MF_), WasmEHInfo(MF_.getWasmEHFuncInfo()) {}
+ explicit WebAssemblyFunctionInfo(const Function &F,
+ const TargetSubtargetInfo *STI) {}
~WebAssemblyFunctionInfo() override;
MachineFunctionInfo *
@@ -79,9 +74,8 @@ public:
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
const override;
- const MachineFunction &getMachineFunction() const { return *MF; }
-
- void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI);
+ void initializeBaseYamlFields(MachineFunction &MF,
+ const yaml::WebAssemblyFunctionInfo &YamlMFI);
void addParam(MVT VT) { Params.push_back(VT); }
const std::vector<MVT> &getParams() const { return Params; }
@@ -166,9 +160,6 @@ public:
bool isCFGStackified() const { return CFGStackified; }
void setCFGStackified(bool Value = true) { CFGStackified = Value; }
-
- WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; }
- void setWasmEHFuncInfo(WasmEHFuncInfo *Info) { WasmEHInfo = Info; }
};
void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
@@ -205,7 +196,8 @@ struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo {
BBNumberMap SrcToUnwindDest;
WebAssemblyFunctionInfo() = default;
- WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI);
+ WebAssemblyFunctionInfo(const llvm::MachineFunction &MF,
+ const llvm::WebAssemblyFunctionInfo &MFI);
void mappingImpl(yaml::IO &YamlIO) override;
~WebAssemblyFunctionInfo() = default;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
index f9ef45bfb41c..4b24f7fdb118 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
@@ -336,12 +336,17 @@ static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use,
// instruction in which the current value is used, we cannot
// stackify. Stackifying in this case would require that def moving below the
// current def in the stack, which cannot be achieved, even with locals.
+ // Also ensure we don't sink the def past any other prior uses.
for (const auto &SubsequentDef : drop_begin(DefI->defs())) {
- for (const auto &PriorUse : UseI->uses()) {
- if (&PriorUse == Use)
- break;
- if (PriorUse.isReg() && SubsequentDef.getReg() == PriorUse.getReg())
- return false;
+ auto I = std::next(MachineBasicBlock::const_iterator(DefI));
+ auto E = std::next(MachineBasicBlock::const_iterator(UseI));
+ for (; I != E; ++I) {
+ for (const auto &PriorUse : I->uses()) {
+ if (&PriorUse == Use)
+ break;
+ if (PriorUse.isReg() && SubsequentDef.getReg() == PriorUse.getReg())
+ return false;
+ }
}
}
@@ -370,7 +375,7 @@ static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use,
!Insert->readsRegister(Reg))
continue;
- if (Register::isPhysicalRegister(Reg)) {
+ if (Reg.isPhysical()) {
// Ignore ARGUMENTS; it's just used to keep the ARGUMENT_* instructions
// from moving down, and we've already checked for that.
if (Reg == WebAssembly::ARGUMENTS)
@@ -466,8 +471,7 @@ static bool oneUseDominatesOtherUses(unsigned Reg, const MachineOperand &OneUse,
if (!MO.isReg())
return false;
Register DefReg = MO.getReg();
- if (!Register::isVirtualRegister(DefReg) ||
- !MFI.isVRegStackified(DefReg))
+ if (!DefReg.isVirtual() || !MFI.isVRegStackified(DefReg))
return false;
assert(MRI.hasOneNonDBGUse(DefReg));
const MachineOperand &NewUse = *MRI.use_nodbg_begin(DefReg);
@@ -842,7 +846,7 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
assert(Use.isUse() && "explicit_uses() should only iterate over uses");
assert(!Use.isImplicit() &&
"explicit_uses() should only iterate over explicit operands");
- if (Register::isPhysicalRegister(Reg))
+ if (Reg.isPhysical())
continue;
// Identify the definition for this register at this point.
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
index 6b6394a58339..4ca262e248f7 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
@@ -50,7 +50,7 @@ WebAssemblyRegisterInfo::getReservedRegs(const MachineFunction & /*MF*/) const {
return Reserved;
}
-void WebAssemblyRegisterInfo::eliminateFrameIndex(
+bool WebAssemblyRegisterInfo::eliminateFrameIndex(
MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum,
RegScavenger * /*RS*/) const {
assert(SPAdj == 0);
@@ -82,7 +82,7 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
MI.getOperand(OffsetOperandNum).setImm(Offset);
MI.getOperand(FIOperandNum)
.ChangeToRegister(FrameRegister, /*isDef=*/false);
- return;
+ return false;
}
}
@@ -92,7 +92,7 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
MachineOperand &OtherMO = MI.getOperand(3 - FIOperandNum);
if (OtherMO.isReg()) {
Register OtherMOReg = OtherMO.getReg();
- if (Register::isVirtualRegister(OtherMOReg)) {
+ if (OtherMOReg.isVirtual()) {
MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(OtherMOReg);
// TODO: For now we just opportunistically do this in the case where
// the CONST_I32/64 happens to have exactly one def and one use. We
@@ -105,7 +105,7 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset));
MI.getOperand(FIOperandNum)
.ChangeToRegister(FrameRegister, /*isDef=*/false);
- return;
+ return false;
}
}
}
@@ -133,6 +133,7 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
.addReg(OffsetOp);
}
MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*isDef=*/false);
+ return false;
}
Register
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
index 7880eb217dbf..d875e4b93603 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
@@ -34,7 +34,7 @@ public:
// Code Generation virtual methods.
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
BitVector getReservedRegs(const MachineFunction &MF) const override;
- void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
+ bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
index 0b3e534315d5..4fe339ce5293 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
@@ -71,6 +71,7 @@ enum RuntimeLibcallSignature {
i64_i64_func_i64_i64_i64_i64_iPTR,
i64_i64_i64_i64_func_i64_i64_i64_i64,
i64_i64_func_i64_i64_i32,
+ iPTR_func_i32,
iPTR_func_iPTR_i32_iPTR,
iPTR_func_iPTR_iPTR_iPTR,
f32_func_f32_f32_f32,
@@ -329,7 +330,7 @@ struct RuntimeLibcallSignatureTable {
Table[RTLIB::STACKPROTECTOR_CHECK_FAIL] = func;
// Return address handling
- Table[RTLIB::RETURN_ADDRESS] = i32_func_i32;
+ Table[RTLIB::RETURN_ADDRESS] = iPTR_func_i32;
// Element-wise Atomic memory
// TODO: Fix these when we implement atomic support
@@ -785,6 +786,10 @@ void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget,
Params.push_back(wasm::ValType::I64);
Params.push_back(wasm::ValType::I32);
break;
+ case iPTR_func_i32:
+ Rets.push_back(PtrTy);
+ Params.push_back(wasm::ValType::I32);
+ break;
case iPTR_func_iPTR_i32_iPTR:
Rets.push_back(PtrTy);
Params.push_back(PtrTy);
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp
index 89ae45722e42..a453e7388e27 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp
@@ -62,7 +62,7 @@ static void rewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
assert((*MI.memoperands_begin())->getSize() ==
(UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
"Default p2align value should be natural");
- assert(MI.getDesc().OpInfo[OperandNo].OperandType ==
+ assert(MI.getDesc().operands()[OperandNo].OperandType ==
WebAssembly::OPERAND_P2ALIGN &&
"Load and store instructions should have a p2align operand");
uint64_t P2Align = Log2((*MI.memoperands_begin())->getAlign());
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 76f036358ae8..630c786a3dc7 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -32,6 +32,7 @@
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/LowerAtomicPass.h"
#include "llvm/Transforms/Utils.h"
+#include <optional>
using namespace llvm;
#define DEBUG_TYPE "wasm"
@@ -79,13 +80,16 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget() {
initializeWebAssemblyDebugFixupPass(PR);
initializeWebAssemblyPeepholePass(PR);
initializeWebAssemblyMCLowerPrePassPass(PR);
+ initializeWebAssemblyLowerRefTypesIntPtrConvPass(PR);
+ initializeWebAssemblyFixBrTableDefaultsPass(PR);
+ initializeWebAssemblyDAGToDAGISelPass(PR);
}
//===----------------------------------------------------------------------===//
// WebAssembly Lowering public interface.
//===----------------------------------------------------------------------===//
-static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM,
+static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM,
const Triple &TT) {
if (!RM) {
// Default to static relocation model. This should always be more optimial
@@ -108,8 +112,8 @@ static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM,
///
WebAssemblyTargetMachine::WebAssemblyTargetMachine(
const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
- const TargetOptions &Options, Optional<Reloc::Model> RM,
- Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
+ const TargetOptions &Options, std::optional<Reloc::Model> RM,
+ std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
: LLVMTargetMachine(
T,
TT.isArch64Bit()
@@ -323,6 +327,7 @@ public:
void addIRPasses() override;
void addISelPrepare() override;
bool addInstSelector() override;
+ void addOptimizedRegAlloc() override;
void addPostRegAlloc() override;
bool addGCPasses() override { return false; }
void addPreEmitPass() override;
@@ -336,6 +341,13 @@ public:
};
} // end anonymous namespace
+MachineFunctionInfo *WebAssemblyTargetMachine::createMachineFunctionInfo(
+ BumpPtrAllocator &Allocator, const Function &F,
+ const TargetSubtargetInfo *STI) const {
+ return WebAssemblyFunctionInfo::create<WebAssemblyFunctionInfo>(Allocator, F,
+ STI);
+}
+
TargetTransformInfo
WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) const {
return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
@@ -412,7 +424,7 @@ void WebAssemblyPassConfig::addIRPasses() {
// Add signatures to prototype-less function declarations
addPass(createWebAssemblyAddMissingPrototypes());
- // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls.
+ // Lower .llvm.global_dtors into .llvm.global_ctors with __cxa_atexit calls.
addPass(createLowerGlobalDtorsLegacyPass());
// Fix function bitcasts, as WebAssembly requires caller and callee signatures
@@ -480,18 +492,31 @@ bool WebAssemblyPassConfig::addInstSelector() {
return false;
}
+void WebAssemblyPassConfig::addOptimizedRegAlloc() {
+ // Currently RegisterCoalesce degrades wasm debug info quality by a
+ // significant margin. As a quick fix, disable this for -O1, which is often
+ // used for debugging large applications. Disabling this increases code size
+ // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which is
+ // usually not used for production builds.
+ // TODO Investigate why RegisterCoalesce degrades debug info quality and fix
+ // it properly
+ if (getOptLevel() == CodeGenOpt::Less)
+ disablePass(&RegisterCoalescerID);
+ TargetPassConfig::addOptimizedRegAlloc();
+}
+
void WebAssemblyPassConfig::addPostRegAlloc() {
// TODO: The following CodeGen passes don't currently support code containing
// virtual registers. Consider removing their restrictions and re-enabling
// them.
// These functions all require the NoVRegs property.
+ disablePass(&MachineLateInstrsCleanupID);
disablePass(&MachineCopyPropagationID);
disablePass(&PostRAMachineSinkingID);
disablePass(&PostRASchedulerID);
disablePass(&FuncletLayoutID);
disablePass(&StackMapLivenessID);
- disablePass(&LiveDebugValuesID);
disablePass(&PatchableFunctionID);
disablePass(&ShrinkWrapID);
@@ -585,7 +610,7 @@ WebAssemblyTargetMachine::createDefaultFuncInfoYAML() const {
yaml::MachineFunctionInfo *WebAssemblyTargetMachine::convertFuncInfoToYAML(
const MachineFunction &MF) const {
const auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
- return new yaml::WebAssemblyFunctionInfo(*MFI);
+ return new yaml::WebAssemblyFunctionInfo(MF, *MFI);
}
bool WebAssemblyTargetMachine::parseMachineFunctionInfo(
@@ -593,6 +618,6 @@ bool WebAssemblyTargetMachine::parseMachineFunctionInfo(
SMDiagnostic &Error, SMRange &SourceRange) const {
const auto &YamlMFI = static_cast<const yaml::WebAssemblyFunctionInfo &>(MFI);
MachineFunction &MF = PFS.MF;
- MF.getInfo<WebAssemblyFunctionInfo>()->initializeBaseYamlFields(YamlMFI);
+ MF.getInfo<WebAssemblyFunctionInfo>()->initializeBaseYamlFields(MF, YamlMFI);
return false;
}
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
index 5d5378f76567..04bf2de81fe6 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
@@ -17,6 +17,7 @@
#include "WebAssemblySubtarget.h"
#include "llvm/Target/TargetMachine.h"
+#include <optional>
namespace llvm {
@@ -27,9 +28,9 @@ class WebAssemblyTargetMachine final : public LLVMTargetMachine {
public:
WebAssemblyTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
- Optional<Reloc::Model> RM,
- Optional<CodeModel::Model> CM, CodeGenOpt::Level OL,
- bool JIT);
+ std::optional<Reloc::Model> RM,
+ std::optional<CodeModel::Model> CM,
+ CodeGenOpt::Level OL, bool JIT);
~WebAssemblyTargetMachine() override;
@@ -46,6 +47,10 @@ public:
return TLOF.get();
}
+ MachineFunctionInfo *
+ createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
+ const TargetSubtargetInfo *STI) const override;
+
TargetTransformInfo getTargetTransformInfo(const Function &F) const override;
bool usesPhysRegsForValues() const override { return false; }
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
index 62f7155e794a..9a434d9b1db5 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
@@ -52,14 +52,13 @@ TypeSize WebAssemblyTTIImpl::getRegisterBitWidth(
InstructionCost WebAssemblyTTIImpl::getArithmeticInstrCost(
unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
- TTI::OperandValueKind Opd1Info, TTI::OperandValueKind Opd2Info,
- TTI::OperandValueProperties Opd1PropInfo,
- TTI::OperandValueProperties Opd2PropInfo, ArrayRef<const Value *> Args,
+ TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info,
+ ArrayRef<const Value *> Args,
const Instruction *CxtI) {
InstructionCost Cost =
BasicTTIImplBase<WebAssemblyTTIImpl>::getArithmeticInstrCost(
- Opcode, Ty, CostKind, Opd1Info, Opd2Info, Opd1PropInfo, Opd2PropInfo);
+ Opcode, Ty, CostKind, Op1Info, Op2Info);
if (auto *VTy = dyn_cast<VectorType>(Ty)) {
switch (Opcode) {
@@ -68,9 +67,8 @@ InstructionCost WebAssemblyTTIImpl::getArithmeticInstrCost(
case Instruction::Shl:
// SIMD128's shifts currently only accept a scalar shift count. For each
// element, we'll need to extract, op, insert. The following is a rough
- // approxmation.
- if (Opd2Info != TTI::OK_UniformValue &&
- Opd2Info != TTI::OK_UniformConstantValue)
+ // approximation.
+ if (!Op2Info.isUniform())
Cost =
cast<FixedVectorType>(VTy)->getNumElements() *
(TargetTransformInfo::TCC_Basic +
@@ -82,11 +80,12 @@ InstructionCost WebAssemblyTTIImpl::getArithmeticInstrCost(
return Cost;
}
-InstructionCost WebAssemblyTTIImpl::getVectorInstrCost(unsigned Opcode,
- Type *Val,
- unsigned Index) {
- InstructionCost Cost =
- BasicTTIImplBase::getVectorInstrCost(Opcode, Val, Index);
+InstructionCost
+WebAssemblyTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val,
+ TTI::TargetCostKind CostKind,
+ unsigned Index, Value *Op0, Value *Op1) {
+ InstructionCost Cost = BasicTTIImplBase::getVectorInstrCost(
+ Opcode, Val, CostKind, Index, Op0, Op1);
// SIMD128's insert/extract currently only take constant indices.
if (Index == -1u)
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h
index fde58a9587b6..a803fe5c1bbe 100644
--- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h
+++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h
@@ -61,14 +61,14 @@ public:
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const;
InstructionCost getArithmeticInstrCost(
unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
- TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue,
- TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue,
- TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None,
- TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None,
+ TTI::OperandValueInfo Op1Info = {TTI::OK_AnyValue, TTI::OP_None},
+ TTI::OperandValueInfo Op2Info = {TTI::OK_AnyValue, TTI::OP_None},
ArrayRef<const Value *> Args = ArrayRef<const Value *>(),
const Instruction *CxtI = nullptr);
+ using BaseT::getVectorInstrCost;
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val,
- unsigned Index);
+ TTI::TargetCostKind CostKind,
+ unsigned Index, Value *Op0, Value *Op1);
/// @}