[llvm] r255844 - [WebAssembly] Implement eliminateCallFramePseudo
Derek Schuff via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 16 15:21:31 PST 2015
Author: dschuff
Date: Wed Dec 16 17:21:30 2015
New Revision: 255844
URL: http://llvm.org/viewvc/llvm-project?rev=255844&view=rev
Log:
[WebAssembly] Implement eliminateCallFramePseudo
Summary:
Implement eliminateCallFramePsuedo to handle ADJCALLSTACKUP/DOWN
pseudo-instructions. Add a test calling a vararg function which causes non-0
adjustments. This revealed an issue with RegisterCoalescer wherein it
eliminates a COPY from SP32 to a vreg but failes to update the live ranges
of EXPR_STACK, causing a machineinstr verifier failure (so this test
is commented out).
Also add a dynamic alloca test, which causes a callseq_end dag node with
a 0 (instead of undef) second argument to be generated. We currently fail to
select that, so adjust the ADJCALLSTACKUP tablegen code to handle it.
Differential Revision: http://reviews.llvm.org/D15587
Modified:
llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td
llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
llvm/trunk/test/CodeGen/WebAssembly/userstack.ll
llvm/trunk/test/CodeGen/WebAssembly/varargs.ll
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp?rev=255844&r1=255843&r2=255844&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp Wed Dec 16 17:21:30 2015
@@ -61,31 +61,16 @@ bool WebAssemblyFrameLowering::hasReserv
return !MF.getFrameInfo()->hasVarSizedObjects();
}
-void WebAssemblyFrameLowering::eliminateCallFramePseudoInstr(
- MachineFunction & /*MF*/, MachineBasicBlock & /*MBB*/,
- MachineBasicBlock::iterator /*I*/) const {
- llvm_unreachable("TODO: implement eliminateCallFramePseudoInstr");
-}
-
-void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
- MachineBasicBlock &MBB) const {
- // TODO: Do ".setMIFlag(MachineInstr::FrameSetup)" on emitted instructions
- auto *MFI = MF.getFrameInfo();
- assert(MFI->getCalleeSavedInfo().empty() &&
- "WebAssembly should not have callee-saved registers");
- assert(!hasFP(MF) && "Functions needing frame pointers not yet supported");
- assert(!MFI->adjustsStack() && "Dynamic stack adjustmet not yet supported");
- uint64_t StackSize = MFI->getStackSize();
- if (!StackSize)
- return;
- const auto *TII = MF.getSubtarget().getInstrInfo();
+/// Adjust the stack pointer by a constant amount.
+static void adjustStackPointer(unsigned StackSize,
+ bool AdjustUp,
+ MachineFunction& MF,
+ MachineBasicBlock& MBB,
+ const TargetInstrInfo* TII,
+ MachineBasicBlock::iterator InsertPt,
+ const DebugLoc& DL) {
auto &MRI = MF.getRegInfo();
- auto InsertPt = MBB.begin();
- DebugLoc DL;
-
- // Get the current stacktop
- // TODO: To support dynamic alloc, also copy to FP
unsigned SPReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer");
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPReg)
@@ -100,11 +85,13 @@ void WebAssemblyFrameLowering::emitProlo
.addImm(0)
.addReg(SPReg)
.addMemOperand(LoadMMO);
- // Subtract the frame size
+ // Add/Subtract the frame size
unsigned OffsetReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
.addImm(StackSize);
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::SUB_I32), WebAssembly::SP32)
+ BuildMI(MBB, InsertPt, DL,
+ TII->get(AdjustUp ? WebAssembly::ADD_I32 : WebAssembly::SUB_I32),
+ WebAssembly::SP32)
.addReg(SPReg)
.addReg(OffsetReg);
// The SP32 register now has the new stacktop. Also write it back to memory.
@@ -119,6 +106,40 @@ void WebAssemblyFrameLowering::emitProlo
.addMemOperand(MMO);
}
+void WebAssemblyFrameLowering::eliminateCallFramePseudoInstr(
+ MachineFunction &MF, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const {
+ const auto *TII =
+ static_cast<const WebAssemblyInstrInfo*>(MF.getSubtarget().getInstrInfo());
+ DebugLoc DL = I->getDebugLoc();
+ unsigned Opc = I->getOpcode();
+ bool IsDestroy = Opc == TII->getCallFrameDestroyOpcode();
+ unsigned Amount = I->getOperand(0).getImm();
+ if (Amount)
+ adjustStackPointer(Amount, IsDestroy, MF, MBB,
+ TII, I, DL);
+ MBB.erase(I);
+}
+
+void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const {
+ // TODO: Do ".setMIFlag(MachineInstr::FrameSetup)" on emitted instructions
+ auto *MFI = MF.getFrameInfo();
+ assert(MFI->getCalleeSavedInfo().empty() &&
+ "WebAssembly should not have callee-saved registers");
+ assert(!hasFP(MF) && "Functions needing frame pointers not yet supported");
+ uint64_t StackSize = MFI->getStackSize();
+ if (!StackSize && (!MFI->adjustsStack() || MFI->getMaxCallFrameSize() == 0))
+ return;
+
+ const auto *TII = MF.getSubtarget().getInstrInfo();
+
+ auto InsertPt = MBB.begin();
+ DebugLoc DL;
+
+ adjustStackPointer(StackSize, false, MF, MBB, TII, InsertPt, DL);
+}
+
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
uint64_t StackSize = MF.getFrameInfo()->getStackSize();
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp?rev=255844&r1=255843&r2=255844&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp Wed Dec 16 17:21:30 2015
@@ -445,7 +445,7 @@ WebAssemblyTargetLowering::LowerCall(Cal
}
if (NumBytes) {
- SDValue Unused = DAG.getUNDEF(PtrVT);
+ SDValue Unused = DAG.getTargetConstant(0, DL, PtrVT);
Chain = DAG.getCALLSEQ_END(Chain, NB, Unused, SDValue(), DL);
}
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td?rev=255844&r1=255843&r2=255844&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td Wed Dec 16 17:21:30 2015
@@ -21,8 +21,8 @@ let Defs = [ARGUMENTS] in {
let Uses = [SP32, SP64], Defs = [SP32, SP64], isCodeGenOnly = 1 in {
def ADJCALLSTACKDOWN : I<(outs), (ins i32imm:$amt),
[(WebAssemblycallseq_start timm:$amt)]>;
-def ADJCALLSTACKUP : I<(outs), (ins i32imm:$amt),
- [(WebAssemblycallseq_end timm:$amt, undef)]>;
+def ADJCALLSTACKUP : I<(outs), (ins i32imm:$amt, i32imm:$amt2),
+ [(WebAssemblycallseq_end timm:$amt, timm:$amt2)]>;
} // isCodeGenOnly = 1
multiclass CALL<WebAssemblyRegClass vt, string prefix> {
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp?rev=255844&r1=255843&r2=255844&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp Wed Dec 16 17:21:30 2015
@@ -36,8 +36,12 @@ void WebAssemblyInstrInfo::copyPhysReg(M
MachineBasicBlock::iterator I,
DebugLoc DL, unsigned DestReg,
unsigned SrcReg, bool KillSrc) const {
- const TargetRegisterClass *RC =
- MBB.getParent()->getRegInfo().getRegClass(SrcReg);
+ // This method is called by post-RA expansion, which expects only pregs to
+ // exist. However we need to handle both here.
+ auto &MRI = MBB.getParent()->getRegInfo();
+ const TargetRegisterClass *RC = TargetRegisterInfo::isVirtualRegister(DestReg) ?
+ MRI.getRegClass(DestReg) :
+ MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(SrcReg);
unsigned CopyLocalOpcode;
if (RC == &WebAssembly::I32RegClass)
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp?rev=255844&r1=255843&r2=255844&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp Wed Dec 16 17:21:30 2015
@@ -136,7 +136,6 @@ bool WebAssemblyRegStackify::runOnMachin
for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : reverse(MBB)) {
MachineInstr *Insert = &MI;
-
// Don't nest anything inside a phi.
if (Insert->getOpcode() == TargetOpcode::PHI)
break;
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp?rev=255844&r1=255843&r2=255844&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp Wed Dec 16 17:21:30 2015
@@ -169,6 +169,9 @@ void WebAssemblyPassConfig::addPreRegAll
// Mark registers as representing wasm's expression stack.
addPass(createWebAssemblyRegStackify());
+ // The register coalescing pass has a bad interaction with COPY MIs which have
+ // EXPR_STACK as an extra operand
+ //disablePass(&RegisterCoalescerID);
}
void WebAssemblyPassConfig::addPostRegAlloc() {
Modified: llvm/trunk/test/CodeGen/WebAssembly/userstack.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/userstack.ll?rev=255844&r1=255843&r2=255844&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/userstack.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/userstack.ll Wed Dec 16 17:21:30 2015
@@ -72,4 +72,10 @@ define void @allocarray() {
ret void
}
+define void @dynamic_alloca(i32 %alloc) {
+ ; TODO: Support frame pointers
+ ;%r = alloca i32, i32 %alloc
+ ;store i32 0, i32* %r
+ ret void
+}
; TODO: test aligned alloc
Modified: llvm/trunk/test/CodeGen/WebAssembly/varargs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/varargs.ll?rev=255844&r1=255843&r2=255844&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/varargs.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/varargs.ll Wed Dec 16 17:21:30 2015
@@ -110,12 +110,13 @@ define void @caller_none() {
ret void
}
-; TODO: Test a varargs call with actual arguments.
-
-;define void @caller_some() {
-; call void (...) @callee(i32 0, double 2.0)
-; ret void
-;}
+; CHECK-LABEL: caller_some
+define void @caller_some() {
+ ; TODO: Fix interaction between register coalescer and reg stackifier,
+ ; or disable coalescer.
+ ;call void (...) @callee(i32 0, double 2.0)
+ ret void
+}
declare void @llvm.va_start(i8*)
declare void @llvm.va_end(i8*)
More information about the llvm-commits
mailing list