mirror of
https://github.com/RPCSX/llvm.git
synced 2025-04-03 08:41:44 +00:00
[WebAssemby] Implement block signatures.
Per spec changes, this implements block signatures, and adds just enough logic to produce correct block signatures at the ends of functions. Differential Revision: https://reviews.llvm.org/D25144 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283503 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d8d953ef76
commit
12bd3d1963
@ -195,6 +195,26 @@ WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI,
|
||||
O << ":p2align=" << Imm;
|
||||
}
|
||||
|
||||
void
|
||||
WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,
|
||||
unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
int64_t Imm = MI->getOperand(OpNo).getImm();
|
||||
switch (Imm) {
|
||||
case WebAssembly::Void: break;
|
||||
case WebAssembly::I32: O << "i32"; break;
|
||||
case WebAssembly::I64: O << "i64"; break;
|
||||
case WebAssembly::F32: O << "f32"; break;
|
||||
case WebAssembly::F64: O << "f64"; break;
|
||||
case WebAssembly::I8x16: O << "i8x16"; break;
|
||||
case WebAssembly::I16x8: O << "i16x8"; break;
|
||||
case WebAssembly::I32x4: O << "i32x4"; break;
|
||||
case WebAssembly::I64x2: O << "i32x4"; break;
|
||||
case WebAssembly::F32x4: O << "f32x4"; break;
|
||||
case WebAssembly::F64x2: O << "f64x2"; break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *llvm::WebAssembly::TypeToString(MVT Ty) {
|
||||
switch (Ty.SimpleTy) {
|
||||
case MVT::i32:
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||
void printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O);
|
||||
void printWebAssemblySignatureOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O);
|
||||
|
||||
// Autogenerated by tblgen.
|
||||
void printInstruction(const MCInst *MI, raw_ostream &O);
|
||||
|
@ -53,7 +53,9 @@ enum OperandType {
|
||||
/// 64-bit floating-point immediates.
|
||||
OPERAND_F64IMM,
|
||||
/// p2align immediate for load and store address alignment.
|
||||
OPERAND_P2ALIGN
|
||||
OPERAND_P2ALIGN,
|
||||
/// signature immediate for block/loop.
|
||||
OPERAND_SIGNATURE
|
||||
};
|
||||
|
||||
/// WebAssembly-specific directive identifiers.
|
||||
@ -63,7 +65,7 @@ enum Directive {
|
||||
DotResult = UINT64_MAX - 1, ///< .result
|
||||
DotLocal = UINT64_MAX - 2, ///< .local
|
||||
DotEndFunc = UINT64_MAX - 3, ///< .endfunc
|
||||
DotIndIdx = UINT64_MAX - 4, /// < .indidx
|
||||
DotIndIdx = UINT64_MAX - 4, ///< .indidx
|
||||
};
|
||||
|
||||
} // end namespace WebAssembly
|
||||
@ -141,6 +143,21 @@ static const unsigned StoreAddressOperandNo = 1;
|
||||
static const unsigned LoadP2AlignOperandNo = 3;
|
||||
static const unsigned StoreP2AlignOperandNo = 2;
|
||||
|
||||
/// This is used to indicate block signatures.
|
||||
enum ExprType {
|
||||
Void = 0,
|
||||
I32 = 1,
|
||||
I64 = 2,
|
||||
F32 = 3,
|
||||
F64 = 4,
|
||||
I8x16 = 5,
|
||||
I16x8 = 6,
|
||||
I32x4 = 7,
|
||||
I64x2 = 8,
|
||||
F32x4 = 9,
|
||||
F64x2 = 10
|
||||
};
|
||||
|
||||
} // end namespace WebAssembly
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -65,14 +65,17 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
|
||||
void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
|
||||
|
||||
void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
|
||||
StringRef name, SmallVectorImpl<MVT> &SignatureVTs, size_t NumResults) {
|
||||
StringRef name, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) {
|
||||
OS << "\t.functype\t" << name;
|
||||
if (NumResults == 0)
|
||||
if (Results.empty())
|
||||
OS << ", void";
|
||||
for (auto Ty : SignatureVTs) {
|
||||
OS << ", " << WebAssembly::TypeToString(Ty);
|
||||
else {
|
||||
assert(Results.size() == 1);
|
||||
OS << ", " << WebAssembly::TypeToString(Results.front());
|
||||
}
|
||||
OS << "\n";
|
||||
for (auto Ty : Params)
|
||||
OS << ", " << WebAssembly::TypeToString(Ty);
|
||||
OS << '\n';
|
||||
}
|
||||
|
||||
void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {
|
||||
|
@ -39,8 +39,8 @@ public:
|
||||
virtual void emitEndFunc() = 0;
|
||||
/// .functype
|
||||
virtual void emitIndirectFunctionType(StringRef name,
|
||||
SmallVectorImpl<MVT> &SignatureVTs,
|
||||
size_t NumResults) {
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
SmallVectorImpl<MVT> &Results) {
|
||||
llvm_unreachable("emitIndirectFunctionType not implemented");
|
||||
}
|
||||
/// .indidx
|
||||
@ -59,8 +59,8 @@ public:
|
||||
void emitLocal(ArrayRef<MVT> Types) override;
|
||||
void emitEndFunc() override;
|
||||
void emitIndirectFunctionType(StringRef name,
|
||||
SmallVectorImpl<MVT> &SignatureVTs,
|
||||
size_t NumResults) override;
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
SmallVectorImpl<MVT> &Results) override;
|
||||
void emitIndIdx(const MCExpr *Value) override;
|
||||
};
|
||||
|
||||
|
@ -121,45 +121,16 @@ WebAssemblyTargetStreamer *WebAssemblyAsmPrinter::getTargetStreamer() {
|
||||
//===----------------------------------------------------------------------===//
|
||||
// WebAssemblyAsmPrinter Implementation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
static void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM,
|
||||
Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
|
||||
const DataLayout &DL(F.getParent()->getDataLayout());
|
||||
const WebAssemblyTargetLowering &TLI =
|
||||
*TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
|
||||
SmallVector<EVT, 4> VTs;
|
||||
ComputeValueVTs(TLI, DL, Ty, VTs);
|
||||
|
||||
for (EVT VT : VTs) {
|
||||
unsigned NumRegs = TLI.getNumRegisters(F.getContext(), VT);
|
||||
MVT RegisterVT = TLI.getRegisterType(F.getContext(), VT);
|
||||
for (unsigned i = 0; i != NumRegs; ++i)
|
||||
ValueVTs.push_back(RegisterVT);
|
||||
}
|
||||
}
|
||||
|
||||
void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
|
||||
for (const auto &F : M) {
|
||||
// Emit function type info for all undefined functions
|
||||
if (F.isDeclarationForLinker() && !F.isIntrinsic()) {
|
||||
SmallVector<MVT, 4> SignatureVTs;
|
||||
ComputeLegalValueVTs(F, TM, F.getReturnType(), SignatureVTs);
|
||||
size_t NumResults = SignatureVTs.size();
|
||||
if (SignatureVTs.size() > 1) {
|
||||
// WebAssembly currently can't lower returns of multiple values without
|
||||
// demoting to sret (see WebAssemblyTargetLowering::CanLowerReturn). So
|
||||
// replace multiple return values with a pointer parameter.
|
||||
SignatureVTs.clear();
|
||||
SignatureVTs.push_back(
|
||||
MVT::getIntegerVT(M.getDataLayout().getPointerSizeInBits()));
|
||||
NumResults = 0;
|
||||
}
|
||||
|
||||
for (auto &Arg : F.args()) {
|
||||
ComputeLegalValueVTs(F, TM, Arg.getType(), SignatureVTs);
|
||||
}
|
||||
|
||||
getTargetStreamer()->emitIndirectFunctionType(F.getName(), SignatureVTs,
|
||||
NumResults);
|
||||
SmallVector<MVT, 4> Results;
|
||||
SmallVector<MVT, 4> Params;
|
||||
ComputeSignatureVTs(F, TM, Params, Results);
|
||||
getTargetStreamer()->emitIndirectFunctionType(F.getName(), Params,
|
||||
Results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +309,8 @@ static bool IsChild(const MachineInstr &MI,
|
||||
static void PlaceBlockMarker(
|
||||
MachineBasicBlock &MBB, MachineFunction &MF,
|
||||
SmallVectorImpl<MachineBasicBlock *> &ScopeTops,
|
||||
DenseMap<const MachineInstr *, const MachineBasicBlock *> &LoopTops,
|
||||
DenseMap<const MachineInstr *, MachineInstr *> &BlockTops,
|
||||
DenseMap<const MachineInstr *, MachineInstr *> &LoopTops,
|
||||
const WebAssemblyInstrInfo &TII,
|
||||
const MachineLoopInfo &MLI,
|
||||
MachineDominatorTree &MDT,
|
||||
@ -372,15 +373,19 @@ static void PlaceBlockMarker(
|
||||
}
|
||||
|
||||
// Add the BLOCK.
|
||||
BuildMI(*Header, InsertPos, DebugLoc(), TII.get(WebAssembly::BLOCK));
|
||||
MachineInstr *Begin = BuildMI(*Header, InsertPos, DebugLoc(),
|
||||
TII.get(WebAssembly::BLOCK))
|
||||
.addImm(WebAssembly::Void);
|
||||
|
||||
// Mark the end of the block.
|
||||
InsertPos = MBB.begin();
|
||||
while (InsertPos != MBB.end() &&
|
||||
InsertPos->getOpcode() == WebAssembly::END_LOOP &&
|
||||
LoopTops[&*InsertPos]->getNumber() >= Header->getNumber())
|
||||
LoopTops[&*InsertPos]->getParent()->getNumber() >= Header->getNumber())
|
||||
++InsertPos;
|
||||
BuildMI(MBB, InsertPos, DebugLoc(), TII.get(WebAssembly::END_BLOCK));
|
||||
MachineInstr *End = BuildMI(MBB, InsertPos, DebugLoc(),
|
||||
TII.get(WebAssembly::END_BLOCK));
|
||||
BlockTops[End] = Begin;
|
||||
|
||||
// Track the farthest-spanning scope that ends at this point.
|
||||
int Number = MBB.getNumber();
|
||||
@ -393,7 +398,7 @@ static void PlaceBlockMarker(
|
||||
static void PlaceLoopMarker(
|
||||
MachineBasicBlock &MBB, MachineFunction &MF,
|
||||
SmallVectorImpl<MachineBasicBlock *> &ScopeTops,
|
||||
DenseMap<const MachineInstr *, const MachineBasicBlock *> &LoopTops,
|
||||
DenseMap<const MachineInstr *, MachineInstr *> &LoopTops,
|
||||
const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI) {
|
||||
MachineLoop *Loop = MLI.getLoopFor(&MBB);
|
||||
if (!Loop || Loop->getHeader() != &MBB)
|
||||
@ -418,12 +423,14 @@ static void PlaceLoopMarker(
|
||||
while (InsertPos != MBB.end() &&
|
||||
InsertPos->getOpcode() == WebAssembly::END_LOOP)
|
||||
++InsertPos;
|
||||
BuildMI(MBB, InsertPos, DebugLoc(), TII.get(WebAssembly::LOOP));
|
||||
MachineInstr *Begin = BuildMI(MBB, InsertPos, DebugLoc(),
|
||||
TII.get(WebAssembly::LOOP))
|
||||
.addImm(WebAssembly::Void);
|
||||
|
||||
// Mark the end of the loop.
|
||||
MachineInstr *End = BuildMI(*AfterLoop, AfterLoop->begin(), DebugLoc(),
|
||||
TII.get(WebAssembly::END_LOOP));
|
||||
LoopTops[End] = &MBB;
|
||||
LoopTops[End] = Begin;
|
||||
|
||||
assert((!ScopeTops[AfterLoop->getNumber()] ||
|
||||
ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
|
||||
@ -445,6 +452,56 @@ GetDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack,
|
||||
return Depth;
|
||||
}
|
||||
|
||||
/// In normal assembly languages, when the end of a function is unreachable,
|
||||
/// because the function ends in an infinite loop or a noreturn call or similar,
|
||||
/// it isn't necessary to worry about the function return type at the end of
|
||||
/// the function, because it's never reached. However, in WebAssembly, blocks
|
||||
/// that end at the function end need to have a return type signature that
|
||||
/// matches the function signature, even though it's unreachable. This function
|
||||
/// checks for such cases and fixes up the signatures.
|
||||
static void FixEndsAtEndOfFunction(
|
||||
MachineFunction &MF,
|
||||
const WebAssemblyFunctionInfo &MFI,
|
||||
DenseMap<const MachineInstr *, MachineInstr *> &BlockTops,
|
||||
DenseMap<const MachineInstr *, MachineInstr *> &LoopTops) {
|
||||
assert(MFI.getResults().size() <= 1);
|
||||
|
||||
if (MFI.getResults().empty())
|
||||
return;
|
||||
|
||||
WebAssembly::ExprType retType;
|
||||
switch (MFI.getResults().front().SimpleTy) {
|
||||
case MVT::i32: retType = WebAssembly::I32; break;
|
||||
case MVT::i64: retType = WebAssembly::I64; break;
|
||||
case MVT::f32: retType = WebAssembly::F32; break;
|
||||
case MVT::f64: retType = WebAssembly::F64; break;
|
||||
case MVT::v16i8: retType = WebAssembly::I8x16; break;
|
||||
case MVT::v8i16: retType = WebAssembly::I16x8; break;
|
||||
case MVT::v4i32: retType = WebAssembly::I32x4; break;
|
||||
case MVT::v2i64: retType = WebAssembly::I64x2; break;
|
||||
case MVT::v4f32: retType = WebAssembly::F32x4; break;
|
||||
case MVT::v2f64: retType = WebAssembly::F64x2; break;
|
||||
default: llvm_unreachable("unexpected return type");
|
||||
}
|
||||
|
||||
for (MachineBasicBlock &MBB : reverse(MF)) {
|
||||
for (MachineInstr &MI : reverse(MBB)) {
|
||||
if (MI.isPosition() || MI.isDebugValue())
|
||||
continue;
|
||||
if (MI.getOpcode() == WebAssembly::END_BLOCK) {
|
||||
BlockTops[&MI]->getOperand(0).setImm(int32_t(retType));
|
||||
continue;
|
||||
}
|
||||
if (MI.getOpcode() == WebAssembly::END_LOOP) {
|
||||
LoopTops[&MI]->getOperand(0).setImm(int32_t(retType));
|
||||
continue;
|
||||
}
|
||||
// Something other than an `end`. We're done.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert LOOP and BLOCK markers at appropriate places.
|
||||
static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
|
||||
const WebAssemblyInstrInfo &TII,
|
||||
@ -457,15 +514,18 @@ static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
|
||||
// we may insert at the end.
|
||||
SmallVector<MachineBasicBlock *, 8> ScopeTops(MF.getNumBlockIDs() + 1);
|
||||
|
||||
// For eacn LOOP_END, the corresponding LOOP.
|
||||
DenseMap<const MachineInstr *, const MachineBasicBlock *> LoopTops;
|
||||
// For each LOOP_END, the corresponding LOOP.
|
||||
DenseMap<const MachineInstr *, MachineInstr *> LoopTops;
|
||||
|
||||
// For each END_BLOCK, the corresponding BLOCK.
|
||||
DenseMap<const MachineInstr *, MachineInstr *> BlockTops;
|
||||
|
||||
for (auto &MBB : MF) {
|
||||
// Place the LOOP for MBB if MBB is the header of a loop.
|
||||
PlaceLoopMarker(MBB, MF, ScopeTops, LoopTops, TII, MLI);
|
||||
|
||||
// Place the BLOCK for MBB if MBB is branched to from above.
|
||||
PlaceBlockMarker(MBB, MF, ScopeTops, LoopTops, TII, MLI, MDT, MFI);
|
||||
PlaceBlockMarker(MBB, MF, ScopeTops, BlockTops, LoopTops, TII, MLI, MDT, MFI);
|
||||
}
|
||||
|
||||
// Now rewrite references to basic blocks to be depth immediates.
|
||||
@ -486,7 +546,7 @@ static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
|
||||
Stack.push_back(&MBB);
|
||||
break;
|
||||
case WebAssembly::END_LOOP:
|
||||
Stack.push_back(LoopTops[&MI]);
|
||||
Stack.push_back(LoopTops[&MI]->getParent());
|
||||
break;
|
||||
default:
|
||||
if (MI.isTerminator()) {
|
||||
@ -505,6 +565,10 @@ static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI,
|
||||
}
|
||||
}
|
||||
assert(Stack.empty() && "Control flow should be balanced");
|
||||
|
||||
// Fix up block/loop signatures at the end of the function to conform to
|
||||
// WebAssembly's rules.
|
||||
FixEndsAtEndOfFunction(MF, MFI, BlockTops, LoopTops);
|
||||
}
|
||||
|
||||
bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
|
||||
|
@ -481,12 +481,12 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments(
|
||||
SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
|
||||
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
|
||||
|
||||
if (!CallingConvSupported(CallConv))
|
||||
fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
|
||||
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
|
||||
|
||||
// Set up the incoming ARGUMENTS value, which serves to represent the liveness
|
||||
// of the incoming values before they're represented by virtual registers.
|
||||
MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
|
||||
@ -526,6 +526,13 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments(
|
||||
MFI->addParam(PtrVT);
|
||||
}
|
||||
|
||||
// Record the number and types of results.
|
||||
SmallVector<MVT, 4> Params;
|
||||
SmallVector<MVT, 4> Results;
|
||||
ComputeSignatureVTs(*MF.getFunction(), DAG.getTarget(), Params, Results);
|
||||
for (MVT VT : Results)
|
||||
MFI->addResult(VT);
|
||||
|
||||
return Chain;
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,8 @@ def BR_TABLE_I64 : I<(outs), (ins I64:$index, variable_ops),
|
||||
// use/clobber VALUE_STACK to prevent them from being moved into the middle of
|
||||
// an expression tree.
|
||||
let Uses = [VALUE_STACK], Defs = [VALUE_STACK] in {
|
||||
def BLOCK : I<(outs), (ins), [], "block", 0x01>;
|
||||
def LOOP : I<(outs), (ins), [], "loop", 0x02>;
|
||||
def BLOCK : I<(outs), (ins Signature:$sig), [], "block \t$sig", 0x01>;
|
||||
def LOOP : I<(outs), (ins Signature:$sig), [], "loop \t$sig", 0x02>;
|
||||
def END_BLOCK : I<(outs), (ins), [], "end_block">;
|
||||
def END_LOOP : I<(outs), (ins), [], "end_loop">;
|
||||
} // Uses = [VALUE_STACK], Defs = [VALUE_STACK]
|
||||
|
@ -89,6 +89,12 @@ def P2Align : Operand<i32> {
|
||||
}
|
||||
} // OperandType = "OPERAND_P2ALIGN"
|
||||
|
||||
let OperandType = "OPERAND_SIGNATURE" in {
|
||||
def Signature : Operand<i32> {
|
||||
let PrintMethod = "printWebAssemblySignatureOperand";
|
||||
}
|
||||
} // OperandType = "OPERAND_SIGNATURE"
|
||||
|
||||
} // OperandNamespace = "WebAssembly"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -14,6 +14,9 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "WebAssemblyMachineFunctionInfo.h"
|
||||
#include "WebAssemblyISelLowering.h"
|
||||
#include "WebAssemblySubtarget.h"
|
||||
#include "llvm/CodeGen/Analysis.h"
|
||||
using namespace llvm;
|
||||
|
||||
WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() {}
|
||||
@ -23,3 +26,37 @@ void WebAssemblyFunctionInfo::initWARegs() {
|
||||
unsigned Reg = UnusedReg;
|
||||
WARegs.resize(MF.getRegInfo().getNumVirtRegs(), Reg);
|
||||
}
|
||||
|
||||
void llvm::ComputeLegalValueVTs(const Function &F, const TargetMachine &TM,
|
||||
Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
|
||||
const DataLayout &DL(F.getParent()->getDataLayout());
|
||||
const WebAssemblyTargetLowering &TLI =
|
||||
*TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
|
||||
SmallVector<EVT, 4> VTs;
|
||||
ComputeValueVTs(TLI, DL, Ty, VTs);
|
||||
|
||||
for (EVT VT : VTs) {
|
||||
unsigned NumRegs = TLI.getNumRegisters(F.getContext(), VT);
|
||||
MVT RegisterVT = TLI.getRegisterType(F.getContext(), VT);
|
||||
for (unsigned i = 0; i != NumRegs; ++i)
|
||||
ValueVTs.push_back(RegisterVT);
|
||||
}
|
||||
}
|
||||
|
||||
void llvm::ComputeSignatureVTs(const Function &F, const TargetMachine &TM,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
SmallVectorImpl<MVT> &Results) {
|
||||
ComputeLegalValueVTs(F, TM, F.getReturnType(), Results);
|
||||
|
||||
if (Results.size() > 1) {
|
||||
// WebAssembly currently can't lower returns of multiple values without
|
||||
// demoting to sret (see WebAssemblyTargetLowering::CanLowerReturn). So
|
||||
// replace multiple return values with a pointer parameter.
|
||||
Results.clear();
|
||||
Params.push_back(
|
||||
MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits()));
|
||||
}
|
||||
|
||||
for (auto &Arg : F.args())
|
||||
ComputeLegalValueVTs(F, TM, Arg.getType(), Params);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
|
||||
MachineFunction &MF;
|
||||
|
||||
std::vector<MVT> Params;
|
||||
std::vector<MVT> Results;
|
||||
|
||||
/// A mapping from CodeGen vreg index to WebAssembly register number.
|
||||
std::vector<unsigned> WARegs;
|
||||
@ -51,6 +52,9 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
|
||||
void addParam(MVT VT) { Params.push_back(VT); }
|
||||
const std::vector<MVT> &getParams() const { return Params; }
|
||||
|
||||
void addResult(MVT VT) { Results.push_back(VT); }
|
||||
const std::vector<MVT> &getResults() const { return Results; }
|
||||
|
||||
unsigned getVarargBufferVreg() const {
|
||||
assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
|
||||
return VarargVreg;
|
||||
@ -88,6 +92,13 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
|
||||
}
|
||||
};
|
||||
|
||||
void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM,
|
||||
Type *Ty, SmallVectorImpl<MVT> &ValueVTs);
|
||||
|
||||
void ComputeSignatureVTs(const Function &F, const TargetMachine &TM,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
SmallVectorImpl<MVT> &Results);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -105,7 +105,7 @@ back:
|
||||
|
||||
; CHECK-LABEL: test2:
|
||||
; CHECK-NOT: local
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK: .LBB2_{{[0-9]+}}:
|
||||
; CHECK: loop
|
||||
@ -116,7 +116,7 @@ back:
|
||||
; CHECK: return{{$}}
|
||||
; OPT-LABEL: test2:
|
||||
; OPT-NOT: local
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT: .LBB2_{{[0-9]+}}:
|
||||
; OPT: loop
|
||||
@ -151,13 +151,13 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: doublediamond:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK: br_if 0, ${{[^,]+}}{{$}}
|
||||
; CHECK: br 1{{$}}
|
||||
; CHECK: .LBB3_2:
|
||||
; CHECK-NEXT: end_block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, ${{[^,]+}}{{$}}
|
||||
; CHECK: br 1{{$}}
|
||||
; CHECK: .LBB3_4:
|
||||
@ -167,9 +167,9 @@ for.end:
|
||||
; CHECK: i32.const $push{{[0-9]+}}=, 0{{$}}
|
||||
; CHECK-NEXT: return $pop{{[0-9]+}}{{$}}
|
||||
; OPT-LABEL: doublediamond:
|
||||
; OPT: block{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT: br_if 0, ${{[^,]+}}{{$}}
|
||||
; OPT: br_if 1, ${{[^,]+}}{{$}}
|
||||
; OPT: br 2{{$}}
|
||||
@ -204,12 +204,12 @@ exit:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: triangle:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, $1{{$}}
|
||||
; CHECK: .LBB4_2:
|
||||
; CHECK: return
|
||||
; OPT-LABEL: triangle:
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, $1{{$}}
|
||||
; OPT: .LBB4_2:
|
||||
; OPT: return
|
||||
@ -227,8 +227,8 @@ exit:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: diamond:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, $1{{$}}
|
||||
; CHECK: br 1{{$}}
|
||||
; CHECK: .LBB5_2:
|
||||
@ -236,8 +236,8 @@ exit:
|
||||
; CHECK: i32.const $push{{[0-9]+}}=, 0{{$}}
|
||||
; CHECK-NEXT: return $pop{{[0-9]+}}{{$}}
|
||||
; OPT-LABEL: diamond:
|
||||
; OPT: block{{$}}
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT: br 1{{$}}
|
||||
; OPT: .LBB5_2:
|
||||
@ -275,16 +275,18 @@ entry:
|
||||
; CHECK-LABEL: minimal_loop:
|
||||
; CHECK-NOT: br
|
||||
; CHECK: .LBB7_1:
|
||||
; CHECK: loop i32
|
||||
; CHECK: i32.store 0($0), $pop{{[0-9]+}}{{$}}
|
||||
; CHECK: br 0{{$}}
|
||||
; CHECK: .LBB7_2:
|
||||
; OPT-LABEL: minimal_loop:
|
||||
; OPT-NOT: br
|
||||
; OPT: .LBB7_1:
|
||||
; OPT: loop i32
|
||||
; OPT: i32.store 0($0), $pop{{[0-9]+}}{{$}}
|
||||
; OPT: br 0{{$}}
|
||||
; OPT: .LBB7_2:
|
||||
define void @minimal_loop(i32* %p) {
|
||||
define i32 @minimal_loop(i32* %p) {
|
||||
entry:
|
||||
store volatile i32 0, i32* %p
|
||||
br label %loop
|
||||
@ -296,7 +298,7 @@ loop:
|
||||
; CHECK-LABEL: simple_loop:
|
||||
; CHECK-NOT: br
|
||||
; CHECK: .LBB8_1:
|
||||
; CHECK: loop{{$}}
|
||||
; CHECK: loop {{$}}
|
||||
; CHECK: br_if 0, $pop{{[0-9]+}}{{$}}
|
||||
; CHECK-NEXT: end_loop{{$}}
|
||||
; CHECK: i32.const $push{{[0-9]+}}=, 0{{$}}
|
||||
@ -304,7 +306,7 @@ loop:
|
||||
; OPT-LABEL: simple_loop:
|
||||
; OPT-NOT: br
|
||||
; OPT: .LBB8_1:
|
||||
; OPT: loop{{$}}
|
||||
; OPT: loop {{$}}
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT-NEXT: end_loop{{$}}
|
||||
; OPT: i32.const $push{{[0-9]+}}=, 0{{$}}
|
||||
@ -323,17 +325,17 @@ exit:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: doubletriangle:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, $0{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, $1{{$}}
|
||||
; CHECK: .LBB9_3:
|
||||
; CHECK: .LBB9_4:
|
||||
; CHECK: return
|
||||
; OPT-LABEL: doubletriangle:
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, $0{{$}}
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, $1{{$}}
|
||||
; OPT: .LBB9_3:
|
||||
; OPT: .LBB9_4:
|
||||
@ -359,8 +361,8 @@ exit:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: ifelse_earlyexits:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, $0{{$}}
|
||||
; CHECK: br 1{{$}}
|
||||
; CHECK: .LBB10_2:
|
||||
@ -369,8 +371,8 @@ exit:
|
||||
; CHECK: i32.const $push{{[0-9]+}}=, 0{{$}}
|
||||
; CHECK-NEXT: return $pop{{[0-9]+}}{{$}}
|
||||
; OPT-LABEL: ifelse_earlyexits:
|
||||
; OPT: block{{$}}
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT: br_if 1, $1{{$}}
|
||||
; OPT: br 1{{$}}
|
||||
@ -400,13 +402,13 @@ exit:
|
||||
|
||||
; CHECK-LABEL: doublediamond_in_a_loop:
|
||||
; CHECK: .LBB11_1:
|
||||
; CHECK: loop{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: loop i32{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, $0{{$}}
|
||||
; CHECK: br 1{{$}}
|
||||
; CHECK: .LBB11_3:
|
||||
; CHECK: end_block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, $1{{$}}
|
||||
; CHECK: br 1{{$}}
|
||||
; CHECK: .LBB11_5:
|
||||
@ -415,10 +417,10 @@ exit:
|
||||
; CHECK-NEXT: end_loop{{$}}
|
||||
; OPT-LABEL: doublediamond_in_a_loop:
|
||||
; OPT: .LBB11_1:
|
||||
; OPT: loop{{$}}
|
||||
; OPT: block{{$}}
|
||||
; OPT: loop i32{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT: br 2{{$}}
|
||||
; OPT-NEXT: .LBB11_4:
|
||||
@ -429,7 +431,7 @@ exit:
|
||||
; OPT: br 0{{$}}
|
||||
; OPT: .LBB11_6:
|
||||
; OPT-NEXT: end_loop{{$}}
|
||||
define void @doublediamond_in_a_loop(i32 %a, i32 %b, i32* %p) {
|
||||
define i32 @doublediamond_in_a_loop(i32 %a, i32 %b, i32* %p) {
|
||||
entry:
|
||||
br label %header
|
||||
header:
|
||||
@ -513,14 +515,14 @@ if.end:
|
||||
|
||||
; CHECK-LABEL: test4:
|
||||
; CHECK-NEXT: .param i32{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK: br_if 0, $pop{{[0-9]+}}{{$}}
|
||||
; CHECK: br_if 1, $pop{{[0-9]+}}{{$}}
|
||||
; CHECK: br 1{{$}}
|
||||
; CHECK-NEXT: .LBB13_3:
|
||||
; CHECK-NEXT: end_block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK: br_if 0, $pop{{[0-9]+}}{{$}}
|
||||
; CHECK: br_if 1, $pop{{[0-9]+}}{{$}}
|
||||
; CHECK-NEXT: .LBB13_5:
|
||||
@ -531,14 +533,14 @@ if.end:
|
||||
; CHECK-NEXT: return{{$}}
|
||||
; OPT-LABEL: test4:
|
||||
; OPT-NEXT: .param i32{{$}}
|
||||
; OPT: block{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT: br_if 0, $pop{{[0-9]+}}{{$}}
|
||||
; OPT: br_if 1, $pop{{[0-9]+}}{{$}}
|
||||
; OPT: br 1{{$}}
|
||||
; OPT-NEXT: .LBB13_3:
|
||||
; OPT-NEXT: end_block{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT: br_if 0, $pop{{[0-9]+}}{{$}}
|
||||
; OPT: br_if 1, $pop{{[0-9]+}}{{$}}
|
||||
; OPT-NEXT: .LBB13_5:
|
||||
@ -574,8 +576,8 @@ default:
|
||||
|
||||
; CHECK-LABEL: test5:
|
||||
; CHECK: .LBB14_1:
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK: br_if 1, {{[^,]+}}{{$}}
|
||||
; CHECK: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NEXT: end_loop{{$}}
|
||||
@ -584,8 +586,8 @@ default:
|
||||
; CHECK: return{{$}}
|
||||
; OPT-LABEL: test5:
|
||||
; OPT: .LBB14_1:
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT: br_if 1, {{[^,]+}}{{$}}
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT-NEXT: end_loop{{$}}
|
||||
@ -619,9 +621,9 @@ return:
|
||||
|
||||
; CHECK-LABEL: test6:
|
||||
; CHECK: .LBB15_1:
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: br_if 2, {{[^,]+}}{{$}}
|
||||
; CHECK-NOT: block
|
||||
@ -640,9 +642,9 @@ return:
|
||||
; CHECK: return{{$}}
|
||||
; OPT-LABEL: test6:
|
||||
; OPT: .LBB15_1:
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 2, {{[^,]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
@ -693,9 +695,9 @@ second:
|
||||
|
||||
; CHECK-LABEL: test7:
|
||||
; CHECK: .LBB16_1:
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: br_if 1, {{[^,]+}}{{$}}
|
||||
@ -711,9 +713,9 @@ second:
|
||||
; OPT-LABEL: test7:
|
||||
; OPT: .LBB16_1:
|
||||
; OPT-NEXT: block
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
@ -760,7 +762,7 @@ u1:
|
||||
|
||||
; CHECK-LABEL: test8:
|
||||
; CHECK: .LBB17_1:
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: loop i32{{$}}
|
||||
; CHECK-NEXT: i32.const $push{{[^,]+}}, 0{{$}}
|
||||
; CHECK-NEXT: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NEXT: br 0{{$}}
|
||||
@ -768,13 +770,13 @@ u1:
|
||||
; CHECK-NEXT: end_loop{{$}}
|
||||
; OPT-LABEL: test8:
|
||||
; OPT: .LBB17_1:
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: loop i32{{$}}
|
||||
; OPT-NEXT: i32.const $push{{[^,]+}}, 0{{$}}
|
||||
; OPT-NEXT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT-NEXT: br 0{{$}}
|
||||
; OPT-NEXT: .LBB17_2:
|
||||
; OPT-NEXT: end_loop{{$}}
|
||||
define void @test8() {
|
||||
define i32 @test8() {
|
||||
bb:
|
||||
br label %bb1
|
||||
|
||||
@ -796,14 +798,14 @@ bb3:
|
||||
|
||||
; CHECK-LABEL: test9:
|
||||
; CHECK: .LBB18_1:
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: br_if 1, {{[^,]+}}{{$}}
|
||||
; CHECK-NEXT: .LBB18_2:
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NOT: block
|
||||
@ -821,14 +823,14 @@ bb3:
|
||||
; CHECK: return{{$}}
|
||||
; OPT-LABEL: test9:
|
||||
; OPT: .LBB18_1:
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 1, {{[^,]+}}{{$}}
|
||||
; OPT-NEXT: .LBB18_2:
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
@ -880,18 +882,18 @@ end:
|
||||
|
||||
; CHECK-LABEL: test10:
|
||||
; CHECK: .LBB19_1:
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK: .LBB19_3:
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: .LBB19_4:
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: br_if 3, {{[^,]+}}{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_table {{[^,]+}}, 1, 0, 4, 2, 3, 1{{$}}
|
||||
; CHECK-NEXT: .LBB19_6:
|
||||
; CHECK-NEXT: end_block{{$}}
|
||||
@ -905,15 +907,15 @@ end:
|
||||
; CHECK-NEXT: .LBB19_8:
|
||||
; OPT-LABEL: test10:
|
||||
; OPT: .LBB19_1:
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT: .LBB19_3:
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: .LBB19_4:
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 3, {{[^,]+}}{{$}}
|
||||
; OPT: block
|
||||
@ -966,13 +968,13 @@ bb6:
|
||||
; Test a CFG DAG with interesting merging.
|
||||
|
||||
; CHECK-LABEL: test11:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK-NEXT: i32.const
|
||||
; CHECK-NEXT: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NOT: block
|
||||
@ -1000,11 +1002,11 @@ bb6:
|
||||
; CHECK-NOT: block
|
||||
; CHECK: return{{$}}
|
||||
; OPT-LABEL: test11:
|
||||
; OPT: block{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT: br_if 0, $pop{{[0-9]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT-NEXT: i32.const
|
||||
; OPT-NEXT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
@ -1016,7 +1018,7 @@ bb6:
|
||||
; OPT-NEXT: .LBB20_4:
|
||||
; OPT-NEXT: end_block{{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 0, $pop{{[0-9]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
@ -1063,11 +1065,11 @@ bb8:
|
||||
|
||||
; CHECK-LABEL: test12:
|
||||
; CHECK: .LBB21_1:
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: br_if 1, {{[^,]+}}{{$}}
|
||||
@ -1090,11 +1092,11 @@ bb8:
|
||||
; CHECK-NEXT: return{{$}}
|
||||
; OPT-LABEL: test12:
|
||||
; OPT: .LBB21_1:
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: loop{{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT-NEXT: loop {{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: block{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 1, {{[^,]+}}{{$}}
|
||||
@ -1143,10 +1145,10 @@ bb7:
|
||||
|
||||
; CHECK-LABEL: test13:
|
||||
; CHECK-NEXT: .local i32{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK: br_if 0, $pop0{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_if 0, $pop3{{$}}
|
||||
; CHECK: .LBB22_3:
|
||||
; CHECK-NEXT: end_block{{$}}
|
||||
@ -1160,10 +1162,10 @@ bb7:
|
||||
; CHECK-NEXT: unreachable{{$}}
|
||||
; OPT-LABEL: test13:
|
||||
; OPT-NEXT: .local i32{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: block{{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT-NEXT: block {{$}}
|
||||
; OPT: br_if 0, $pop0{{$}}
|
||||
; OPT: block{{$}}
|
||||
; OPT: block {{$}}
|
||||
; OPT: br_if 0, $pop3{{$}}
|
||||
; OPT: .LBB22_3:
|
||||
; OPT-NEXT: end_block{{$}}
|
||||
@ -1197,12 +1199,12 @@ bb5:
|
||||
|
||||
; CHECK-LABEL: test14:
|
||||
; CHECK-NEXT: .LBB23_1:{{$}}
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NEXT: i32.const $push0=, 0{{$}}
|
||||
; CHECK-NEXT: br_if 0, $pop0{{$}}
|
||||
; CHECK-NEXT: end_loop{{$}}
|
||||
; CHECK-NEXT: .LBB23_3:{{$}}
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK-NEXT: i32.const $push1=, 0{{$}}
|
||||
; CHECK-NEXT: br_if 0, $pop1{{$}}
|
||||
; CHECK-NEXT: end_loop{{$}}
|
||||
@ -1261,9 +1263,9 @@ bb50:
|
||||
; CHECK-NEXT: block
|
||||
; CHECK: br_if 0, $pop{{.*}}{{$}}
|
||||
; CHECK: .LBB24_2:
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: loop{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: loop {{$}}
|
||||
; CHECK: br_if 1, $pop{{.*}}{{$}}
|
||||
; CHECK: br_if 0, ${{.*}}{{$}}
|
||||
; CHECK-NEXT: br 2{{$}}
|
||||
|
@ -84,7 +84,7 @@ define i32 @no_sink_readonly_call(i32 %x, i32 %y, i32* %p) {
|
||||
; CHECK-LABEL: stack_uses:
|
||||
; CHECK: .param i32, i32, i32, i32{{$}}
|
||||
; CHECK-NEXT: .result i32{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: i32.const $push[[L13:[0-9]+]]=, 1{{$}}
|
||||
; CHECK-NEXT: i32.lt_s $push[[L0:[0-9]+]]=, $0, $pop[[L13]]{{$}}
|
||||
; CHECK-NEXT: i32.const $push[[L1:[0-9]+]]=, 2{{$}}
|
||||
@ -127,7 +127,7 @@ false:
|
||||
; CHECK-LABEL: multiple_uses:
|
||||
; CHECK: .param i32, i32, i32{{$}}
|
||||
; CHECK-NEXT: .local i32{{$}}
|
||||
; CHECK-NEXT: block{{$}}
|
||||
; CHECK-NEXT: block {{$}}
|
||||
; CHECK-NEXT: i32.load $push[[NUM0:[0-9]+]]=, 0($2){{$}}
|
||||
; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $3=, $pop[[NUM0]]{{$}}
|
||||
; CHECK-NEXT: i32.ge_u $push[[NUM2:[0-9]+]]=, $pop[[NUM1]], $1{{$}}
|
||||
|
@ -14,13 +14,13 @@ declare void @foo4()
|
||||
declare void @foo5()
|
||||
|
||||
; CHECK-LABEL: bar32:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_table {{[^,]+}}, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5, 0{{$}}
|
||||
; CHECK: .LBB0_2:
|
||||
; CHECK: call foo0@FUNCTION{{$}}
|
||||
@ -94,13 +94,13 @@ sw.epilog: ; preds = %entry, %sw.bb.5, %s
|
||||
}
|
||||
|
||||
; CHECK-LABEL: bar64:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: block {{$}}
|
||||
; CHECK: br_table {{[^,]+}}, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5, 0{{$}}
|
||||
; CHECK: .LBB1_2:
|
||||
; CHECK: call foo0@FUNCTION{{$}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user