//===---------------------------------------------------------------------===//
-Br, br_if, and br_table instructions can support having a value on the
-expression stack across the jump (sometimes). We should (a) model this, and
-(b) extend the stackifier to utilize it.
+Br, br_if, and br_table instructions can support having a value on the value
+stack across the jump (sometimes). We should (a) model this, and (b) extend
+the stackifier to utilize it.
//===---------------------------------------------------------------------===//
-The min/max operators aren't exactly a<b?a:b because of NaN and negative zero
+The min/max instructions aren't exactly a<b?a:b because of NaN and negative zero
behavior. The ARM target has the same kind of min/max instructions and has
implemented optimizations for them; we should do similar optimizations for
WebAssembly.
//===---------------------------------------------------------------------===//
-Register stackification uses the EXPR_STACK physical register to impose
+Register stackification uses the VALUE_STACK physical register to impose
ordering dependencies on instructions with stack operands. This is pessimistic;
we should consider alternate ways to model stack dependencies.
instructions advantageously for this purpose.
//===---------------------------------------------------------------------===//
+
+WebAssembly is now officially a stack machine, rather than an AST, and this
+comes with additional opportunities for WebAssemblyRegStackify. Specifically,
+the stack doesn't need to be empty after an instruction with no return values.
+WebAssemblyRegStackify could be extended, or possibly rewritten, to take
+advantage of the new opportunities.
+
+//===---------------------------------------------------------------------===//
const auto &MLI = getAnalysis<MachineLoopInfo>();
auto &MDT = getAnalysis<MachineDominatorTree>();
- // Liveness is not tracked for EXPR_STACK physreg.
+ // Liveness is not tracked for VALUE_STACK physreg.
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
MF.getRegInfo().invalidateLiveness();
} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
// Placemarkers to indicate the start or end of a block or loop scope. These
-// use/clobber EXPR_STACK to prevent them from being moved into the middle of
+// use/clobber VALUE_STACK to prevent them from being moved into the middle of
// an expression tree.
-let Uses = [EXPR_STACK], Defs = [EXPR_STACK] in {
+let Uses = [VALUE_STACK], Defs = [VALUE_STACK] in {
def BLOCK : I<(outs), (ins), [], "block">;
def LOOP : I<(outs), (ins), [], "loop">;
def END_BLOCK : I<(outs), (ins), [], "end_block">;
def END_LOOP : I<(outs), (ins), [], "end_loop">;
-} // Uses = [EXPR_STACK], Defs = [EXPR_STACK]
+} // Uses = [VALUE_STACK], Defs = [VALUE_STACK]
multiclass RETURN<WebAssemblyRegClass vt> {
def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)],
}
// If we weren't able to invert the condition in place. Insert an
- // expression to invert it.
+ // instruction to invert it.
if (!Inverted) {
unsigned Tmp = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
MFI.stackifyVReg(Tmp);
/// This pass reorders instructions to put register uses and defs in an order
/// such that they form single-use expression trees. Registers fitting this form
/// are then marked as "stackified", meaning references to them are replaced by
-/// "push" and "pop" from the stack.
+/// "push" and "pop" from the value stack.
///
/// This is primarily a code size optimization, since temporary values on the
-/// expression don't need to be named.
+/// value stack don't need to be named.
///
//===----------------------------------------------------------------------===//
// expression stack ordering constraints for an instruction which is on
// the expression stack.
static void ImposeStackOrdering(MachineInstr *MI) {
- // Write the opaque EXPR_STACK register.
- if (!MI->definesRegister(WebAssembly::EXPR_STACK))
- MI->addOperand(MachineOperand::CreateReg(WebAssembly::EXPR_STACK,
+ // Write the opaque VALUE_STACK register.
+ if (!MI->definesRegister(WebAssembly::VALUE_STACK))
+ MI->addOperand(MachineOperand::CreateReg(WebAssembly::VALUE_STACK,
/*isDef=*/true,
/*isImp=*/true));
- // Also read the opaque EXPR_STACK register.
- if (!MI->readsRegister(WebAssembly::EXPR_STACK))
- MI->addOperand(MachineOperand::CreateReg(WebAssembly::EXPR_STACK,
+ // Also read the opaque VALUE_STACK register.
+ if (!MI->readsRegister(WebAssembly::VALUE_STACK))
+ MI->addOperand(MachineOperand::CreateReg(WebAssembly::VALUE_STACK,
/*isDef=*/false,
/*isImp=*/true));
}
}
}
- // If we used EXPR_STACK anywhere, add it to the live-in sets everywhere so
+ // If we used VALUE_STACK anywhere, add it to the live-in sets everywhere so
// that it never looks like a use-before-def.
if (Changed) {
- MF.getRegInfo().addLiveIn(WebAssembly::EXPR_STACK);
+ MF.getRegInfo().addLiveIn(WebAssembly::VALUE_STACK);
for (MachineBasicBlock &MBB : MF)
- MBB.addLiveIn(WebAssembly::EXPR_STACK);
+ MBB.addLiveIn(WebAssembly::VALUE_STACK);
}
#ifndef NDEBUG
def V128_0: WebAssemblyReg<"%v128">;
-// The expression stack "register". This is an opaque entity which serves to
-// order uses and defs that must remain in LIFO order.
-def EXPR_STACK : WebAssemblyReg<"STACK">;
+// The value stack "register". This is an opaque entity which serves to order
+// uses and defs that must remain in LIFO order.
+def VALUE_STACK : WebAssemblyReg<"STACK">;
// The incoming arguments "register". This is an opaque entity which serves to
// order the ARGUMENT instructions that are emulating live-in registers and
for (unsigned PReg = WebAssembly::NoRegister + 1;
PReg < WebAssembly::NUM_TARGET_REGS; ++PReg) {
// Skip fake registers that are never used explicitly.
- if (PReg == WebAssembly::EXPR_STACK || PReg == WebAssembly::ARGUMENTS)
+ if (PReg == WebAssembly::VALUE_STACK || PReg == WebAssembly::ARGUMENTS)
continue;
// Replace explicit uses of the physical register with a virtual register.
TT, CPU, FS, Options, getEffectiveRelocModel(RM),
CM, OL),
TLOF(make_unique<WebAssemblyTargetObjectFile>()) {
- // WebAssembly type-checks expressions, but a noreturn function with a return
+ // WebAssembly type-checks instructions, but a noreturn function with a return
// type that doesn't match the context will cause a check failure. So we lower
// LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
- // 'unreachable' expression which is meant for that case.
+ // 'unreachable' instructions which is meant for that case.
this->Options.TrapUnreachable = true;
initAsmInfo();
// Prepare store instructions for register stackifying.
addPass(createWebAssemblyStoreResults());
- // Mark registers as representing wasm's expression stack. This is a key
+ // Mark registers as representing wasm's value stack. This is a key
// code-compression technique in WebAssembly. We run this pass (and
// StoreResults above) very late, so that it sees as much code as possible,
// including code emitted by PEI and expanded by late tail duplication.