Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -160,6 +160,7 @@ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addImm(StackSize); auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer"); + // TODO: Fold this add into the const offset field of the store. BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::ADD_I32), WebAssembly::SP32) .addReg(WebAssembly::SP32) .addReg(OffsetReg); Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyPeephole.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyPeephole.cpp +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyPeephole.cpp @@ -120,7 +120,10 @@ MachineOperand &MO = MI.getOperand(0); unsigned OldReg = MO.getReg(); unsigned NewReg = Op2.getReg(); - if (MRI.getRegClass(NewReg) != MRI.getRegClass(OldReg)) + + // TODO: Handle SP/physregs in MaybeRewriteToDiscard + if (TargetRegisterInfo::isVirtualRegister(NewReg) && + (MRI.getRegClass(NewReg) != MRI.getRegClass(OldReg))) report_fatal_error("Peephole: call to builtin function with " "wrong signature, from/to mismatch"); Changed |= MaybeRewriteToDiscard(OldReg, NewReg, MO, MFI, MRI); Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp @@ -81,15 +81,18 @@ auto &MRI = MF.getRegInfo(); const auto *TII = MF.getSubtarget().getInstrInfo(); - unsigned OffsetReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); - BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(WebAssembly::CONST_I32), - OffsetReg) - .addImm(FrameOffset); - BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(WebAssembly::ADD_I32), - OffsetReg) - .addReg(WebAssembly::SP32) - .addReg(OffsetReg); - MI.getOperand(FIOperandNum).ChangeToRegister(OffsetReg, /*IsDef=*/false); + unsigned FIRegOperand = WebAssembly::SP32; + if (FrameOffset) { + FIRegOperand = MRI.createVirtualRegister(&WebAssembly::I32RegClass); + BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(WebAssembly::CONST_I32), + FIRegOperand) + .addImm(FrameOffset); + BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(WebAssembly::ADD_I32), + FIRegOperand) + .addReg(WebAssembly::SP32) + .addReg(FIRegOperand); + } + MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*IsDef=*/false); } } Index: llvm/trunk/test/CodeGen/WebAssembly/mem-intrinsics.ll =================================================================== --- llvm/trunk/test/CodeGen/WebAssembly/mem-intrinsics.ll +++ llvm/trunk/test/CodeGen/WebAssembly/mem-intrinsics.ll @@ -59,13 +59,18 @@ ret void } + ; CHECK-LABEL: frame_index: ; CHECK: i32.call $discard=, memset@FUNCTION, $3, $pop1, $pop0{{$}} +; CHECK: i32.call $discard=, memset@FUNCTION, $4, $pop3, $pop2{{$}} ; CHECK: return{{$}} define void @frame_index() { entry: %a = alloca [2048 x i8], align 16 + %b = alloca [2048 x i8], align 16 %0 = getelementptr inbounds [2048 x i8], [2048 x i8]* %a, i32 0, i32 0 + %1 = getelementptr inbounds [2048 x i8], [2048 x i8]* %b, i32 0, i32 0 call void @llvm.memset.p0i8.i32(i8* %0, i8 256, i32 1024, i32 16, i1 false) + call void @llvm.memset.p0i8.i32(i8* %1, i8 256, i32 1024, i32 16, i1 false) ret void } Index: llvm/trunk/test/CodeGen/WebAssembly/userstack.ll =================================================================== --- llvm/trunk/test/CodeGen/WebAssembly/userstack.ll +++ llvm/trunk/test/CodeGen/WebAssembly/userstack.ll @@ -76,6 +76,24 @@ ret void } +declare void @ext_func(i64* %ptr) +; CHECK-LABEL: non_mem_use +define void @non_mem_use() { + ; CHECK: i32.const [[L2:.+]]=, 16 + ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, [[L2]] + %r = alloca i64 + %r2 = alloca i64 + ; %r is at SP+8 + ; CHECK: i32.const [[OFF:.+]]=, 8 + ; CHECK-NEXT: i32.add [[ARG1:.+]]=, [[SP]], [[OFF]] + ; CHECK-NEXT: call ext_func@FUNCTION, [[ARG1]] + call void @ext_func(i64* %r) + ; %r2 is at SP+0, no add needed + ; CHECK-NEXT: call ext_func@FUNCTION, [[SP]] + call void @ext_func(i64* %r2) + ret void +} + ; CHECK-LABEL: allocarray_inbounds: ; CHECK: .local i32, i32, i32, i32{{$}} define void @allocarray_inbounds() {