1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[WebAssembly] Replace all calls with generalized multivalue calls

Summary:
Extends the multivalue call infrastructure to tail calls, removes all
legacy calls specialized for particular result types, and removes the
CallIndirectFixup pass, since all indirect call arguments are now
fixed up directly in the post-insertion hook.

In order to keep supporting pretty-printed defs and uses in test
expectations, MCInstLower now inserts an immediate containing the
number of defs for each call and call_indirect. The InstPrinter is
updated to query this immediate if it is present and determine which
MCOperands are defs and uses accordingly.

Depends on D72902.

Reviewers: aheejin

Subscribers: dschuff, mgorny, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D74192
This commit is contained in:
Thomas Lively 2020-02-06 16:29:59 -08:00
parent df2d55c040
commit bd828c852a
50 changed files with 273 additions and 652 deletions

View File

@ -16,7 +16,6 @@ add_llvm_target(WebAssemblyCodeGen
WebAssemblyAddMissingPrototypes.cpp
WebAssemblyArgumentMove.cpp
WebAssemblyAsmPrinter.cpp
WebAssemblyCallIndirectFixup.cpp
WebAssemblyCFGStackify.cpp
WebAssemblyCFGSort.cpp
WebAssemblyDebugValueManager.cpp

View File

@ -54,17 +54,28 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
// Print any additional variadic operands.
const MCInstrDesc &Desc = MII.get(MI->getOpcode());
if (Desc.isVariadic()) {
if (Desc.getNumOperands() == 0 && MI->getNumOperands() > 0)
if ((Desc.getNumOperands() == 0 && MI->getNumOperands() > 0) ||
Desc.variadicOpsAreDefs())
OS << "\t";
for (auto I = Desc.getNumOperands(), E = MI->getNumOperands(); I < E; ++I) {
// FIXME: For CALL_INDIRECT_VOID, don't print a leading comma, because
// we have an extra flags operand which is not currently printed, for
// compatiblity reasons.
if (I != 0 && ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
I != Desc.getNumOperands()))
unsigned Start = Desc.getNumOperands();
unsigned NumVariadicDefs = 0;
if (Desc.variadicOpsAreDefs()) {
// The number of variadic defs is encoded in an immediate by MCInstLower
NumVariadicDefs = MI->getOperand(0).getImm();
Start = 1;
}
bool NeedsComma = Desc.getNumOperands() > 0 && !Desc.variadicOpsAreDefs();
for (auto I = Start, E = MI->getNumOperands(); I < E; ++I) {
if (MI->getOpcode() == WebAssembly::CALL_INDIRECT &&
I - Start == NumVariadicDefs) {
// Skip type and flags arguments when printing for tests
++I;
continue;
}
if (NeedsComma)
OS << ", ";
printOperand(MI, I, OS);
printOperand(MI, I, OS, I - Start < NumVariadicDefs);
NeedsComma = true;
}
}
@ -207,20 +218,21 @@ static std::string toString(const APFloat &FP) {
}
void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
raw_ostream &O, bool IsVariadicDef) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
const MCInstrDesc &Desc = MII.get(MI->getOpcode());
unsigned WAReg = Op.getReg();
if (int(WAReg) >= 0)
printRegName(O, WAReg);
else if (OpNo >= MII.get(MI->getOpcode()).getNumDefs())
else if (OpNo >= Desc.getNumDefs() && !IsVariadicDef)
O << "$pop" << WebAssemblyFunctionInfo::getWARegStackId(WAReg);
else if (WAReg != WebAssemblyFunctionInfo::UnusedReg)
O << "$push" << WebAssemblyFunctionInfo::getWARegStackId(WAReg);
else
O << "$drop";
// Add a '=' suffix if this is a def.
if (OpNo < MII.get(MI->getOpcode()).getNumDefs())
if (OpNo < MII.get(MI->getOpcode()).getNumDefs() || IsVariadicDef)
O << '=';
} else if (Op.isImm()) {
O << Op.getImm();

View File

@ -41,7 +41,8 @@ public:
const MCSubtargetInfo &STI, raw_ostream &OS) override;
// Used by tblegen code.
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
bool IsVariadicDef = false);
void printBrList(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O);

View File

@ -441,30 +441,6 @@ inline bool isTee(unsigned Opc) {
inline bool isCallDirect(unsigned Opc) {
switch (Opc) {
case WebAssembly::CALL_VOID:
case WebAssembly::CALL_VOID_S:
case WebAssembly::CALL_i32:
case WebAssembly::CALL_i32_S:
case WebAssembly::CALL_i64:
case WebAssembly::CALL_i64_S:
case WebAssembly::CALL_f32:
case WebAssembly::CALL_f32_S:
case WebAssembly::CALL_f64:
case WebAssembly::CALL_f64_S:
case WebAssembly::CALL_v16i8:
case WebAssembly::CALL_v16i8_S:
case WebAssembly::CALL_v8i16:
case WebAssembly::CALL_v8i16_S:
case WebAssembly::CALL_v4i32:
case WebAssembly::CALL_v4i32_S:
case WebAssembly::CALL_v2i64:
case WebAssembly::CALL_v2i64_S:
case WebAssembly::CALL_v4f32:
case WebAssembly::CALL_v4f32_S:
case WebAssembly::CALL_v2f64:
case WebAssembly::CALL_v2f64_S:
case WebAssembly::CALL_exnref:
case WebAssembly::CALL_exnref_S:
case WebAssembly::CALL:
case WebAssembly::CALL_S:
case WebAssembly::RET_CALL:
@ -477,30 +453,6 @@ inline bool isCallDirect(unsigned Opc) {
inline bool isCallIndirect(unsigned Opc) {
switch (Opc) {
case WebAssembly::CALL_INDIRECT_VOID:
case WebAssembly::CALL_INDIRECT_VOID_S:
case WebAssembly::CALL_INDIRECT_i32:
case WebAssembly::CALL_INDIRECT_i32_S:
case WebAssembly::CALL_INDIRECT_i64:
case WebAssembly::CALL_INDIRECT_i64_S:
case WebAssembly::CALL_INDIRECT_f32:
case WebAssembly::CALL_INDIRECT_f32_S:
case WebAssembly::CALL_INDIRECT_f64:
case WebAssembly::CALL_INDIRECT_f64_S:
case WebAssembly::CALL_INDIRECT_v16i8:
case WebAssembly::CALL_INDIRECT_v16i8_S:
case WebAssembly::CALL_INDIRECT_v8i16:
case WebAssembly::CALL_INDIRECT_v8i16_S:
case WebAssembly::CALL_INDIRECT_v4i32:
case WebAssembly::CALL_INDIRECT_v4i32_S:
case WebAssembly::CALL_INDIRECT_v2i64:
case WebAssembly::CALL_INDIRECT_v2i64_S:
case WebAssembly::CALL_INDIRECT_v4f32:
case WebAssembly::CALL_INDIRECT_v4f32_S:
case WebAssembly::CALL_INDIRECT_v2f64:
case WebAssembly::CALL_INDIRECT_v2f64_S:
case WebAssembly::CALL_INDIRECT_exnref:
case WebAssembly::CALL_INDIRECT_exnref_S:
case WebAssembly::CALL_INDIRECT:
case WebAssembly::CALL_INDIRECT_S:
case WebAssembly::RET_CALL_INDIRECT:

View File

@ -52,7 +52,6 @@ FunctionPass *createWebAssemblyExplicitLocals();
FunctionPass *createWebAssemblyLowerBrUnless();
FunctionPass *createWebAssemblyRegNumbering();
FunctionPass *createWebAssemblyPeephole();
FunctionPass *createWebAssemblyCallIndirectFixup();
// PassRegistry initialization declarations.
void initializeWebAssemblyAddMissingPrototypesPass(PassRegistry &);
@ -77,7 +76,6 @@ void initializeWebAssemblyExplicitLocalsPass(PassRegistry &);
void initializeWebAssemblyLowerBrUnlessPass(PassRegistry &);
void initializeWebAssemblyRegNumberingPass(PassRegistry &);
void initializeWebAssemblyPeepholePass(PassRegistry &);
void initializeWebAssemblyCallIndirectFixupPass(PassRegistry &);
namespace WebAssembly {
enum TargetIndex { TI_LOCAL_START, TI_GLOBAL_START, TI_OPERAND_STACK_START };

View File

@ -1,150 +0,0 @@
//===-- WebAssemblyCallIndirectFixup.cpp - Fix call_indirects -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file converts pseudo call_indirect instructions into real
/// call_indirects.
///
/// The order of arguments for a call_indirect is the arguments to the function
/// call, followed by the function pointer. There's no natural way to express
/// a machineinstr with varargs followed by one more arg, so we express it as
/// the function pointer followed by varargs, then rewrite it here.
///
/// We need to rewrite the order of the arguments on the machineinstrs
/// themselves so that register stackification knows the order they'll be
/// executed in.
///
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" // for WebAssembly::ARGUMENT_*
#include "WebAssembly.h"
#include "WebAssemblyMachineFunctionInfo.h"
#include "WebAssemblySubtarget.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "wasm-call-indirect-fixup"
namespace {
class WebAssemblyCallIndirectFixup final : public MachineFunctionPass {
StringRef getPassName() const override {
return "WebAssembly CallIndirect Fixup";
}
bool runOnMachineFunction(MachineFunction &MF) override;
public:
static char ID; // Pass identification, replacement for typeid
WebAssemblyCallIndirectFixup() : MachineFunctionPass(ID) {}
};
} // end anonymous namespace
char WebAssemblyCallIndirectFixup::ID = 0;
INITIALIZE_PASS(WebAssemblyCallIndirectFixup, DEBUG_TYPE,
"Rewrite call_indirect argument orderings", false, false)
FunctionPass *llvm::createWebAssemblyCallIndirectFixup() {
return new WebAssemblyCallIndirectFixup();
}
static unsigned getNonPseudoCallIndirectOpcode(const MachineInstr &MI) {
switch (MI.getOpcode()) {
using namespace WebAssembly;
case PCALL_INDIRECT_VOID:
return CALL_INDIRECT_VOID;
case PCALL_INDIRECT_i32:
return CALL_INDIRECT_i32;
case PCALL_INDIRECT_i64:
return CALL_INDIRECT_i64;
case PCALL_INDIRECT_f32:
return CALL_INDIRECT_f32;
case PCALL_INDIRECT_f64:
return CALL_INDIRECT_f64;
case PCALL_INDIRECT_v16i8:
return CALL_INDIRECT_v16i8;
case PCALL_INDIRECT_v8i16:
return CALL_INDIRECT_v8i16;
case PCALL_INDIRECT_v4i32:
return CALL_INDIRECT_v4i32;
case PCALL_INDIRECT_v2i64:
return CALL_INDIRECT_v2i64;
case PCALL_INDIRECT_v4f32:
return CALL_INDIRECT_v4f32;
case PCALL_INDIRECT_v2f64:
return CALL_INDIRECT_v2f64;
case PCALL_INDIRECT_exnref:
return CALL_INDIRECT_exnref;
case PRET_CALL_INDIRECT:
return RET_CALL_INDIRECT;
default:
return INSTRUCTION_LIST_END;
}
}
static bool isPseudoCallIndirect(const MachineInstr &MI) {
return getNonPseudoCallIndirectOpcode(MI) !=
WebAssembly::INSTRUCTION_LIST_END;
}
bool WebAssemblyCallIndirectFixup::runOnMachineFunction(MachineFunction &MF) {
LLVM_DEBUG(dbgs() << "********** Fixing up CALL_INDIRECTs **********\n"
<< "********** Function: " << MF.getName() << '\n');
bool Changed = false;
const WebAssemblyInstrInfo *TII =
MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : MBB) {
if (isPseudoCallIndirect(MI)) {
LLVM_DEBUG(dbgs() << "Found call_indirect: " << MI << '\n');
// Rewrite pseudo to non-pseudo
const MCInstrDesc &Desc = TII->get(getNonPseudoCallIndirectOpcode(MI));
MI.setDesc(Desc);
// Rewrite argument order
SmallVector<MachineOperand, 8> Ops;
// Set up a placeholder for the type signature immediate.
Ops.push_back(MachineOperand::CreateImm(0));
// Set up the flags immediate, which currently has no defined flags
// so it's always zero.
Ops.push_back(MachineOperand::CreateImm(0));
for (const MachineOperand &MO :
make_range(MI.operands_begin() + MI.getDesc().getNumDefs() + 1,
MI.operands_begin() + MI.getNumExplicitOperands()))
Ops.push_back(MO);
Ops.push_back(MI.getOperand(MI.getDesc().getNumDefs()));
// Replace the instructions operands.
while (MI.getNumOperands() > MI.getDesc().getNumDefs())
MI.RemoveOperand(MI.getNumOperands() - 1);
for (const MachineOperand &MO : Ops)
MI.addOperand(MO);
LLVM_DEBUG(dbgs() << " After transform: " << MI);
Changed = true;
}
}
}
LLVM_DEBUG(dbgs() << "\nDone fixing up CALL_INDIRECTs\n\n");
return Changed;
}

View File

@ -759,12 +759,10 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
return false;
FunctionType *FuncTy = Call->getFunctionType();
unsigned Opc;
unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
bool IsVoid = FuncTy->getReturnType()->isVoidTy();
unsigned ResultReg;
if (IsVoid) {
Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
} else {
if (!IsVoid) {
if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
return false;
@ -774,54 +772,36 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
case MVT::i8:
case MVT::i16:
case MVT::i32:
Opc = IsDirect ? WebAssembly::CALL_i32 : WebAssembly::PCALL_INDIRECT_i32;
ResultReg = createResultReg(&WebAssembly::I32RegClass);
break;
case MVT::i64:
Opc = IsDirect ? WebAssembly::CALL_i64 : WebAssembly::PCALL_INDIRECT_i64;
ResultReg = createResultReg(&WebAssembly::I64RegClass);
break;
case MVT::f32:
Opc = IsDirect ? WebAssembly::CALL_f32 : WebAssembly::PCALL_INDIRECT_f32;
ResultReg = createResultReg(&WebAssembly::F32RegClass);
break;
case MVT::f64:
Opc = IsDirect ? WebAssembly::CALL_f64 : WebAssembly::PCALL_INDIRECT_f64;
ResultReg = createResultReg(&WebAssembly::F64RegClass);
break;
case MVT::v16i8:
Opc = IsDirect ? WebAssembly::CALL_v16i8
: WebAssembly::PCALL_INDIRECT_v16i8;
ResultReg = createResultReg(&WebAssembly::V128RegClass);
break;
case MVT::v8i16:
Opc = IsDirect ? WebAssembly::CALL_v8i16
: WebAssembly::PCALL_INDIRECT_v8i16;
ResultReg = createResultReg(&WebAssembly::V128RegClass);
break;
case MVT::v4i32:
Opc = IsDirect ? WebAssembly::CALL_v4i32
: WebAssembly::PCALL_INDIRECT_v4i32;
ResultReg = createResultReg(&WebAssembly::V128RegClass);
break;
case MVT::v2i64:
Opc = IsDirect ? WebAssembly::CALL_v2i64
: WebAssembly::PCALL_INDIRECT_v2i64;
ResultReg = createResultReg(&WebAssembly::V128RegClass);
break;
case MVT::v4f32:
Opc = IsDirect ? WebAssembly::CALL_v4f32
: WebAssembly::PCALL_INDIRECT_v4f32;
ResultReg = createResultReg(&WebAssembly::V128RegClass);
break;
case MVT::v2f64:
Opc = IsDirect ? WebAssembly::CALL_v2f64
: WebAssembly::PCALL_INDIRECT_v2f64;
ResultReg = createResultReg(&WebAssembly::V128RegClass);
break;
case MVT::exnref:
Opc = IsDirect ? WebAssembly::CALL_exnref
: WebAssembly::PCALL_INDIRECT_exnref;
ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
break;
default:
@ -871,14 +851,20 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
if (!IsVoid)
MIB.addReg(ResultReg, RegState::Define);
if (IsDirect)
if (IsDirect) {
MIB.addGlobalAddress(Func);
else
MIB.addReg(CalleeReg);
} else {
// Add placeholders for the type index and immediate flags
MIB.addImm(0);
MIB.addImm(0);
}
for (unsigned ArgReg : Args)
MIB.addReg(ArgReg);
if (!IsDirect)
MIB.addReg(CalleeReg);
if (!IsVoid)
updateValueMap(Call, ResultReg);
return true;

View File

@ -13,8 +13,6 @@
// NOTE: NO INCLUDE GUARD DESIRED!
HANDLE_NODETYPE(CALL1)
HANDLE_NODETYPE(CALL0)
HANDLE_NODETYPE(CALL)
HANDLE_NODETYPE(RET_CALL)
HANDLE_NODETYPE(RETURN)

View File

@ -206,7 +206,8 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
}
break;
}
case WebAssemblyISD::CALL: {
case WebAssemblyISD::CALL:
case WebAssemblyISD::RET_CALL: {
// CALL has both variable operands and variable results, but ISel only
// supports one or the other. Split calls into two nodes glued together, one
// for the operands and one for the results. These two nodes will be
@ -214,16 +215,23 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
SmallVector<SDValue, 16> Ops;
for (size_t i = 1; i < Node->getNumOperands(); ++i) {
SDValue Op = Node->getOperand(i);
if (Op->getOpcode() == WebAssemblyISD::Wrapper)
if (i == 1 && Op->getOpcode() == WebAssemblyISD::Wrapper)
Op = Op->getOperand(0);
Ops.push_back(Op);
}
// Add the chain last
Ops.push_back(Node->getOperand(0));
MachineSDNode *CallParams =
CurDAG->getMachineNode(WebAssembly::CALL_PARAMS, DL, MVT::Glue, Ops);
unsigned Results = Node->getOpcode() == WebAssemblyISD::CALL
? WebAssembly::CALL_RESULTS
: WebAssembly::RET_CALL_RESULTS;
SDValue Link(CallParams, 0);
MachineSDNode *CallResults = CurDAG->getMachineNode(
WebAssembly::CALL_RESULTS, DL, Node->getVTList(), Link);
MachineSDNode *CallResults =
CurDAG->getMachineNode(Results, DL, Node->getVTList(), Link);
ReplaceNode(Node, CallResults);
return;
}

View File

@ -416,10 +416,22 @@ static MachineBasicBlock *LowerCallResults(MachineInstr &CallResults,
const TargetInstrInfo &TII) {
MachineInstr &CallParams = *CallResults.getPrevNode();
assert(CallParams.getOpcode() == WebAssembly::CALL_PARAMS);
assert(CallResults.getOpcode() == WebAssembly::CALL_RESULTS);
assert(CallResults.getOpcode() == WebAssembly::CALL_RESULTS ||
CallResults.getOpcode() == WebAssembly::RET_CALL_RESULTS);
bool IsIndirect = CallParams.getOperand(0).isReg();
unsigned CallOp = IsIndirect ? WebAssembly::CALL_INDIRECT : WebAssembly::CALL;
bool IsRetCall = CallResults.getOpcode() == WebAssembly::RET_CALL_RESULTS;
unsigned CallOp;
if (IsIndirect && IsRetCall) {
CallOp = WebAssembly::RET_CALL_INDIRECT;
} else if (IsIndirect) {
CallOp = WebAssembly::CALL_INDIRECT;
} else if (IsRetCall) {
CallOp = WebAssembly::RET_CALL;
} else {
CallOp = WebAssembly::CALL;
}
MachineFunction &MF = *BB->getParent();
const MCInstrDesc &MCID = TII.get(CallOp);
@ -484,6 +496,7 @@ MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
return LowerFPToInt(MI, DL, BB, TII, true, true, true,
WebAssembly::I64_TRUNC_U_F64);
case WebAssembly::CALL_RESULTS:
case WebAssembly::RET_CALL_RESULTS:
return LowerCallResults(MI, DL, BB, TII);
}
}
@ -885,21 +898,8 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
}
InTys.push_back(MVT::Other);
unsigned Opc;
// TODO: Remove CALL0 and CALL1 in favor of CALL
switch (Ins.size()) {
case 0:
Opc = WebAssemblyISD::CALL0;
break;
case 1:
Opc = WebAssemblyISD::CALL1;
break;
default:
Opc = WebAssemblyISD::CALL;
break;
}
SDVTList InTyList = DAG.getVTList(InTys);
SDValue Res = DAG.getNode(Opc, DL, InTyList, Ops);
SDValue Res = DAG.getNode(WebAssemblyISD::CALL, DL, InTyList, Ops);
for (size_t I = 0; I < Ins.size(); ++I)
InVals.push_back(Res.getValue(I));

View File

@ -23,36 +23,8 @@ defm ADJCALLSTACKUP : NRI<(outs), (ins i32imm:$amt, i32imm:$amt2),
[(WebAssemblycallseq_end timm:$amt, timm:$amt2)]>;
} // Uses = [SP32, SP64], Defs = [SP32, SP64], isCodeGenOnly = 1
multiclass CALL<ValueType vt, WebAssemblyRegClass rt, string prefix,
list<Predicate> preds = []> {
defm CALL_#vt :
I<(outs rt:$dst), (ins function32_op:$callee, variable_ops),
(outs), (ins function32_op:$callee),
[(set (vt rt:$dst), (WebAssemblycall1 (i32 imm:$callee)))],
!strconcat(prefix, "call\t$dst, $callee"),
!strconcat(prefix, "call\t$callee"),
0x10>,
Requires<preds>;
let isCodeGenOnly = 1 in
defm PCALL_INDIRECT_#vt :
I<(outs rt:$dst), (ins I32:$callee, variable_ops),
(outs), (ins I32:$callee),
[(set (vt rt:$dst), (WebAssemblycall1 I32:$callee))],
"PSEUDO CALL INDIRECT\t$callee",
"PSEUDO CALL INDIRECT\t$callee">,
Requires<preds>;
defm CALL_INDIRECT_#vt :
I<(outs rt:$dst),
(ins TypeIndex:$type, i32imm:$flags, variable_ops),
(outs), (ins TypeIndex:$type, i32imm:$flags),
[],
!strconcat(prefix, "call_indirect\t$dst"),
!strconcat(prefix, "call_indirect\t$type"),
0x11>,
Requires<preds>;
}
let Uses = [SP32, SP64], isCall = 1 in {
// CALL should take both variadic arguments and produce variadic results, but
// this is not possible to model directly. Instead, we select calls to a
@ -71,14 +43,16 @@ defm CALL_RESULTS :
I<(outs), (ins variable_ops), (outs), (ins), [],
"call_results", "call_results", -1>;
let Uses = [SP32, SP64], isCall = 1 in {
let variadicOpsAreDefs = 1, usesCustomInserter = 1, isPseudo = 1 in
defm RET_CALL_RESULTS :
I<(outs), (ins variable_ops), (outs), (ins), [],
"return_call_results", "return_call_results", -1>;
// TODO: delete CALL_*
let variadicOpsAreDefs = 1 in
defm CALL :
I<(outs), (ins function32_op:$callee, variable_ops),
(outs), (ins function32_op:$callee), [],
"call\t$callee", "call\t$callee", 0x10>;
"call", "call\t$callee", 0x10>;
let variadicOpsAreDefs = 1 in
defm CALL_INDIRECT :
@ -86,124 +60,19 @@ defm CALL_INDIRECT :
(outs), (ins TypeIndex:$type, i32imm:$flags), [],
"call_indirect", "call_indirect\t$type", 0x11>;
defm "" : CALL<i32, I32, "i32.">;
defm "" : CALL<i64, I64, "i64.">;
defm "" : CALL<f32, F32, "f32.">;
defm "" : CALL<f64, F64, "f64.">;
defm "" : CALL<exnref, EXNREF, "exnref.", [HasExceptionHandling]>;
defm "" : CALL<v16i8, V128, "v128.", [HasSIMD128]>;
defm "" : CALL<v8i16, V128, "v128.", [HasSIMD128]>;
defm "" : CALL<v4i32, V128, "v128.", [HasSIMD128]>;
defm "" : CALL<v2i64, V128, "v128.", [HasSIMD128]>;
defm "" : CALL<v4f32, V128, "v128.", [HasSIMD128]>;
defm "" : CALL<v2f64, V128, "v128.", [HasSIMD128]>;
let IsCanonical = 1 in {
defm CALL_VOID :
I<(outs), (ins function32_op:$callee, variable_ops),
(outs), (ins function32_op:$callee),
[(WebAssemblycall0 (i32 imm:$callee))],
"call \t$callee", "call\t$callee", 0x10>;
let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in
defm RET_CALL :
I<(outs), (ins function32_op:$callee, variable_ops),
(outs), (ins function32_op:$callee),
[(WebAssemblyretcall (i32 imm:$callee))],
(outs), (ins function32_op:$callee), [],
"return_call \t$callee", "return_call\t$callee", 0x12>,
Requires<[HasTailCall]>;
let isCodeGenOnly = 1 in
defm PCALL_INDIRECT_VOID :
I<(outs), (ins I32:$callee, variable_ops),
(outs), (ins I32:$callee),
[(WebAssemblycall0 I32:$callee)],
"PSEUDO CALL INDIRECT\t$callee",
"PSEUDO CALL INDIRECT\t$callee">;
defm CALL_INDIRECT_VOID :
I<(outs), (ins TypeIndex:$type, i32imm:$flags, variable_ops),
(outs), (ins TypeIndex:$type, i32imm:$flags),
[],
"call_indirect\t", "call_indirect\t$type",
0x11>;
let isReturn = 1 in
defm RET_CALL_INDIRECT :
I<(outs), (ins TypeIndex:$type, i32imm:$flags, variable_ops),
(outs), (ins TypeIndex:$type, i32imm:$flags),
[],
(outs), (ins TypeIndex:$type, i32imm:$flags), [],
"return_call_indirect\t", "return_call_indirect\t$type",
0x13>,
Requires<[HasTailCall]>;
let isCodeGenOnly = 1, isReturn = 1 in
defm PRET_CALL_INDIRECT:
I<(outs), (ins I32:$callee, variable_ops),
(outs), (ins I32:$callee),
[(WebAssemblyretcall I32:$callee)],
"PSEUDO RET_CALL INDIRECT\t$callee",
"PSEUDO RET_CALL INDIRECT\t$callee">,
Requires<[HasTailCall]>;
} // IsCanonical = 1
} // Uses = [SP32,SP64], isCall = 1
// Patterns for matching a direct call to a global address.
def : Pat<(i32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_i32 tglobaladdr:$callee)>;
def : Pat<(i64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_i64 tglobaladdr:$callee)>;
def : Pat<(f32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_f32 tglobaladdr:$callee)>;
def : Pat<(f64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_f64 tglobaladdr:$callee)>;
def : Pat<(v16i8 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_v16i8 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v8i16 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_v8i16 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_v4i32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v2i64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_v2i64 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_v4f32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v2f64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_v2f64 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
(CALL_exnref tglobaladdr:$callee)>,
Requires<[HasExceptionHandling]>;
def : Pat<(WebAssemblycall0 (WebAssemblywrapper tglobaladdr:$callee)),
(CALL_VOID tglobaladdr:$callee)>;
def : Pat<(WebAssemblyretcall (WebAssemblywrapper tglobaladdr:$callee)),
(RET_CALL tglobaladdr:$callee)>, Requires<[HasTailCall]>;
// Patterns for matching a direct call to an external symbol.
def : Pat<(i32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_i32 texternalsym:$callee)>;
def : Pat<(i64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_i64 texternalsym:$callee)>;
def : Pat<(f32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_f32 texternalsym:$callee)>;
def : Pat<(f64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_f64 texternalsym:$callee)>;
def : Pat<(v16i8 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_v16i8 texternalsym:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v8i16 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_v8i16 texternalsym:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_v4i32 texternalsym:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v2i64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_v2i64 texternalsym:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_v4f32 texternalsym:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(v2f64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_v2f64 texternalsym:$callee)>, Requires<[HasSIMD128]>;
def : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
(CALL_exnref texternalsym:$callee)>,
Requires<[HasExceptionHandling]>;
def : Pat<(WebAssemblycall0 (WebAssemblywrapper texternalsym:$callee)),
(CALL_VOID texternalsym:$callee)>;
def : Pat<(WebAssemblyretcall (WebAssemblywrapper texternalsym:$callee)),
(RET_CALL texternalsym:$callee)>, Requires<[HasTailCall]>;

View File

@ -95,15 +95,6 @@ def WebAssemblycallseq_start :
def WebAssemblycallseq_end :
SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
def WebAssemblycall0 : SDNode<"WebAssemblyISD::CALL0",
SDT_WebAssemblyCall0,
[SDNPHasChain, SDNPVariadic]>;
def WebAssemblycall1 : SDNode<"WebAssemblyISD::CALL1",
SDT_WebAssemblyCall1,
[SDNPHasChain, SDNPVariadic]>;
def WebAssemblyretcall : SDNode<"WebAssemblyISD::RET_CALL",
SDT_WebAssemblyCall0,
[SDNPHasChain, SDNPVariadic]>;
def WebAssemblybr_table : SDNode<"WebAssemblyISD::BR_TABLE",
SDT_WebAssemblyBrTable,
[SDNPHasChain, SDNPVariadic]>;

View File

@ -343,7 +343,7 @@ bool WebAssemblyLateEHPrepare::addExceptionExtraction(MachineFunction &MF) {
"There is no __clang_call_terminate() function");
Register Reg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
BuildMI(ElseMBB, DL, TII.get(WebAssembly::CONST_I32), Reg).addImm(0);
BuildMI(ElseMBB, DL, TII.get(WebAssembly::CALL_VOID))
BuildMI(ElseMBB, DL, TII.get(WebAssembly::CALL))
.addGlobalAddress(ClangCallTerminateFn)
.addReg(Reg);
BuildMI(ElseMBB, DL, TII.get(WebAssembly::UNREACHABLE));

View File

@ -309,6 +309,8 @@ void WebAssemblyMCInstLower::lower(const MachineInstr *MI,
if (!WasmKeepRegisters)
removeRegisterOperands(MI, OutMI);
else if (Desc.variadicOpsAreDefs())
OutMI.insert(OutMI.begin(), MCOperand::createImm(MI->getNumExplicitDefs()));
}
static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI) {

View File

@ -201,8 +201,7 @@ bool WebAssemblyMemIntrinsicResults::runOnMachineFunction(MachineFunction &MF) {
switch (MI.getOpcode()) {
default:
break;
case WebAssembly::CALL_i32:
case WebAssembly::CALL_i64:
case WebAssembly::CALL:
Changed |= optimizeCall(MBB, MI, MRI, MDT, LIS, TLI, LibInfo);
break;
}

View File

@ -149,8 +149,7 @@ bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
switch (MI.getOpcode()) {
default:
break;
case WebAssembly::CALL_i32:
case WebAssembly::CALL_i64: {
case WebAssembly::CALL: {
MachineOperand &Op1 = MI.getOperand(1);
if (Op1.isSymbol()) {
StringRef Name(Op1.getSymbolName());

View File

@ -76,7 +76,6 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget() {
initializeWebAssemblyLowerBrUnlessPass(PR);
initializeWebAssemblyRegNumberingPass(PR);
initializeWebAssemblyPeepholePass(PR);
initializeWebAssemblyCallIndirectFixupPass(PR);
}
//===----------------------------------------------------------------------===//
@ -423,11 +422,6 @@ void WebAssemblyPassConfig::addPostRegAlloc() {
void WebAssemblyPassConfig::addPreEmitPass() {
TargetPassConfig::addPreEmitPass();
// Rewrite pseudo call_indirect instructions as real instructions.
// This needs to run before register stackification, because we change the
// order of the arguments.
addPass(createWebAssemblyCallIndirectFixup());
// Eliminate multiple-entry loops.
addPass(createWebAssemblyFixIrreducibleControlFlow());

View File

@ -82,65 +82,15 @@ bool WebAssembly::mayThrow(const MachineInstr &MI) {
const MachineOperand &WebAssembly::getCalleeOp(const MachineInstr &MI) {
switch (MI.getOpcode()) {
case WebAssembly::CALL_VOID:
case WebAssembly::CALL_VOID_S:
case WebAssembly::CALL_INDIRECT_VOID:
case WebAssembly::CALL_INDIRECT_VOID_S:
case WebAssembly::RET_CALL:
case WebAssembly::RET_CALL_S:
case WebAssembly::RET_CALL_INDIRECT:
case WebAssembly::RET_CALL_INDIRECT_S:
return MI.getOperand(0);
case WebAssembly::CALL_i32:
case WebAssembly::CALL_i32_S:
case WebAssembly::CALL_i64:
case WebAssembly::CALL_i64_S:
case WebAssembly::CALL_f32:
case WebAssembly::CALL_f32_S:
case WebAssembly::CALL_f64:
case WebAssembly::CALL_f64_S:
case WebAssembly::CALL_v16i8:
case WebAssembly::CALL_v16i8_S:
case WebAssembly::CALL_v8i16:
case WebAssembly::CALL_v8i16_S:
case WebAssembly::CALL_v4i32:
case WebAssembly::CALL_v4i32_S:
case WebAssembly::CALL_v2i64:
case WebAssembly::CALL_v2i64_S:
case WebAssembly::CALL_v4f32:
case WebAssembly::CALL_v4f32_S:
case WebAssembly::CALL_v2f64:
case WebAssembly::CALL_v2f64_S:
case WebAssembly::CALL_exnref:
case WebAssembly::CALL_exnref_S:
case WebAssembly::CALL_INDIRECT_i32:
case WebAssembly::CALL_INDIRECT_i32_S:
case WebAssembly::CALL_INDIRECT_i64:
case WebAssembly::CALL_INDIRECT_i64_S:
case WebAssembly::CALL_INDIRECT_f32:
case WebAssembly::CALL_INDIRECT_f32_S:
case WebAssembly::CALL_INDIRECT_f64:
case WebAssembly::CALL_INDIRECT_f64_S:
case WebAssembly::CALL_INDIRECT_v16i8:
case WebAssembly::CALL_INDIRECT_v16i8_S:
case WebAssembly::CALL_INDIRECT_v8i16:
case WebAssembly::CALL_INDIRECT_v8i16_S:
case WebAssembly::CALL_INDIRECT_v4i32:
case WebAssembly::CALL_INDIRECT_v4i32_S:
case WebAssembly::CALL_INDIRECT_v2i64:
case WebAssembly::CALL_INDIRECT_v2i64_S:
case WebAssembly::CALL_INDIRECT_v4f32:
case WebAssembly::CALL_INDIRECT_v4f32_S:
case WebAssembly::CALL_INDIRECT_v2f64:
case WebAssembly::CALL_INDIRECT_v2f64_S:
case WebAssembly::CALL_INDIRECT_exnref:
case WebAssembly::CALL_INDIRECT_exnref_S:
return MI.getOperand(1);
case WebAssembly::CALL:
case WebAssembly::CALL_S:
case WebAssembly::RET_CALL:
case WebAssembly::RET_CALL_S:
return MI.getOperand(MI.getNumExplicitDefs());
case WebAssembly::CALL_INDIRECT:
case WebAssembly::CALL_INDIRECT_S:
case WebAssembly::RET_CALL_INDIRECT:
case WebAssembly::RET_CALL_INDIRECT_S:
return MI.getOperand(MI.getNumOperands() - 1);
default:
llvm_unreachable("Not a call instruction");

View File

@ -31,14 +31,14 @@ body: |
; CHECK: COMPILER_FENCE
; CHECK: ADD_I32
; CHECK: LOCAL_GET_I32 [[LOCAL]]
; CHECK: CALL_VOID @foo
; CHECK: CALL @foo
liveins: $arguments
%0:i32 = CONST_I32 0, implicit-def $arguments
%1:i32 = ATOMIC_NOTIFY 2, 0, %0:i32, %0:i32, implicit-def $arguments
COMPILER_FENCE implicit-def $arguments
%2:i32 = ADD_I32 %0:i32, %0:i32, implicit-def $arguments
CALL_VOID @foo, %2:i32, %1:i32, implicit-def $arguments
CALL @foo, %2:i32, %1:i32, implicit-def $arguments
RETURN implicit-def $arguments
...
@ -55,13 +55,13 @@ body: |
; CHECK: ATOMIC_FENCE
; CHECK: ADD_I32
; CHECK: LOCAL_GET_I32 [[LOCAL]]
; CHECK: CALL_VOID @foo
; CHECK: CALL @foo
liveins: $arguments
%0:i32 = CONST_I32 0, implicit-def $arguments
%1:i32 = ATOMIC_NOTIFY 2, 0, %0:i32, %0:i32, implicit-def $arguments
ATOMIC_FENCE 0, implicit-def $arguments
%2:i32 = ADD_I32 %0:i32, %0:i32, implicit-def $arguments
CALL_VOID @foo, %2:i32, %1:i32, implicit-def $arguments
CALL @foo, %2:i32, %1:i32, implicit-def $arguments
RETURN implicit-def $arguments
...

View File

@ -113,7 +113,7 @@ define void @byval_empty_callee(%EmptyStruct* byval %ptr) {
; CHECK-NEXT: local.tee $push[[L10:.+]]=, $[[SP:.+]]=, $pop[[L11]]{{$}}
; CHECK-NEXT: global.set __stack_pointer, $pop[[L10]]{{$}}
; CHECK-NEXT: i32.const $push[[L0:.+]]=, 131072
; CHECK-NEXT: i32.call $push[[L11:.+]]=, memcpy, $[[SP]], ${{.+}}, $pop{{.+}}
; CHECK-NEXT: call $push[[L11:.+]]=, memcpy, $[[SP]], ${{.+}}, $pop{{.+}}
; CHECK-NEXT: local.tee $push[[L9:.+]]=, $[[SP:.+]]=, $pop[[L11]]{{$}}
; CHECK-NEXT: call big_byval_callee,
%big = type [131072 x i8]

View File

@ -20,7 +20,7 @@ define void @call_indirect_func() {
; CHECK-NEXT: i32.const $push[[L1:[0-9]+]]=, indirect_func@MBREL{{$}}
; CHECK-NEXT: i32.add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}}
; CHECK-NEXT: i32.load $push[[L3:[0-9]+]]=, 0($pop[[L2]]){{$}}
; CHECK-NEXT: i32.call_indirect $push[[L4:[0-9]+]]=, $pop[[L3]]{{$}}
; CHECK-NEXT: call_indirect $push[[L4:[0-9]+]]=, $pop[[L3]]{{$}}
%1 = load i32 ()*, i32 ()** @indirect_func, align 4
%call = call i32 %1()
ret void
@ -29,7 +29,7 @@ define void @call_indirect_func() {
define void @call_direct() {
; CHECK-LABEL: call_direct:
; CHECK: .functype call_direct () -> ()
; CHECK-NEXT: i32.call $push0=, foo{{$}}
; CHECK-NEXT: call $push0=, foo{{$}}
; CHECK-NEXT: drop $pop0{{$}}
; CHECK-NEXT: return{{$}}
%call = call i32 @foo()
@ -39,7 +39,7 @@ define void @call_direct() {
define void @call_alias_func() {
; CHECK-LABEL: call_alias_func:
; CHECK: .functype call_alias_func () -> ()
; CHECK-NEXT: i32.call $push0=, alias_func
; CHECK-NEXT: call $push0=, alias_func
; CHECK-NEXT: drop $pop0{{$}}
; CHECK-NEXT: return{{$}}
%call = call i32 @alias_func()

View File

@ -19,7 +19,7 @@ declare void @void_nullary()
; CHECK-LABEL: call_i32_nullary:
; CHECK-NEXT: .functype call_i32_nullary () -> (i32){{$}}
; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_nullary{{$}}
; CHECK-NEXT: {{^}} call $push[[NUM:[0-9]+]]=, i32_nullary{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i32 @call_i32_nullary() {
%r = call i32 @i32_nullary()
@ -28,7 +28,7 @@ define i32 @call_i32_nullary() {
; CHECK-LABEL: call_i64_nullary:
; CHECK-NEXT: .functype call_i64_nullary () -> (i64){{$}}
; CHECK-NEXT: {{^}} i64.call $push[[NUM:[0-9]+]]=, i64_nullary{{$}}
; CHECK-NEXT: {{^}} call $push[[NUM:[0-9]+]]=, i64_nullary{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i64 @call_i64_nullary() {
%r = call i64 @i64_nullary()
@ -37,7 +37,7 @@ define i64 @call_i64_nullary() {
; CHECK-LABEL: call_float_nullary:
; CHECK-NEXT: .functype call_float_nullary () -> (f32){{$}}
; CHECK-NEXT: {{^}} f32.call $push[[NUM:[0-9]+]]=, float_nullary{{$}}
; CHECK-NEXT: {{^}} call $push[[NUM:[0-9]+]]=, float_nullary{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define float @call_float_nullary() {
%r = call float @float_nullary()
@ -46,7 +46,7 @@ define float @call_float_nullary() {
; CHECK-LABEL: call_double_nullary:
; CHECK-NEXT: .functype call_double_nullary () -> (f64){{$}}
; CHECK-NEXT: {{^}} f64.call $push[[NUM:[0-9]+]]=, double_nullary{{$}}
; CHECK-NEXT: {{^}} call $push[[NUM:[0-9]+]]=, double_nullary{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define double @call_double_nullary() {
%r = call double @double_nullary()
@ -55,7 +55,7 @@ define double @call_double_nullary() {
; CHECK-LABEL: call_v128_nullary:
; CHECK-NEXT: .functype call_v128_nullary () -> (v128){{$}}
; CHECK-NEXT: {{^}} v128.call $push[[NUM:[0-9]+]]=, v128_nullary{{$}}
; CHECK-NEXT: {{^}} call $push[[NUM:[0-9]+]]=, v128_nullary{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define <16 x i8> @call_v128_nullary() {
%r = call <16 x i8> @v128_nullary()
@ -74,7 +74,7 @@ define void @call_void_nullary() {
; CHECK-LABEL: call_i32_unary:
; CHECK-NEXT: .functype call_i32_unary (i32) -> (i32){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_unary, $pop[[L0]]{{$}}
; CHECK-NEXT: {{^}} call $push[[NUM:[0-9]+]]=, i32_unary, $pop[[L0]]{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i32 @call_i32_unary(i32 %a) {
%r = call i32 @i32_unary(i32 %a)
@ -85,7 +85,7 @@ define i32 @call_i32_unary(i32 %a) {
; CHECK-NEXT: .functype call_i32_binary (i32, i32) -> (i32){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_binary, $pop[[L0]], $pop[[L1]]{{$}}
; CHECK-NEXT: {{^}} call $push[[NUM:[0-9]+]]=, i32_binary, $pop[[L0]], $pop[[L1]]{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i32 @call_i32_binary(i32 %a, i32 %b) {
%r = call i32 @i32_binary(i32 %a, i32 %b)
@ -105,7 +105,7 @@ define void @call_indirect_void(void ()* %callee) {
; CHECK-LABEL: call_indirect_i32:
; CHECK-NEXT: .functype call_indirect_i32 (i32) -> (i32){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: {{^}} i32.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: {{^}} call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i32 @call_indirect_i32(i32 ()* %callee) {
%t = call i32 %callee()
@ -115,7 +115,7 @@ define i32 @call_indirect_i32(i32 ()* %callee) {
; CHECK-LABEL: call_indirect_i64:
; CHECK-NEXT: .functype call_indirect_i64 (i32) -> (i64){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: {{^}} i64.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: {{^}} call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i64 @call_indirect_i64(i64 ()* %callee) {
%t = call i64 %callee()
@ -125,7 +125,7 @@ define i64 @call_indirect_i64(i64 ()* %callee) {
; CHECK-LABEL: call_indirect_float:
; CHECK-NEXT: .functype call_indirect_float (i32) -> (f32){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: {{^}} f32.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: {{^}} call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define float @call_indirect_float(float ()* %callee) {
%t = call float %callee()
@ -135,7 +135,7 @@ define float @call_indirect_float(float ()* %callee) {
; CHECK-LABEL: call_indirect_double:
; CHECK-NEXT: .functype call_indirect_double (i32) -> (f64){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: {{^}} f64.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: {{^}} call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define double @call_indirect_double(double ()* %callee) {
%t = call double %callee()
@ -145,7 +145,7 @@ define double @call_indirect_double(double ()* %callee) {
; CHECK-LABEL: call_indirect_v128:
; CHECK-NEXT: .functype call_indirect_v128 (i32) -> (v128){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: {{^}} v128.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: {{^}} call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define <16 x i8> @call_indirect_v128(<16 x i8> ()* %callee) {
%t = call <16 x i8> %callee()
@ -168,7 +168,7 @@ define void @call_indirect_arg(void (i32)* %callee, i32 %arg) {
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 1{{$}}
; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 2{{$}}
; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: {{^}} i32.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]], $pop[[L2]]{{$}}
; CHECK-NEXT: {{^}} call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]], $pop[[L2]]{{$}}
; CHECK-NEXT: drop $pop[[NUM]]{{$}}
; CHECK-NEXT: return{{$}}
define void @call_indirect_arg_2(i32 (i32, i32)* %callee, i32 %arg, i32 %arg2) {

View File

@ -27,13 +27,13 @@ target triple = "wasm32-unknown-unknown"
; CHECK: catch
; CHECK: block
; CHECK: br_if 0, {{.*}} # 0: down to label2
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: call __cxa_end_catch
; CHECK: br 1 # 1: down to label0
; CHECK: end_block # label2:
; CHECK: block
; CHECK: br_if 0, {{.*}} # 0: down to label3
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: call __cxa_end_catch
; CHECK: br 1 # 1: down to label0
; CHECK: end_block # label3:
@ -98,7 +98,7 @@ try.cont: ; preds = %catch, %catch2, %en
; CHECK: block
; CHECK: block
; CHECK: br_if 0, {{.*}} # 0: down to label7
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: try
; CHECK: call foo
; CHECK: br 2 # 2: down to label6
@ -106,7 +106,7 @@ try.cont: ; preds = %catch, %catch2, %en
; CHECK: try
; CHECK: block
; CHECK: br_if 0, {{.*}} # 0: down to label11
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: try
; CHECK: call foo
; CHECK: br 2 # 2: down to label9
@ -216,7 +216,7 @@ unreachable: ; preds = %rethrow5
; CHECK: try
; CHECK: call foo
; CHECK: catch
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: loop # label15:
; CHECK: block
; CHECK: block
@ -447,8 +447,8 @@ try.cont: ; preds = %catch.start1, %catc
; --- Nested try/catch/end_try starts
; NOSORT: try
; NOSORT: call bar
; NOSORT: i32.call ${{[0-9]+}}=, baz
; NOSORT-NOT: i32.call $push{{.*}}=, baz
; NOSORT: call ${{[0-9]+}}=, baz
; NOSORT-NOT: call $push{{.*}}=, baz
; NOSORT: catch $[[REG:[0-9]+]]=
; NOSORT: br 1 # 1: down to label35
; NOSORT: end_try
@ -570,7 +570,7 @@ try.cont: ; preds = %catch.start
; NOSORT: end_try
; --- Nested try/catch/end_try ends
; NOSORT: end_block # label46:
; NOSORT: i32.call $drop=, __cxa_begin_catch
; NOSORT: call $drop=, __cxa_begin_catch
; --- Nested try/catch/end_try starts
; NOSORT: try
; NOSORT: call __cxa_end_catch
@ -582,7 +582,7 @@ try.cont: ; preds = %catch.start
; NOSORT: end_try
; NOSORT: catch $[[REG0]]=
; NOSORT: end_try # label43:
; NOSORT: i32.call $drop=, __cxa_begin_catch
; NOSORT: call $drop=, __cxa_begin_catch
; NOSORT: call __cxa_end_catch
; NOSORT: end_block # label42:
; NOSORT: return
@ -678,9 +678,9 @@ if.end: ; preds = %cont, %catch.start,
; NOSORT-LABEL: test10
; NOSORT: try
; NOSORT: call foo
; NOSORT: i32.call {{.*}} memcpy
; NOSORT: i32.call {{.*}} memmove
; NOSORT: i32.call {{.*}} memset
; NOSORT: call {{.*}} memcpy
; NOSORT: call {{.*}} memmove
; NOSORT: call {{.*}} memset
; NOSORT: return
; NOSORT: catch
; NOSORT: rethrow
@ -711,7 +711,7 @@ ehcleanup: ; preds = %entry
; CHECK-LABEL: test11
; CHECK: try
; CHECK: i32.call $push{{.*}}=, nothrow_i32
; CHECK: call $push{{.*}}=, nothrow_i32
; CHECK: call fun, $pop{{.*}}
define void @test11() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
entry:

View File

@ -23,11 +23,11 @@ body: |
; TRY should be before EH_LABEL wrappers of throwing calls
; CHECK: TRY
; CHECK-NEXT: EH_LABEL
; CHECK-NEXT: CALL_VOID @foo
; CHECK-NEXT: CALL @foo
; CHECK-NEXT: EH_LABEL
successors: %bb.1, %bb.2
EH_LABEL <mcsymbol .Ltmp0>
CALL_VOID @foo, implicit-def dead $arguments, implicit $sp32, implicit $sp64
CALL @foo, implicit-def dead $arguments, implicit $sp32, implicit $sp64
EH_LABEL <mcsymbol .Ltmp1>
bb.1 (landing-pad):

View File

@ -40,10 +40,10 @@ define void @test_throw(i8* %p) {
; CHECK: extract_exception $[[EXN:[0-9]+]]=
; CHECK-DAG: i32.store __wasm_lpad_context
; CHECK-DAG: i32.store __wasm_lpad_context+4
; CHECK: i32.call $drop=, _Unwind_CallPersonality, $[[EXN]]
; CHECK: call $drop=, _Unwind_CallPersonality, $[[EXN]]
; CHECK: block
; CHECK: br_if 0
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: call __cxa_end_catch
; CHECK: br 1
; CHECK: end_block
@ -94,7 +94,7 @@ try.cont: ; preds = %entry, %catch
; CHECK: call foo
; CHECK: catch $[[EXNREF:[0-9]+]]=
; CHECK: global.set __stack_pointer
; CHECK: i32.call $drop=, _ZN4TempD2Ev
; CHECK: call $drop=, _ZN4TempD2Ev
; CHECK: rethrow $[[EXNREF]]
; CHECK: end_try
define void @test_cleanup() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
@ -129,7 +129,7 @@ ehcleanup: ; preds = %entry
; CHECK: try
; CHECK: call foo
; CHECK: catch
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: try
; CHECK: call foo
; CHECK: catch
@ -213,7 +213,7 @@ terminate: ; preds = %ehcleanup
; CHECK: block
; CHECK: block
; CHECK: br_if 0
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: try
; CHECK: call foo
; CHECK: catch
@ -286,7 +286,7 @@ ehcleanup: ; preds = %catch
; CHECK: try
; CHECK: call foo
; CHECK: catch
; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: call $drop=, __cxa_begin_catch
; CHECK: call __cxa_end_catch
; CHECK: end_try
; CHECK-NOT: global.set __stack_pointer

View File

@ -9,8 +9,8 @@ target triple = "wasm32-unknown-unknown"
; CHECK-LABEL: demote.f32:
; CHECK-NEXT: .functype demote.f32 (f32) -> (f32){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: i32.call $push[[L1:[0-9]+]]=, __truncsfhf2, $pop[[L0]]{{$}}
; CHECK-NEXT: f32.call $push[[L2:[0-9]+]]=, __extendhfsf2, $pop[[L1]]{{$}}
; CHECK-NEXT: call $push[[L1:[0-9]+]]=, __truncsfhf2, $pop[[L0]]{{$}}
; CHECK-NEXT: call $push[[L2:[0-9]+]]=, __extendhfsf2, $pop[[L1]]{{$}}
; CHECK-NEXT: return $pop[[L2]]{{$}}
define half @demote.f32(float %f) {
%t = fptrunc float %f to half
@ -29,8 +29,8 @@ define float @promote.f32(half %f) {
; CHECK-LABEL: demote.f64:
; CHECK-NEXT: .functype demote.f64 (f64) -> (f32){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: i32.call $push[[L1:[0-9]+]]=, __truncdfhf2, $pop[[L0]]{{$}}
; CHECK-NEXT: f32.call $push[[L2:[0-9]+]]=, __extendhfsf2, $pop[[L1]]{{$}}
; CHECK-NEXT: call $push[[L1:[0-9]+]]=, __truncdfhf2, $pop[[L0]]{{$}}
; CHECK-NEXT: call $push[[L2:[0-9]+]]=, __extendhfsf2, $pop[[L1]]{{$}}
; CHECK-NEXT: return $pop[[L2]]{{$}}
define half @demote.f64(double %f) {
%t = fptrunc double %f to half
@ -51,8 +51,8 @@ define double @promote.f64(half %f) {
; CHECK-NEXT: .functype demote.f128 (i64, i64) -> (f32){{$}}
; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}}
; CHECK-NEXT: i32.call $push[[L2:[0-9]+]]=, __trunctfhf2, $pop[[L0]], $pop[[L1]]{{$}}
; CHECK-NEXT: f32.call $push[[L3:[0-9]+]]=, __extendhfsf2, $pop[[L2]]{{$}}
; CHECK-NEXT: call $push[[L2:[0-9]+]]=, __trunctfhf2, $pop[[L0]], $pop[[L1]]{{$}}
; CHECK-NEXT: call $push[[L3:[0-9]+]]=, __extendhfsf2, $pop[[L2]]{{$}}
; CHECK-NEXT: return $pop[[L3]]{{$}}
define half @demote.f128(fp128 %f) {
%t = fptrunc fp128 %f to half

View File

@ -177,7 +177,7 @@ define float @fmaxnum32_intrinsic(float %x, float %y) {
}
; CHECK-LABEL: fma32:
; CHECK: {{^}} f32.call $push[[LR:[0-9]+]]=, fmaf, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: {{^}} call $push[[LR:[0-9]+]]=, fmaf, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK-NEXT: return $pop[[LR]]{{$}}
define float @fma32(float %a, float %b, float %c) {
%d = call float @llvm.fma.f32(float %a, float %b, float %c)

View File

@ -159,7 +159,7 @@ define double @fmax64_intrinsic(double %x, double %y) {
}
; CHECK-LABEL: fma64:
; CHECK: {{^}} f64.call $push[[LR:[0-9]+]]=, fma, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: {{^}} call $push[[LR:[0-9]+]]=, fma, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK-NEXT: return $pop[[LR]]{{$}}
define double @fma64(double %a, double %b, double %c) {
%d = call double @llvm.fma.f64(double %a, double %b, double %c)

View File

@ -7,7 +7,7 @@ target triple = "wasm32-unknown-unknown"
; CHECK-LABEL: frem32:
; CHECK-NEXT: .functype frem32 (f32, f32) -> (f32){{$}}
; CHECK-NEXT: {{^}} f32.call $push0=, fmodf, $0, $1{{$}}
; CHECK-NEXT: {{^}} call $push0=, fmodf, $0, $1{{$}}
; CHECK-NEXT: return $pop0{{$}}
define float @frem32(float %x, float %y) {
%a = frem float %x, %y
@ -16,7 +16,7 @@ define float @frem32(float %x, float %y) {
; CHECK-LABEL: frem64:
; CHECK-NEXT: .functype frem64 (f64, f64) -> (f64){{$}}
; CHECK-NEXT: {{^}} f64.call $push0=, fmod, $0, $1{{$}}
; CHECK-NEXT: {{^}} call $push0=, fmod, $0, $1{{$}}
; CHECK-NEXT: return $pop0{{$}}
define double @frem64(double %x, double %y) {
%a = frem double %x, %y

View File

@ -24,7 +24,7 @@ declare void @foo3()
; CHECK: call .Lhas_i32_arg_bitcast.2{{$}}
; CHECK-NEXT: call .Lhas_i32_arg_bitcast.2{{$}}
; CHECK-NEXT: call .Lhas_i32_ret_bitcast{{$}}
; CHECK-NEXT: i32.call $drop=, has_i32_ret
; CHECK-NEXT: call $drop=, has_i32_ret
; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 0
; CHECK-NEXT: call .Lfoo0_bitcast, $pop[[L0]]{{$}}
; CHECK-NEXT: i32.const $push[[L1:[0-9]+]]=, 0
@ -32,7 +32,7 @@ declare void @foo3()
; CHECK-NEXT: i32.const $push[[L2:[0-9]+]]=, 0
; CHECK-NEXT: call .Lfoo0_bitcast, $pop[[L2]]{{$}}
; CHECK-NEXT: call foo0
; CHECK-NEXT: i32.call $drop=, .Lfoo1_bitcast{{$}}
; CHECK-NEXT: call $drop=, .Lfoo1_bitcast{{$}}
; CHECK-NEXT: call foo2{{$}}
; CHECK-NEXT: call foo1{{$}}
; CHECK-NEXT: call foo3{{$}}
@ -126,7 +126,7 @@ define void @test_store() {
; CHECK-NEXT: .functype test_load () -> (i32){{$}}
; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L1:[0-9]+]]=, global_func($pop[[L0]]){{$}}
; CHECK-NEXT: i32.call_indirect $push{{[0-9]+}}=, $pop[[L1]]{{$}}
; CHECK-NEXT: call_indirect $push{{[0-9]+}}=, $pop[[L1]]{{$}}
define i32 @test_load() {
%1 = load i32 ()*, i32 ()** bitcast (void ()** @global_func to i32 ()**)
%2 = call i32 %1()

View File

@ -21,7 +21,7 @@ define i32 @foo() {
; CHECK-LABEL: call_memcpy:
; CHECK-NEXT: .functype call_memcpy (i32, i32, i32) -> (i32){{$}}
; CHECK-NEXT: i32.call $push0=, memcpy, $0, $1, $2{{$}}
; CHECK-NEXT: call $push0=, memcpy, $0, $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1)
define i8* @call_memcpy(i8* %p, i8* nocapture readonly %q, i32 %n) {

View File

@ -61,21 +61,21 @@ define i128 @i128libcalls(i128 %x, i128 %y) {
; CHECK-LABEL: f64libcalls:
define i32 @f64libcalls(double %x, double %y, i32 %z) {
; CHECK: f64.call $push{{[0-9]}}=, cos
; CHECK: call $push{{[0-9]}}=, cos
%a = call double @llvm.cos.f64(double %x)
; CHECK: f64.call $push{{[0-9]}}=, log10
; CHECK: call $push{{[0-9]}}=, log10
%b = call double @llvm.log10.f64(double %a)
; CHECK: f64.call $push{{[0-9]}}=, pow
; CHECK: call $push{{[0-9]}}=, pow
%c = call double @llvm.pow.f64(double %b, double %y)
; CHECK: f64.call $push{{[0-9]}}=, __powidf2
; CHECK: call $push{{[0-9]}}=, __powidf2
%d = call double @llvm.powi.f64(double %c, i32 %z)
; CHECK: f64.call $push{{[0-9]}}=, log
; CHECK: call $push{{[0-9]}}=, log
%e = call double @llvm.log.f64(double %d)
; CHECK: f64.call $push{{[0-9]}}=, exp
; CHECK: call $push{{[0-9]}}=, exp
%f = call double @llvm.exp.f64(double %e)
; CHECK: f64.call $push{{[0-9]}}=, cbrt
; CHECK: call $push{{[0-9]}}=, cbrt
%g = call fast double @llvm.pow.f64(double %f, double 0x3FD5555555555555)
; CHECK: i32.call $push{{[0-9]}}=, lround
; CHECK: call $push{{[0-9]}}=, lround
%h = call i32 @llvm.lround(double %g)
ret i32 %h
}
@ -112,7 +112,7 @@ define i1 @unordf(float %x, float %y) {
; CHECK-LABEL: unordt:
define i1 @unordt(fp128 %x, fp128 %y) {
; CHECK: i32.call $push[[CALL:[0-9]]]=, __unordtf2
; CHECK: call $push[[CALL:[0-9]]]=, __unordtf2
; CHECK-NEXT: i32.const $push[[ZERO:[0-9]+]]=, 0
; CHECK-NEXT: i32.ne $push{{[0-9]}}=, $pop[[CALL]], $pop[[ZERO]]
%a = fcmp uno fp128 %x, %y
@ -121,7 +121,7 @@ define i1 @unordt(fp128 %x, fp128 %y) {
; CHECK-LABEL: ordt:
define i1 @ordt(fp128 %x, fp128 %y) {
; CHECK: i32.call $push[[CALL:[0-9]]]=, __unordtf2
; CHECK: call $push[[CALL:[0-9]]]=, __unordtf2
; CHECK-NEXT: i32.eqz $push{{[0-9]}}=, $pop[[CALL]]
%a = fcmp ord fp128 %x, %y
ret i1 %a

View File

@ -6,7 +6,7 @@ define i64 @testmsxs_builtin(float %x) {
; CHECK: .functype testmsxs_builtin (f32) -> (i64)
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i64.call llroundf
; CHECK-NEXT: call llroundf
; CHECK-NEXT: # fallthrough-return
; CHECK-NEXT: end_function
entry:
@ -19,7 +19,7 @@ define i64 @testmsxd_builtin(double %x) {
; CHECK: .functype testmsxd_builtin (f64) -> (i64)
; CHECK-NEXT: # %bb.0: # %entry
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i64.call llround
; CHECK-NEXT: call llround
; CHECK-NEXT: # fallthrough-return
; CHECK-NEXT: end_function
entry:

View File

@ -39,9 +39,9 @@ entry:
%arraydecay1 = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %buf, i32 0, i32 0
call void @longjmp(%struct.__jmp_buf_tag* %arraydecay1, i32 1) #1
unreachable
; SJLJ: i32.call saveSetjmp
; SJLJ: i32.call testSetjmp
; NONE: i32.call setjmp
; SJLJ: call saveSetjmp
; SJLJ: call testSetjmp
; NONE: call setjmp
; NONE: call longjmp
}

View File

@ -48,7 +48,7 @@ declare void @after_the_null()
; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.0{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: i32.call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: i32.eqz $push4=, $pop3
; CHECK-NEXT: br_if 0, $pop4
; CHECK-NEXT: unreachable
@ -64,7 +64,7 @@ declare void @after_the_null()
; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: i32.call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: i32.eqz $push4=, $pop3
; CHECK-NEXT: br_if 0, $pop4
; CHECK-NEXT: unreachable
@ -79,7 +79,7 @@ declare void @after_the_null()
; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1.associated1c0{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: i32.call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: i32.eqz $push4=, $pop3
; CHECK-NEXT: br_if 0, $pop4
; CHECK-NEXT: unreachable
@ -94,7 +94,7 @@ declare void @after_the_null()
; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1.associated1c1{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: i32.call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: i32.eqz $push4=, $pop3
; CHECK-NEXT: br_if 0, $pop4
; CHECK-NEXT: unreachable
@ -108,7 +108,7 @@ declare void @after_the_null()
; CHECK-NEXT: i32.const $push2=, .Lcall_dtors{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: i32.call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
; CHECK-NEXT: i32.eqz $push4=, $pop3
; CHECK-NEXT: br_if 0, $pop4
; CHECK-NEXT: unreachable

View File

@ -12,7 +12,7 @@ declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1)
; Test that return values are optimized.
; CHECK-LABEL: copy_yes:
; CHECK: i32.call $push0=, memcpy, $0, $1, $2{{$}}
; CHECK: call $push0=, memcpy, $0, $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
define i8* @copy_yes(i8* %dst, i8* %src, i32 %len) {
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i1 false)
@ -20,7 +20,7 @@ define i8* @copy_yes(i8* %dst, i8* %src, i32 %len) {
}
; CHECK-LABEL: copy_no:
; CHECK: i32.call $drop=, memcpy, $0, $1, $2{{$}}
; CHECK: call $drop=, memcpy, $0, $1, $2{{$}}
; CHECK-NEXT: return{{$}}
define void @copy_no(i8* %dst, i8* %src, i32 %len) {
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i1 false)
@ -28,7 +28,7 @@ define void @copy_no(i8* %dst, i8* %src, i32 %len) {
}
; CHECK-LABEL: move_yes:
; CHECK: i32.call $push0=, memmove, $0, $1, $2{{$}}
; CHECK: call $push0=, memmove, $0, $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
define i8* @move_yes(i8* %dst, i8* %src, i32 %len) {
call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i1 false)
@ -36,7 +36,7 @@ define i8* @move_yes(i8* %dst, i8* %src, i32 %len) {
}
; CHECK-LABEL: move_no:
; CHECK: i32.call $drop=, memmove, $0, $1, $2{{$}}
; CHECK: call $drop=, memmove, $0, $1, $2{{$}}
; CHECK-NEXT: return{{$}}
define void @move_no(i8* %dst, i8* %src, i32 %len) {
call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i1 false)
@ -44,7 +44,7 @@ define void @move_no(i8* %dst, i8* %src, i32 %len) {
}
; CHECK-LABEL: set_yes:
; CHECK: i32.call $push0=, memset, $0, $1, $2{{$}}
; CHECK: call $push0=, memset, $0, $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
define i8* @set_yes(i8* %dst, i8 %src, i32 %len) {
call void @llvm.memset.p0i8.i32(i8* %dst, i8 %src, i32 %len, i1 false)
@ -52,7 +52,7 @@ define i8* @set_yes(i8* %dst, i8 %src, i32 %len) {
}
; CHECK-LABEL: set_no:
; CHECK: i32.call $drop=, memset, $0, $1, $2{{$}}
; CHECK: call $drop=, memset, $0, $1, $2{{$}}
; CHECK-NEXT: return{{$}}
define void @set_no(i8* %dst, i8 %src, i32 %len) {
call void @llvm.memset.p0i8.i32(i8* %dst, i8 %src, i32 %len, i1 false)
@ -61,8 +61,8 @@ define void @set_no(i8* %dst, i8 %src, i32 %len) {
; CHECK-LABEL: frame_index:
; CHECK: i32.call $drop=, memset, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: i32.call $push{{[0-9]+}}=, memset, ${{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: call $drop=, memset, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: call $push{{[0-9]+}}=, memset, ${{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: return{{$}}
define void @frame_index() {
entry:
@ -80,7 +80,7 @@ entry:
; this specific functionality.
; CHECK-LABEL: drop_result:
; CHECK: i32.call $drop=, memset, $0, $1, $2
; CHECK: call $drop=, memset, $0, $1, $2
declare i8* @def()
declare void @block_tail_dup()
define i8* @drop_result(i8* %arg, i8 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) {
@ -113,7 +113,7 @@ bb11:
; result of the memset *is* stackified.
; CHECK-LABEL: tail_dup_to_reuse_result:
; CHECK: i32.call $push{{[0-9]+}}=, memset, $0, $1, $2
; CHECK: call $push{{[0-9]+}}=, memset, $0, $1, $2
define i8* @tail_dup_to_reuse_result(i8* %arg, i8 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) {
bb:
%tmp = icmp eq i32 %arg3, 0

View File

@ -1,4 +1,5 @@
; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mattr=+multivalue,+tail-call | FileCheck %s
; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+multivalue,+tail-call | FileCheck %s --check-prefix REGS
; RUN: llc < %s --filetype=obj -mattr=+multivalue,+tail-call | obj2yaml | FileCheck %s --check-prefix OBJ
; Test that the multivalue calls, returns, function types, and block
@ -37,6 +38,7 @@ define %pair @pair_ident(%pair %p) {
; CHECK-NEXT: drop{{$}}
; CHECK-NEXT: drop{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $drop=, $drop=, pair_const{{$}}
define void @pair_call() {
%p = call %pair @pair_const()
ret void
@ -46,6 +48,7 @@ define void @pair_call() {
; CHECK-NEXT: .functype pair_call_return () -> (i32, i64)
; CHECK-NEXT: call pair_const{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $push{{[0-9]+}}=, $push{{[0-9]+}}=, pair_const{{$}}
define %pair @pair_call_return() {
%p = call %pair @pair_const()
ret %pair %p
@ -56,6 +59,7 @@ define %pair @pair_call_return() {
; CHECK-NEXT: local.get 0{{$}}
; CHECK-NEXT: call_indirect () -> (i32, i64){{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call_indirect $push{{[0-9]+}}=, $push{{[0-9]+}}=, $0{{$}}
define %pair @pair_call_indirect(%pair()* %f) {
%p = call %pair %f()
ret %pair %p
@ -65,6 +69,7 @@ define %pair @pair_call_indirect(%pair()* %f) {
; CHECK-NEXT: .functype pair_tail_call () -> (i32, i64)
; CHECK-NEXT: return_call pair_const{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: return_call pair_const{{$}}
define %pair @pair_tail_call() {
%p = musttail call %pair @pair_const()
ret %pair %p
@ -75,6 +80,7 @@ define %pair @pair_tail_call() {
; CHECK-NEXT: call pair_const{{$}}
; CHECK-NEXT: drop{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $push{{[0-9]+}}=, $drop=, pair_const{{$}}
define i32 @pair_call_return_first() {
%p = call %pair @pair_const()
%v = extractvalue %pair %p, 0
@ -89,6 +95,7 @@ define i32 @pair_call_return_first() {
; CHECK-NEXT: drop{{$}}
; CHECK-NEXT: local.get 0{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $drop=, $0=, pair_const{{$}}
define i64 @pair_call_return_second() {
%p = call %pair @pair_const()
%v = extractvalue %pair %p, 1
@ -101,6 +108,7 @@ define i64 @pair_call_return_second() {
; CHECK-NEXT: drop{{$}}
; CHECK-NEXT: call use_i32{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $push{{[0-9]+}}=, $drop=, pair_const{{$}}
define void @pair_call_use_first() {
%p = call %pair @pair_const()
%v = extractvalue %pair %p, 0
@ -117,6 +125,7 @@ define void @pair_call_use_first() {
; CHECK-NEXT: local.get 0{{$}}
; CHECK-NEXT: call use_i64{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $drop=, $0=, pair_const{{$}}
define void @pair_call_use_second() {
%p = call %pair @pair_const()
%v = extractvalue %pair %p, 1
@ -132,6 +141,7 @@ define void @pair_call_use_second() {
; CHECK-NEXT: call use_i32{{$}}
; CHECK-NEXT: local.get 0{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $push{{[0-9]+}}=, $0=, pair_const{{$}}
define i64 @pair_call_use_first_return_second() {
%p = call %pair @pair_const()
%v = extractvalue %pair %p, 0
@ -150,6 +160,7 @@ define i64 @pair_call_use_first_return_second() {
; CHECK-NEXT: call use_i64{{$}}
; CHECK-NEXT: local.get 0{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $0=, $1=, pair_const{{$}}
define i32 @pair_call_use_second_return_first() {
%p = call %pair @pair_const()
%v = extractvalue %pair %p, 1
@ -164,6 +175,7 @@ define i32 @pair_call_use_second_return_first() {
; CHECK-NEXT: local.get 1
; CHECK-NEXT: call pair_ident{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $push{{[0-9]+}}=, $push{{[0-9]+}}=, pair_ident, $0, $1{{$}}
define %pair @pair_pass_through(%pair %p) {
%r = call %pair @pair_ident(%pair %p)
ret %pair %r
@ -191,6 +203,7 @@ define %rpair @pair_swap(%pair %p) {
; CHECK-NEXT: local.get 1{{$}}
; CHECK-NEXT: local.get 0{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $0=, $1=, pair_const{{$}}
define %rpair @pair_call_swap() {
%p = call %pair @pair_const()
%first = extractvalue %pair %p, 0
@ -210,6 +223,7 @@ define %rpair @pair_call_swap() {
; CHECK-NEXT: local.get 1{{$}}
; CHECK-NEXT: local.get 0{{$}}
; CHECK-NEXT: end_function{{$}}
; REGS: call $0=, $1=, pair_ident, $0, $1{{$}}
define %rpair @pair_pass_through_swap(%pair %p) {
%p1 = call %pair @pair_ident(%pair %p)
%first = extractvalue %pair %p1, 0

View File

@ -71,7 +71,7 @@ define i32 @sink_trap(i32 %x, i32 %y, i32* %p) {
; Yes because the call is readnone.
; CHECK-LABEL: sink_readnone_call:
; CHECK: return $pop0{{$}}
; CHECK: return $pop1{{$}}
; NOREGS-LABEL: sink_readnone_call:
; NOREGS: return{{$}}
declare i32 @readnone_callee() readnone nounwind
@ -378,18 +378,18 @@ define void @multiple_uses_in_same_insn(i32 %x, i32 %y) {
; CHECK-LABEL: commute:
; CHECK: .functype commute () -> (i32){{$}}
; CHECK-NEXT: i32.call $push0=, red{{$}}
; CHECK-NEXT: i32.call $push1=, green{{$}}
; CHECK-NEXT: call $push0=, red{{$}}
; CHECK-NEXT: call $push1=, green{{$}}
; CHECK-NEXT: i32.add $push2=, $pop0, $pop1{{$}}
; CHECK-NEXT: i32.call $push3=, blue{{$}}
; CHECK-NEXT: call $push3=, blue{{$}}
; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}}
; CHECK-NEXT: return $pop4{{$}}
; NOREGS-LABEL: commute:
; NOREGS: .functype commute () -> (i32){{$}}
; NOREGS-NEXT: i32.call red{{$}}
; NOREGS-NEXT: i32.call green{{$}}
; NOREGS-NEXT: call red{{$}}
; NOREGS-NEXT: call green{{$}}
; NOREGS-NEXT: i32.add {{$}}
; NOREGS-NEXT: i32.call blue{{$}}
; NOREGS-NEXT: call blue{{$}}
; NOREGS-NEXT: i32.add {{$}}
; NOREGS-NEXT: return{{$}}
declare i32 @red()
@ -408,21 +408,21 @@ define i32 @commute() {
; an implicit local.get for the register.
; CHECK-LABEL: no_stackify_past_use:
; CHECK: i32.call $1=, callee, $0
; CHECK: call $1=, callee, $0
; CHECK-NEXT: i32.const $push0=, 1
; CHECK-NEXT: i32.add $push1=, $0, $pop0
; CHECK-NEXT: i32.call $push2=, callee, $pop1
; CHECK-NEXT: call $push2=, callee, $pop1
; CHECK-NEXT: i32.sub $push3=, $pop2, $1
; CHECK-NEXT: i32.div_s $push4=, $pop3, $1
; CHECK-NEXT: return $pop4
; NOREGS-LABEL: no_stackify_past_use:
; NOREGS: local.get 0{{$}}
; NOREGS-NEXT: i32.call callee
; NOREGS-NEXT: call callee
; NOREGS-NEXT: local.set 1{{$}}
; NOREGS-NEXT: local.get 0{{$}}
; NOREGS-NEXT: i32.const 1
; NOREGS-NEXT: i32.add
; NOREGS-NEXT: i32.call callee
; NOREGS-NEXT: call callee
; NOREGS-NEXT: local.get 1{{$}}
; NOREGS-NEXT: i32.sub
; NOREGS-NEXT: local.get 1{{$}}
@ -442,23 +442,23 @@ define i32 @no_stackify_past_use(i32 %arg) {
; so we can reorder the operands and stackify.
; CHECK-LABEL: commute_to_fix_ordering:
; CHECK: i32.call $push[[L0:.+]]=, callee, $0
; CHECK: call $push[[L0:.+]]=, callee, $0
; CHECK: local.tee $push[[L1:.+]]=, $1=, $pop[[L0]]
; CHECK: i32.const $push0=, 1
; CHECK: i32.add $push1=, $0, $pop0
; CHECK: i32.call $push2=, callee, $pop1
; CHECK: call $push2=, callee, $pop1
; CHECK: i32.add $push3=, $1, $pop2
; CHECK: i32.mul $push4=, $pop[[L1]], $pop3
; CHECK: return $pop4
; NOREGS-LABEL: commute_to_fix_ordering:
; NOREGS: local.get 0{{$}}
; NOREGS: i32.call callee
; NOREGS: call callee
; NOREGS: local.tee 1
; NOREGS: local.get 1{{$}}
; NOREGS: local.get 0{{$}}
; NOREGS: i32.const 1
; NOREGS: i32.add
; NOREGS: i32.call callee
; NOREGS: call callee
; NOREGS: i32.add
; NOREGS: i32.mul
; NOREGS: return
@ -521,11 +521,11 @@ exit:
; Don't move calls past loads
; CHECK-LABEL: no_stackify_call_past_load:
; CHECK: i32.call $0=, red
; CHECK: call $0=, red
; CHECK: i32.const $push0=, 0
; CHECK: i32.load $1=, count($pop0)
; NOREGS-LABEL: no_stackify_call_past_load:
; NOREGS: i32.call red
; NOREGS: call red
; NOREGS: i32.const 0
; NOREGS: i32.load count
@count = hidden global i32 0, align 4
@ -541,11 +541,11 @@ define i32 @no_stackify_call_past_load() {
; CHECK-LABEL: no_stackify_store_past_load
; CHECK: i32.store 0($1), $0
; CHECK: i32.load {{.*}}, 0($2)
; CHECK: i32.call {{.*}}, callee, $0{{$}}
; CHECK: call {{.*}}, callee, $0{{$}}
; NOREGS-LABEL: no_stackify_store_past_load
; NOREGS: i32.store 0
; NOREGS: i32.load 0
; NOREGS: i32.call callee{{$}}
; NOREGS: call callee{{$}}
define i32 @no_stackify_store_past_load(i32 %a, i32* %p1, i32* %p2) {
store i32 %a, i32* %p1
%b = load i32, i32* %p2, align 4
@ -556,12 +556,12 @@ define i32 @no_stackify_store_past_load(i32 %a, i32* %p1, i32* %p2) {
; Can still stackify past invariant loads.
; CHECK-LABEL: store_past_invar_load
; CHECK: i32.store 0($1), $0
; CHECK: i32.call {{.*}}, callee, $0
; CHECK: call {{.*}}, callee, $0
; CHECK: i32.load $push{{.*}}, 0($2)
; CHECK: return $pop
; NOREGS-LABEL: store_past_invar_load
; NOREGS: i32.store 0
; NOREGS: i32.call callee
; NOREGS: call callee
; NOREGS: i32.load 0
; NOREGS: return
define i32 @store_past_invar_load(i32 %a, i32* %p1, i32* dereferenceable(4) %p2) {
@ -649,13 +649,13 @@ define i32 @stackpointer_dependency(i8* readnone) {
; CHECK-NEXT: local.tee $push[[L3:.+]]=, $0=, $pop[[L4]]
; CHECK-NEXT: i32.load $push[[L0:.+]]=, 0($0)
; CHECK-NEXT: i32.load $push[[L1:.+]]=, 0($pop[[L0]])
; CHECK-NEXT: i32.call_indirect $push{{.+}}=, $pop[[L3]], $1, $pop[[L1]]
; CHECK-NEXT: call_indirect $push{{.+}}=, $pop[[L3]], $1, $pop[[L1]]
; NOREGS-LABEL: call_indirect_stackify:
; NOREGS: i32.load 0
; NOREGS-NEXT: local.tee 0
; NOREGS: i32.load 0
; NOREGS-NEXT: i32.load 0
; NOREGS-NEXT: i32.call_indirect (i32, i32) -> (i32)
; NOREGS-NEXT: call_indirect (i32, i32) -> (i32)
%class.call_indirect = type { i32 (...)** }
define i32 @call_indirect_stackify(%class.call_indirect** %objptr, i32 %arg) {
%obj = load %class.call_indirect*, %class.call_indirect** %objptr
@ -680,4 +680,3 @@ define i32 @call_indirect_stackify(%class.call_indirect** %objptr, i32 %arg) {
!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!9 = !DIExpression()
!10 = !DILocation(line: 15, column: 6, scope: !5)

View File

@ -8,7 +8,7 @@ target triple = "wasm32-unknown-emscripten"
; CHECK-LABEL: test_returnaddress:
; CHECK-NEXT: .functype test_returnaddress () -> (i32){{$}}
; CHECK-NEXT: {{^}} i32.const 0{{$}}
; CHECK-NEXT: {{^}} i32.call emscripten_return_address{{$}}
; CHECK-NEXT: {{^}} call emscripten_return_address{{$}}
; CHECK-NEXT: {{^}} end_function{{$}}
define i8* @test_returnaddress() {
%r = call i8* @llvm.returnaddress(i32 0)

View File

@ -8,8 +8,8 @@ target triple = "wasm32-unknown-unknown"
; CHECK-LABEL: _Z3foov:
; CHECK-NEXT: .functype _Z3foov () -> (i32){{$}}
; CHECK-NEXT: i32.const $push0=, 1{{$}}
; CHECK-NEXT: {{^}} i32.call $push1=, _Znwm, $pop0{{$}}
; CHECK-NEXT: {{^}} i32.call $push2=, _ZN5AppleC1Ev, $pop1{{$}}
; CHECK-NEXT: {{^}} call $push1=, _Znwm, $pop0{{$}}
; CHECK-NEXT: {{^}} call $push2=, _ZN5AppleC1Ev, $pop1{{$}}
; CHECK-NEXT: return $pop2{{$}}
%class.Apple = type { i8 }
declare noalias i8* @_Znwm(i32)
@ -24,7 +24,7 @@ entry:
; CHECK-LABEL: _Z3barPvS_l:
; CHECK-NEXT: .functype _Z3barPvS_l (i32, i32, i32) -> (i32){{$}}
; CHECK-NEXT: {{^}} i32.call $push0=, memcpy, $0, $1, $2{{$}}
; CHECK-NEXT: {{^}} call $push0=, memcpy, $0, $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
declare i8* @memcpy(i8* returned, i8*, i32)
define i8* @_Z3barPvS_l(i8* %p, i8* %s, i32 %n) {
@ -37,7 +37,7 @@ entry:
; CHECK-LABEL: test_constant_arg:
; CHECK: i32.const $push0=, global{{$}}
; CHECK-NEXT: {{^}} i32.call $drop=, returns_arg, $pop0{{$}}
; CHECK-NEXT: {{^}} call $drop=, returns_arg, $pop0{{$}}
; CHECK-NEXT: return{{$}}
@global = external global i32
@addr = global i32* @global
@ -52,7 +52,7 @@ declare i32* @returns_arg(i32* returned)
; CHECK-LABEL: test_other_skipped:
; CHECK-NEXT: .functype test_other_skipped (i32, i32, f64) -> (){{$}}
; CHECK-NEXT: {{^}} i32.call $drop=, do_something, $0, $1, $2{{$}}
; CHECK-NEXT: {{^}} call $drop=, do_something, $0, $1, $2{{$}}
; CHECK-NEXT: {{^}} call do_something_with_i32, $1{{$}}
; CHECK-NEXT: {{^}} call do_something_with_double, $2{{$}}
declare i32 @do_something(i32 returned, i32, double)
@ -69,7 +69,7 @@ define void @test_other_skipped(i32 %a, i32 %b, double %c) {
; CHECK-LABEL: test_second_arg:
; CHECK-NEXT: .functype test_second_arg (i32, i32) -> (i32){{$}}
; CHECK-NEXT: {{^}} i32.call $push0=, do_something_else, $0, $1{{$}}
; CHECK-NEXT: {{^}} call $push0=, do_something_else, $0, $1{{$}}
; CHECK-NEXT: return $pop0{{$}}
declare i32 @do_something_else(i32, i32 returned)
define i32 @test_second_arg(i32 %a, i32 %b) {

View File

@ -12,7 +12,7 @@ define i32 @func_1(i16 %arg1 , i32 %arg2) #0 {
; CHECK-NEXT: i32.shl $push2=, $0, $pop1
; CHECK-NEXT: i32.const $push4=, 16
; CHECK-NEXT: i32.shr_s $push3=, $pop2, $pop4
; CHECK-NEXT: i32.call $push0=, get_int, $pop3
; CHECK-NEXT: call $push0=, get_int, $pop3
; CHECK-NEXT: end_function
entry:
%retval = call i32 @get_int(i16 signext %arg1)

View File

@ -406,7 +406,7 @@ define <4 x float> @copysign_v4f32(<4 x float> %x, <4 x float> %y) {
}
; CHECK-LABEL: sin_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, sinf
; CHECK: call $push[[L:[0-9]+]]=, sinf
declare <4 x float> @llvm.sin.v4f32(<4 x float>)
define <4 x float> @sin_v4f32(<4 x float> %x) {
%v = call <4 x float> @llvm.sin.v4f32(<4 x float> %x)
@ -414,7 +414,7 @@ define <4 x float> @sin_v4f32(<4 x float> %x) {
}
; CHECK-LABEL: cos_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, cosf
; CHECK: call $push[[L:[0-9]+]]=, cosf
declare <4 x float> @llvm.cos.v4f32(<4 x float>)
define <4 x float> @cos_v4f32(<4 x float> %x) {
%v = call <4 x float> @llvm.cos.v4f32(<4 x float> %x)
@ -422,7 +422,7 @@ define <4 x float> @cos_v4f32(<4 x float> %x) {
}
; CHECK-LABEL: powi_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, __powisf2
; CHECK: call $push[[L:[0-9]+]]=, __powisf2
declare <4 x float> @llvm.powi.v4f32(<4 x float>, i32)
define <4 x float> @powi_v4f32(<4 x float> %x, i32 %y) {
%v = call <4 x float> @llvm.powi.v4f32(<4 x float> %x, i32 %y)
@ -430,7 +430,7 @@ define <4 x float> @powi_v4f32(<4 x float> %x, i32 %y) {
}
; CHECK-LABEL: pow_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, powf
; CHECK: call $push[[L:[0-9]+]]=, powf
declare <4 x float> @llvm.pow.v4f32(<4 x float>, <4 x float>)
define <4 x float> @pow_v4f32(<4 x float> %x, <4 x float> %y) {
%v = call <4 x float> @llvm.pow.v4f32(<4 x float> %x, <4 x float> %y)
@ -438,7 +438,7 @@ define <4 x float> @pow_v4f32(<4 x float> %x, <4 x float> %y) {
}
; CHECK-LABEL: log_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, logf
; CHECK: call $push[[L:[0-9]+]]=, logf
declare <4 x float> @llvm.log.v4f32(<4 x float>)
define <4 x float> @log_v4f32(<4 x float> %x) {
%v = call <4 x float> @llvm.log.v4f32(<4 x float> %x)
@ -446,7 +446,7 @@ define <4 x float> @log_v4f32(<4 x float> %x) {
}
; CHECK-LABEL: log2_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, log2f
; CHECK: call $push[[L:[0-9]+]]=, log2f
declare <4 x float> @llvm.log2.v4f32(<4 x float>)
define <4 x float> @log2_v4f32(<4 x float> %x) {
%v = call <4 x float> @llvm.log2.v4f32(<4 x float> %x)
@ -454,7 +454,7 @@ define <4 x float> @log2_v4f32(<4 x float> %x) {
}
; CHECK-LABEL: log10_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, log10f
; CHECK: call $push[[L:[0-9]+]]=, log10f
declare <4 x float> @llvm.log10.v4f32(<4 x float>)
define <4 x float> @log10_v4f32(<4 x float> %x) {
%v = call <4 x float> @llvm.log10.v4f32(<4 x float> %x)
@ -462,7 +462,7 @@ define <4 x float> @log10_v4f32(<4 x float> %x) {
}
; CHECK-LABEL: exp_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, expf
; CHECK: call $push[[L:[0-9]+]]=, expf
declare <4 x float> @llvm.exp.v4f32(<4 x float>)
define <4 x float> @exp_v4f32(<4 x float> %x) {
%v = call <4 x float> @llvm.exp.v4f32(<4 x float> %x)
@ -470,7 +470,7 @@ define <4 x float> @exp_v4f32(<4 x float> %x) {
}
; CHECK-LABEL: exp2_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, exp2f
; CHECK: call $push[[L:[0-9]+]]=, exp2f
declare <4 x float> @llvm.exp2.v4f32(<4 x float>)
define <4 x float> @exp2_v4f32(<4 x float> %x) {
%v = call <4 x float> @llvm.exp2.v4f32(<4 x float> %x)
@ -486,7 +486,7 @@ define <4 x float> @rint_v4f32(<4 x float> %x) {
}
; CHECK-LABEL: round_v4f32:
; CHECK: f32.call $push[[L:[0-9]+]]=, roundf
; CHECK: call $push[[L:[0-9]+]]=, roundf
declare <4 x float> @llvm.round.v4f32(<4 x float>)
define <4 x float> @round_v4f32(<4 x float> %x) {
%v = call <4 x float> @llvm.round.v4f32(<4 x float> %x)
@ -538,7 +538,7 @@ define <2 x double> @copysign_v2f64(<2 x double> %x, <2 x double> %y) {
}
; CHECK-LABEL: sin_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, sin
; CHECK: call $push[[L:[0-9]+]]=, sin
declare <2 x double> @llvm.sin.v2f64(<2 x double>)
define <2 x double> @sin_v2f64(<2 x double> %x) {
%v = call <2 x double> @llvm.sin.v2f64(<2 x double> %x)
@ -546,7 +546,7 @@ define <2 x double> @sin_v2f64(<2 x double> %x) {
}
; CHECK-LABEL: cos_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, cos
; CHECK: call $push[[L:[0-9]+]]=, cos
declare <2 x double> @llvm.cos.v2f64(<2 x double>)
define <2 x double> @cos_v2f64(<2 x double> %x) {
%v = call <2 x double> @llvm.cos.v2f64(<2 x double> %x)
@ -554,7 +554,7 @@ define <2 x double> @cos_v2f64(<2 x double> %x) {
}
; CHECK-LABEL: powi_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, __powidf2
; CHECK: call $push[[L:[0-9]+]]=, __powidf2
declare <2 x double> @llvm.powi.v2f64(<2 x double>, i32)
define <2 x double> @powi_v2f64(<2 x double> %x, i32 %y) {
%v = call <2 x double> @llvm.powi.v2f64(<2 x double> %x, i32 %y)
@ -562,7 +562,7 @@ define <2 x double> @powi_v2f64(<2 x double> %x, i32 %y) {
}
; CHECK-LABEL: pow_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, pow
; CHECK: call $push[[L:[0-9]+]]=, pow
declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>)
define <2 x double> @pow_v2f64(<2 x double> %x, <2 x double> %y) {
%v = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> %y)
@ -570,7 +570,7 @@ define <2 x double> @pow_v2f64(<2 x double> %x, <2 x double> %y) {
}
; CHECK-LABEL: log_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, log
; CHECK: call $push[[L:[0-9]+]]=, log
declare <2 x double> @llvm.log.v2f64(<2 x double>)
define <2 x double> @log_v2f64(<2 x double> %x) {
%v = call <2 x double> @llvm.log.v2f64(<2 x double> %x)
@ -578,7 +578,7 @@ define <2 x double> @log_v2f64(<2 x double> %x) {
}
; CHECK-LABEL: log2_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, log2
; CHECK: call $push[[L:[0-9]+]]=, log2
declare <2 x double> @llvm.log2.v2f64(<2 x double>)
define <2 x double> @log2_v2f64(<2 x double> %x) {
%v = call <2 x double> @llvm.log2.v2f64(<2 x double> %x)
@ -586,7 +586,7 @@ define <2 x double> @log2_v2f64(<2 x double> %x) {
}
; CHECK-LABEL: log10_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, log10
; CHECK: call $push[[L:[0-9]+]]=, log10
declare <2 x double> @llvm.log10.v2f64(<2 x double>)
define <2 x double> @log10_v2f64(<2 x double> %x) {
%v = call <2 x double> @llvm.log10.v2f64(<2 x double> %x)
@ -594,7 +594,7 @@ define <2 x double> @log10_v2f64(<2 x double> %x) {
}
; CHECK-LABEL: exp_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, exp
; CHECK: call $push[[L:[0-9]+]]=, exp
declare <2 x double> @llvm.exp.v2f64(<2 x double>)
define <2 x double> @exp_v2f64(<2 x double> %x) {
%v = call <2 x double> @llvm.exp.v2f64(<2 x double> %x)
@ -602,7 +602,7 @@ define <2 x double> @exp_v2f64(<2 x double> %x) {
}
; CHECK-LABEL: exp2_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, exp2
; CHECK: call $push[[L:[0-9]+]]=, exp2
declare <2 x double> @llvm.exp2.v2f64(<2 x double>)
define <2 x double> @exp2_v2f64(<2 x double> %x) {
%v = call <2 x double> @llvm.exp2.v2f64(<2 x double> %x)
@ -618,7 +618,7 @@ define <2 x double> @rint_v2f64(<2 x double> %x) {
}
; CHECK-LABEL: round_v2f64:
; CHECK: f64.call $push[[L:[0-9]+]]=, round
; CHECK: call $push[[L:[0-9]+]]=, round
declare <2 x double> @llvm.round.v2f64(<2 x double>)
define <2 x double> @round_v2f64(<2 x double> %x) {
%v = call <2 x double> @llvm.round.v2f64(<2 x double> %x)

View File

@ -36,7 +36,7 @@ define void @recursive_tail_nullary() {
}
; CHECK-LABEL: recursive_notail:
; CHECK: i32.call $push[[L:[0-9]+]]=, recursive_notail, $0, $1{{$}}
; CHECK: call $push[[L:[0-9]+]]=, recursive_notail, $0, $1{{$}}
; CHECK-NEXT: return $pop[[L]]{{$}}
define i32 @recursive_notail(i32 %x, i32 %y) {
%v = notail call i32 @recursive_notail(i32 %x, i32 %y)
@ -52,7 +52,7 @@ define i32 @recursive_musttail(i32 %x, i32 %y) {
; CHECK-LABEL: recursive_tail:
; SLOW: return_call recursive_tail, $0, $1{{$}}
; FAST: i32.call $push[[L:[0-9]+]]=, recursive_tail, $0, $1{{$}}
; FAST: call $push[[L:[0-9]+]]=, recursive_tail, $0, $1{{$}}
; FAST-NEXT: return $pop[[L]]{{$}}
define i32 @recursive_tail(i32 %x, i32 %y) {
%v = tail call i32 @recursive_tail(i32 %x, i32 %y)
@ -60,7 +60,7 @@ define i32 @recursive_tail(i32 %x, i32 %y) {
}
; CHECK-LABEL: indirect_notail:
; CHECK: i32.call_indirect $push[[L:[0-9]+]]=, $0, $1, $2, $0{{$}}
; CHECK: call_indirect $push[[L:[0-9]+]]=, $0, $1, $2, $0{{$}}
; CHECK-NEXT: return $pop[[L]]{{$}}
define i32 @indirect_notail(%fn %f, i32 %x, i32 %y) {
%p = extractvalue %fn %f, 0
@ -85,7 +85,7 @@ define i32 @indirect_tail(%fn %f, i32 %x, i32 %y) {
}
; CHECK-LABEL: choice_notail:
; CHECK: i32.call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
; CHECK: call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
; CHECK-NEXT: return $pop[[L]]{{$}}
define i1 @choice_notail(i1 %x) {
%p = select i1 %x, i1 (i1)* @foo, i1 (i1)* @bar
@ -103,7 +103,7 @@ define i1 @choice_musttail(i1 %x) {
; CHECK-LABEL: choice_tail:
; SLOW: return_call_indirect , $0, $pop{{[0-9]+}}{{$}}
; FAST: i32.call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
; FAST: call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
; FAST: return $pop[[L]]{{$}}
define i1 @choice_tail(i1 %x) {
%p = select i1 %x, i1 (i1)* @foo, i1 (i1)* @bar
@ -117,7 +117,7 @@ define i1 @choice_tail(i1 %x) {
; CHECK-LABEL: mismatched_prototypes:
; SLOW: return_call baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; FAST: i32.call $push[[L:[0-9]+]]=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; FAST: call $push[[L:[0-9]+]]=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; FAST: return $pop[[L]]{{$}}
declare i32 @baz(i32, i32, i32)
define i32 @mismatched_prototypes() {
@ -126,7 +126,7 @@ define i32 @mismatched_prototypes() {
}
; CHECK-LABEL: mismatched_return_void:
; CHECK: i32.call $drop=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: call $drop=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: return{{$}}
define void @mismatched_return_void() {
%v = tail call i32 @baz(i32 0, i32 42, i32 6)
@ -134,7 +134,7 @@ define void @mismatched_return_void() {
}
; CHECK-LABEL: mismatched_return_f32:
; CHECK: i32.call $push[[L:[0-9]+]]=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: call $push[[L:[0-9]+]]=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK: f32.reinterpret_i32 $push[[L1:[0-9]+]]=, $pop[[L]]{{$}}
; CHECK: return $pop[[L1]]{{$}}
define float @mismatched_return_f32() {
@ -144,7 +144,7 @@ define float @mismatched_return_f32() {
}
; CHECK-LABEL: mismatched_indirect_void:
; CHECK: i32.call_indirect $drop=, $0, $1, $2, $0{{$}}
; CHECK: call_indirect $drop=, $0, $1, $2, $0{{$}}
; CHECK: return{{$}}
define void @mismatched_indirect_void(%fn %f, i32 %x, i32 %y) {
%p = extractvalue %fn %f, 0
@ -153,7 +153,7 @@ define void @mismatched_indirect_void(%fn %f, i32 %x, i32 %y) {
}
; CHECK-LABEL: mismatched_indirect_f32:
; CHECK: i32.call_indirect $push[[L:[0-9]+]]=, $0, $1, $2, $0{{$}}
; CHECK: call_indirect $push[[L:[0-9]+]]=, $0, $1, $2, $0{{$}}
; CHECK: f32.reinterpret_i32 $push[[L1:[0-9]+]]=, $pop[[L]]{{$}}
; CHECK: return $pop[[L1]]{{$}}
define float @mismatched_indirect_f32(%fn %f, i32 %x, i32 %y) {
@ -174,7 +174,7 @@ define i32 @mismatched_byval(i32* %x) {
; CHECK-LABEL: varargs:
; CHECK: i32.store
; CHECK: i32.call $0=, var, $1{{$}}
; CHECK: call $0=, var, $1{{$}}
; CHECK: return $0{{$}}
declare i32 @var(...)
define i32 @varargs(i32 %x) {
@ -185,7 +185,7 @@ define i32 @varargs(i32 %x) {
; Type transformations inhibit tail calls, even when they are nops
; CHECK-LABEL: mismatched_return_zext:
; CHECK: i32.call
; CHECK: call
define i32 @mismatched_return_zext() {
%v = tail call i1 @foo(i1 1)
%u = zext i1 %v to i32
@ -193,7 +193,7 @@ define i32 @mismatched_return_zext() {
}
; CHECK-LABEL: mismatched_return_sext:
; CHECK: i32.call
; CHECK: call
define i32 @mismatched_return_sext() {
%v = tail call i1 @foo(i1 1)
%u = sext i1 %v to i32
@ -201,7 +201,7 @@ define i32 @mismatched_return_sext() {
}
; CHECK-LABEL: mismatched_return_trunc:
; CHECK: i32.call
; CHECK: call
declare i32 @int()
define i1 @mismatched_return_trunc() {
%v = tail call i32 @int()
@ -212,7 +212,7 @@ define i1 @mismatched_return_trunc() {
; Stack-allocated arguments inhibit tail calls
; CHECK-LABEL: stack_arg:
; CHECK: i32.call
; CHECK: call
define i32 @stack_arg(i32* %x) {
%a = alloca i32
%v = tail call i32 @stack_arg(i32* %a)
@ -220,7 +220,7 @@ define i32 @stack_arg(i32* %x) {
}
; CHECK-LABEL: stack_arg_gep:
; CHECK: i32.call
; CHECK: call
define i32 @stack_arg_gep(i32* %x) {
%a = alloca { i32, i32 }
%p = getelementptr { i32, i32 }, { i32, i32 }* %a, i32 0, i32 1
@ -231,7 +231,7 @@ define i32 @stack_arg_gep(i32* %x) {
; CHECK-LABEL: stack_arg_cast:
; CHECK: global.get $push{{[0-9]+}}=, __stack_pointer
; CHECK: global.set __stack_pointer, $pop{{[0-9]+}}
; FAST: i32.call ${{[0-9]+}}=, stack_arg_cast, $pop{{[0-9]+}}
; FAST: call ${{[0-9]+}}=, stack_arg_cast, $pop{{[0-9]+}}
; CHECK: global.set __stack_pointer, $pop{{[0-9]+}}
; SLOW: return_call stack_arg_cast, ${{[0-9]+}}
define i32 @stack_arg_cast(i32 %x) {

View File

@ -11,10 +11,10 @@ declare i32 @has_ptr_arg(i8*)
; CHECK-LABEL: test_invalid_rtn:
; CHECK: i32.const $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: i32.call $push[[L1:[0-9]+]]=, .Lhas_i64_arg_bitcast_invalid.2, $pop[[L0]]{{$}}
; CHECK-NEXT: call $push[[L1:[0-9]+]]=, .Lhas_i64_arg_bitcast_invalid.2, $pop[[L0]]{{$}}
; CHECK-NEXT: drop $pop[[L1]]{{$}}
; CHECK-NEXT: i64.const $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: i64.call $push[[L1:[0-9]+]]=, .Lhas_i64_arg_bitcast_invalid, $pop[[L0]]{{$}}
; CHECK-NEXT: call $push[[L1:[0-9]+]]=, .Lhas_i64_arg_bitcast_invalid, $pop[[L0]]{{$}}
; CHECK-NEXT: drop $pop[[L1]]{{$}}
; CHECK-NEXT: end_function
define void @test_invalid_rtn() {
@ -33,13 +33,13 @@ define void @test_struct_rtn() {
; CHECK-LABEL: test_invalid_arg:
; CHECK: i32.const $push[[L0:[0-9]+]]=, 2{{$}}
; CHECK-NEXT: i32.call $push[[L1:[0-9]+]]=, .Lhas_ptr_arg_bitcast_invalid.4, $pop[[L0]]{{$}}
; CHECK-NEXT: call $push[[L1:[0-9]+]]=, .Lhas_ptr_arg_bitcast_invalid.4, $pop[[L0]]{{$}}
; CHECK-NEXT: drop $pop[[L1]]{{$}}
; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 2{{$}}
; CHECK-NEXT: i32.call $push[[L1:[0-9]+]]=, has_ptr_arg, $pop[[L0]]{{$}}
; CHECK-NEXT: call $push[[L1:[0-9]+]]=, has_ptr_arg, $pop[[L0]]{{$}}
; CHECK-NEXT: drop $pop[[L1]]{{$}}
; CHECK-NEXT: i64.const $push[[L0:[0-9]+]]=, 3{{$}}
; CHECK-NEXT: i32.call $push[[L1:[0-9]+]]=, .Lhas_ptr_arg_bitcast_invalid, $pop[[L0]]{{$}}
; CHECK-NEXT: call $push[[L1:[0-9]+]]=, .Lhas_ptr_arg_bitcast_invalid, $pop[[L0]]{{$}}
; CHECK-NEXT: drop $pop[[L1]]{{$}}
; CHECK-NEXT: end_function
define void @test_invalid_arg() {

View File

@ -20,7 +20,7 @@ define i32 @unused_second(i32 %x, i32 %y) {
}
; CHECK-LABEL: call_something:
; CHECK: {{^}} i32.call $drop=, return_something{{$}}
; CHECK: {{^}} call $drop=, return_something{{$}}
; CHECK-NEXT: return{{$}}
declare i32 @return_something()
define void @call_something() {

View File

@ -4,14 +4,14 @@
# CHECK: bb.0:
# CHECK: %[[REG1:[0-9]+]]:i32 = CONST_I32 0,
# CHECK-NEXT: DBG_VALUE %[[REG1]],
# CHECK-NEXT: CALL_VOID @foo, %[[REG1]],
# CHECK-NEXT: CALL @foo, %[[REG1]],
# CHECK: bb.1:
# CHECK: %[[REG2:[0-9]+]]:i32 = CONST_I32 0,
# CHECK-NEXT: DBG_VALUE %[[REG2]],
# CHECK-NEXT: CALL_VOID @foo, %[[REG2]],
# CHECK-NEXT: CALL @foo, %[[REG2]],
# CHECK: %[[REG3:[0-9]+]]:i32 = CONST_I32 0,
# CHECK-NEXT: DBG_VALUE %[[REG3]],
# CHECK-NEXT: CALL_VOID @foo, %[[REG3]],
# CHECK-NEXT: CALL @foo, %[[REG3]],
--- |
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
@ -55,11 +55,11 @@ body: |
%0:i64 = ARGUMENT_i64 0, implicit $arguments
%1:i32 = CONST_I32 0, implicit-def dead $arguments
DBG_VALUE %1:i32, $noreg, !10, !DIExpression(), debug-location !13; <unknown>:357:12 line no:357
CALL_VOID @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
CALL @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
bb.1:
CALL_VOID @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
CALL_VOID @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
CALL @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
CALL @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
RETURN implicit-def dead $arguments
...

View File

@ -3,11 +3,11 @@
# CHECK: body:
# CHECK: dead %3:i32 = I32_WRAP_I64 %0,
# CHECK-NEXT: DBG_VALUE %1:i32
# CHECK-NEXT: dead %2:i32 = CALL_i32 @bar,
# CHECK-NEXT: dead %2:i32 = CALL @bar,
# CHECK-NEXT: DBG_VALUE %1:i32,
# CHECK-NEXT: %[[NEWREG:.*]]:i32 = CALL_i32 @bar,
# CHECK-NEXT: %[[NEWREG:.*]]:i32 = CALL @bar,
# CHECK-NEXT: DBG_VALUE %[[NEWREG]],
# CHECK-NEXT: CALL_VOID @foo, %[[NEWREG]],
# CHECK-NEXT: CALL @foo, %[[NEWREG]],
--- |
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
@ -50,11 +50,11 @@ body: |
%0:i64 = ARGUMENT_i64 0, implicit $arguments
%1:i32 = I32_WRAP_I64 %0:i64, implicit-def dead $arguments
DBG_VALUE %1:i32, $noreg, !10, !DIExpression(), debug-location !13; <unknown>:357:12 line no:357
%1:i32 = CALL_i32 @bar, implicit-def dead $arguments, implicit $sp32, implicit $sp64
%1:i32 = CALL @bar, implicit-def dead $arguments, implicit $sp32, implicit $sp64
DBG_VALUE %1:i32, $noreg, !11, !DIExpression(), debug-location !14; <unknown>:357:12 line no:357
%1:i32 = CALL_i32 @bar, implicit-def dead $arguments, implicit $sp32, implicit $sp64
%1:i32 = CALL @bar, implicit-def dead $arguments, implicit $sp32, implicit $sp64
DBG_VALUE %1:i32, $noreg, !12, !DIExpression(), debug-location !15; <unknown>:357:12 line no:357
CALL_VOID @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
CALL @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
RETURN implicit-def dead $arguments
...

View File

@ -37,7 +37,7 @@ test0:
loop i32 # label1:
call something1
i64.const 1234
i32.call something2
call something2
i32.const 0
call_indirect (i32, f64) -> ()
i32.const 1
@ -150,7 +150,7 @@ test0:
# CHECK-NEXT: loop i32 # label1:
# CHECK-NEXT: call something1
# CHECK-NEXT: i64.const 1234
# CHECK-NEXT: i32.call something2
# CHECK-NEXT: call something2
# CHECK-NEXT: i32.const 0
# CHECK-NEXT: call_indirect (i32, f64) -> ()
# CHECK-NEXT: i32.const 1

View File

@ -1,4 +1,4 @@
; RUN: llc -filetype=obj -wasm-keep-registers %s -o - | llvm-readobj -r --expand-relocs | FileCheck %s
; RUN: llc -filetype=obj %s -o - | llvm-readobj -r --expand-relocs | FileCheck %s
target triple = "wasm32-unknown-unknown"

View File

@ -16,14 +16,14 @@ call_direct:
.hidden call_direct
.globl call_direct
.functype call_direct () -> (i32)
i32.call foo
call foo
end_function
call_alias:
.hidden call_alias
.globl call_alias
.functype call_alias () -> (i32)
i32.call foo_alias
call foo_alias
end_function
call_direct_ptr: