llvm.org GIT mirror llvm / 1a513a6
[WebAssembly] Optimize away return instructions using fallthroughs. This saves a small amount of code size, and is a first small step toward passing values on the stack across block boundaries. Differential Review: http://reviews.llvm.org/D20450 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270294 91177308-0d34-0410-b5e6-96231b3b80d8 Dan Gohman 4 years ago
47 changed file(s) with 202 addition(s) and 60 deletion(s). Raw diff Collapse all Expand all
144144 if (int(WAReg) >= 0)
145145 printRegName(O, WAReg);
146146 else if (OpNo >= MII.get(MI->getOpcode()).getNumDefs())
147 O << "$pop" << (WAReg & INT32_MAX);
147 O << "$pop" << WebAssemblyFunctionInfo::getWARegStackId(WAReg);
148148 else if (WAReg != WebAssemblyFunctionInfo::UnusedReg)
149 O << "$push" << (WAReg & INT32_MAX);
149 O << "$push" << WebAssemblyFunctionInfo::getWARegStackId(WAReg);
150150 else
151151 O << "$drop";
152152 // Add a '=' suffix if this is a def.
200200 // These represent values which are live into the function entry, so there's
201201 // no instruction to emit.
202202 break;
203 case WebAssembly::FALLTHROUGH_RETURN_I32:
204 case WebAssembly::FALLTHROUGH_RETURN_I64:
205 case WebAssembly::FALLTHROUGH_RETURN_F32:
206 case WebAssembly::FALLTHROUGH_RETURN_F64: {
207 // These instructions represent the implicit return at the end of a
208 // function body. The operand is always a pop.
209 assert(MFI->isVRegStackified(MI->getOperand(0).getReg()));
210
211 if (isVerbose()) {
212 OutStreamer->AddComment("fallthrough-return: $pop" +
213 utostr(MFI->getWARegStackId(
214 MFI->getWAReg(MI->getOperand(0).getReg()))));
215 OutStreamer->AddBlankLine();
216 }
217 break;
218 }
219 case WebAssembly::FALLTHROUGH_RETURN_VOID:
220 // This instruction represents the implicit return at the end of a
221 // function body with no return value.
222 if (isVerbose()) {
223 OutStreamer->AddComment("fallthrough-return");
224 OutStreamer->AddBlankLine();
225 }
226 break;
203227 default: {
204228 WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
205229 MCInst TmpInst;
7070 multiclass RETURN {
7171 def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)],
7272 "return \t$val">;
73 // Equivalent to RETURN_#vt, for use at the end of a function when wasm
74 // semantics return by falling off the end of the block.
75 let isCodeGenOnly = 1 in
76 def FALLTHROUGH_RETURN_#vt : I<(outs), (ins vt:$val), []>;
7377 }
7478
7579 let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
7983 defm : RETURN;
8084 defm : RETURN;
8185 def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return">;
86
87 // This is to RETURN_VOID what FALLTHROUGH_RETURN_#vt is to RETURN_#vt.
88 let isCodeGenOnly = 1 in
89 def FALLTHROUGH_RETURN_VOID : I<(outs), (ins), []>;
8290 } // isReturn = 1
8391 def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable">;
8492 } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
8585 assert(VReg = WARegs.size());
8686 WARegs.push_back(WAReg);
8787 }
88
89 // For a given stackified WAReg, return the id number to print with push/pop.
90 static unsigned getWARegStackId(unsigned Reg) {
91 assert(Reg & INT32_MIN);
92 return Reg & INT32_MAX;
93 }
8894 };
8995
9096 } // end namespace llvm
1111 ///
1212 //===----------------------------------------------------------------------===//
1313
14 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1415 #include "WebAssembly.h"
15 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1616 #include "WebAssemblyMachineFunctionInfo.h"
1717 #include "WebAssemblySubtarget.h"
1818 #include "llvm/Analysis/TargetLibraryInfo.h"
1919 #include "llvm/CodeGen/MachineFunctionPass.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
2021 #include "llvm/CodeGen/MachineRegisterInfo.h"
2122 using namespace llvm;
2223
2324 #define DEBUG_TYPE "wasm-peephole"
25
26 static cl::opt DisableWebAssemblyFallthroughReturnOpt(
27 "disable-wasm-fallthrough-return-opt", cl::Hidden,
28 cl::desc("WebAssembly: Disable fallthrough-return optimizations."),
29 cl::init(false));
2430
2531 namespace {
2632 class WebAssemblyPeephole final : public MachineFunctionPass {
4955
5056 /// If desirable, rewrite NewReg to a drop register.
5157 static bool MaybeRewriteToDrop(unsigned OldReg, unsigned NewReg,
52 MachineOperand &MO,
53 WebAssemblyFunctionInfo &MFI,
58 MachineOperand &MO, WebAssemblyFunctionInfo &MFI,
5459 MachineRegisterInfo &MRI) {
5560 bool Changed = false;
5661 if (OldReg == NewReg) {
5964 MO.setReg(NewReg);
6065 MO.setIsDead();
6166 MFI.stackifyVReg(NewReg);
62 MFI.addWAReg(NewReg, WebAssemblyFunctionInfo::UnusedReg);
6367 }
6468 return Changed;
6569 }
6670
71 static bool MaybeRewriteToFallthrough(MachineInstr &MI, MachineBasicBlock &MBB,
72 const MachineFunction &MF,
73 WebAssemblyFunctionInfo &MFI,
74 MachineRegisterInfo &MRI,
75 const WebAssemblyInstrInfo &TII,
76 unsigned FallthroughOpc,
77 unsigned CopyLocalOpc) {
78 if (DisableWebAssemblyFallthroughReturnOpt)
79 return false;
80 if (&MBB != &MF.back())
81 return false;
82 if (&MI != &MBB.back())
83 return false;
84
85 // If the operand isn't stackified, insert a COPY_LOCAL to read the operand
86 // and stackify it.
87 MachineOperand &MO = MI.getOperand(0);
88 unsigned Reg = MO.getReg();
89 if (!MFI.isVRegStackified(Reg)) {
90 unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(Reg));
91 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(CopyLocalOpc), NewReg)
92 .addReg(Reg);
93 MO.setReg(NewReg);
94 MFI.stackifyVReg(NewReg);
95 }
96
97 // Rewrite the return.
98 MI.setDesc(TII.get(FallthroughOpc));
99 return true;
100 }
101
67102 bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
68103 DEBUG({
69 dbgs() << "********** Store Results **********\n"
104 dbgs() << "********** Peephole **********\n"
70105 << "********** Function: " << MF.getName() << '\n';
71106 });
72107
73108 MachineRegisterInfo &MRI = MF.getRegInfo();
74109 WebAssemblyFunctionInfo &MFI = *MF.getInfo();
110 const auto &TII = *MF.getSubtarget().getInstrInfo();
75111 const WebAssemblyTargetLowering &TLI =
76112 *MF.getSubtarget().getTargetLowering();
77113 auto &LibInfo = getAnalysis().getTLI();
126162 }
127163 }
128164 }
165 break;
129166 }
167 // Optimize away an explicit void return at the end of the function.
168 case WebAssembly::RETURN_I32:
169 Changed |= MaybeRewriteToFallthrough(
170 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_I32,
171 WebAssembly::COPY_LOCAL_I32);
172 break;
173 case WebAssembly::RETURN_I64:
174 Changed |= MaybeRewriteToFallthrough(
175 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_I64,
176 WebAssembly::COPY_LOCAL_I64);
177 break;
178 case WebAssembly::RETURN_F32:
179 Changed |= MaybeRewriteToFallthrough(
180 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_F32,
181 WebAssembly::COPY_LOCAL_F32);
182 break;
183 case WebAssembly::RETURN_F64:
184 Changed |= MaybeRewriteToFallthrough(
185 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_F64,
186 WebAssembly::COPY_LOCAL_F64);
187 break;
188 case WebAssembly::RETURN_VOID:
189 if (!DisableWebAssemblyFallthroughReturnOpt &&
190 &MBB == &MF.back() && &MI == &MBB.back())
191 MI.setDesc(TII.get(WebAssembly::FALLTHROUGH_RETURN_VOID));
192 break;
130193 }
131194
132195 return Changed;
224224 // Lower br_unless into br_if.
225225 addPass(createWebAssemblyLowerBrUnless());
226226
227 // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
228 addPass(createWebAssemblyRegNumbering());
229
230227 // Perform the very last peephole optimizations on the code.
231228 if (getOptLevel() != CodeGenOpt::None)
232229 addPass(createWebAssemblyPeephole());
233 }
230
231 // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
232 addPass(createWebAssemblyRegNumbering());
233 }
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test folding constant offsets and symbols into load and store addresses under
33 ; a variety of circumstances.
None ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -fast-isel | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs -fast-isel | FileCheck %s
22
33 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
44 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic call operations assemble as expected.
44
None ; RUN: llc < %s -asm-verbose=false -disable-block-placement -verify-machineinstrs -fast-isel=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -fast-isel=false | FileCheck -check-prefix=OPT %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs -fast-isel=false | FileCheck -check-prefix=OPT %s
22
33 ; Test the CFG stackifier pass.
44
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic 32-bit floating-point comparison operations assemble as
33 ; expected.
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic 64-bit floating-point comparison operations assemble as
33 ; expected.
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic 32-bit integer comparison operations assemble as expected.
44
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic 64-bit integer comparison operations assemble as expected.
44
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic conversion operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic 32-bit floating-point operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic 64-bit floating-point operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that the frem instruction works.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic functions assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that globals assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic 128-bit integer operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test loads and stores with custom alignment values.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic 32-bit integer operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test loads and stores with custom alignment values.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic 64-bit integer operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic immediates assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false -no-integrated-as | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -no-integrated-as | FileCheck %s
11
22 ; Test basic inline assembly. Pass -no-integrated-as since these aren't
33 ; actually valid assembly syntax.
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test various types and operators that need to be legalized.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that extending loads are assembled properly.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that i1 extending loads and truncating stores are assembled properly.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic loads are assembled properly.
44
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test memcpy, memmove, and memset intrinsics.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic memory operations assemble as expected with 32-bit addresses.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that basic memory operations assemble as expected with 64-bit addresses.
33
None ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s
11
22 ; Test that phis are lowered.
33
None ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s
11
22 ; Test the register stackifier pass.
33
44 target triple = "wasm32-unknown-unknown"
55
66 ; CHECK-LABEL: return_i32:
7 ; CHECK: return $0{{$}}
7 ; CHECK-NEXT: .param i32{{$}}
8 ; CHECK-NEXT: .result i32{{$}}
9 ; CHECK-NEXT: copy_local $push0=, $0
10 ; CHECK-NEXT: .endfunc{{$}}
811 define i32 @return_i32(i32 %p) {
912 ret i32 %p
1013 }
14
15 ; CHECK-LABEL: return_i32_twice:
16 ; CHECK: store
17 ; CHECK-NEXT: i32.const $push[[L0:[^,]+]]=, 1{{$}}
18 ; CHECK-NEXT: return $pop[[L0]]{{$}}
19 ; CHECK: store
20 ; CHECK-NEXT: i32.const $push{{[^,]+}}=, 3{{$}}
21 ; CHECK-NEXT: .endfunc{{$}}
22 define i32 @return_i32_twice(i32 %a) {
23 %b = icmp ne i32 %a, 0
24 br i1 %b, label %true, label %false
25
26 true:
27 store i32 0, i32* null
28 ret i32 1
29
30 false:
31 store i32 2, i32* null
32 ret i32 3
33 }
44 target triple = "wasm32-unknown-unknown"
55
66 ; CHECK-LABEL: return_void:
7 ; CHECK: return{{$}}
7 ; CHECK-NEXT: .endfunc{{$}}
88 define void @return_void() {
99 ret void
1010 }
11
12 ; CHECK-LABEL: return_void_twice:
13 ; CHECK: store
14 ; CHECK-NEXT: return{{$}}
15 ; CHECK: store
16 ; CHECK-NEXT: .endfunc{{$}}
17 define void @return_void_twice(i32 %a) {
18 %b = icmp ne i32 %a, 0
19 br i1 %b, label %true, label %false
20
21 true:
22 store i32 0, i32* null
23 ret void
24
25 false:
26 store i32 1, i32* null
27 ret void
28 }
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that the "returned" attribute is optimized effectively.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that wasm select instruction is selected from LLVM select instruction.
44
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test zeroext and signext ABI keywords
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test that the wasm-store-results pass makes users of stored values use the
33 ; result of store expressions to reduce get_local/set_local traffic.
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic stores are assembled properly.
44
None ; RUN: llc < %s -asm-verbose=false -disable-block-placement -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs | FileCheck %s
11
22 ; Test switch instructions. Block placement is disabled because it reorders
33 ; the blocks in a way that isn't interesting here.
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Make sure that argument offsets are correct even if some arguments are unused.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s
11
22 ; Test varargs constructs.
33