Index: llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp +++ llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp @@ -336,12 +336,18 @@ // instruction in which the current value is used, we cannot // stackify. Stackifying in this case would require that def moving below the // current def in the stack, which cannot be achieved, even with locals. + // If any subsequent def is used prior by a different instruction, we also + // cannot stackify. for (const auto &SubsequentDef : drop_begin(DefI->defs())) { - for (const auto &PriorUse : UseI->uses()) { - if (&PriorUse == Use) - break; - if (PriorUse.isReg() && SubsequentDef.getReg() == PriorUse.getReg()) - return false; + auto I = std::next(MachineBasicBlock::const_iterator(DefI)); + auto E = std::next(MachineBasicBlock::const_iterator(UseI)); + for (; I != E; ++I) { + for (const auto &PriorUse : I->uses()) { + if (&PriorUse == Use) + break; + if (PriorUse.isReg() && SubsequentDef.getReg() == PriorUse.getReg()) + return false; + } } } Index: llvm/test/CodeGen/WebAssembly/multivalue-dont-move-def-bug.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/WebAssembly/multivalue-dont-move-def-bug.ll @@ -0,0 +1,82 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -verify-machineinstrs -mattr=+multivalue | FileCheck %s + +target triple = "wasm32-unknown-wasi" + +@d = hidden local_unnamed_addr global double 0.000000e+00, align 8 +@c = hidden local_unnamed_addr global i32 0, align 4 + +define hidden fp128 @e() local_unnamed_addr #0 { +; CHECK-LABEL: e: +; CHECK: .functype e () -> (i64, i64) +; CHECK-NEXT: .local i64, i64, f64, i32, i32 +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: i64.const 0 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i64.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: block +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: f64.load d +; CHECK-NEXT: local.tee 2 +; CHECK-NEXT: f64.const 0x0p0 +; CHECK-NEXT: f64.ne +; CHECK-NEXT: br_if 0 # 0: down to label0 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: i32.load c +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: block +; CHECK-NEXT: block +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: f64.abs +; CHECK-NEXT: f64.const 0x1p31 +; CHECK-NEXT: f64.lt +; CHECK-NEXT: i32.eqz +; CHECK-NEXT: br_if 0 # 0: down to label2 +; CHECK-NEXT: # %bb.2: +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.trunc_f64_s +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: br 1 # 1: down to label1 +; CHECK-NEXT: .LBB0_3: +; CHECK-NEXT: end_block # label2: +; CHECK-NEXT: i32.const -2147483648 +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: .LBB0_4: +; CHECK-NEXT: end_block # label1: +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: call __floatsitf +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: i64.const 0 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: i64.select +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: i64.const 0 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: i64.select +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: .LBB0_5: +; CHECK-NEXT: end_block # label0: +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: # fallthrough-return + %1 = load double, ptr @d, align 8 + %2 = fcmp une double %1, 0.000000e+00 + br i1 %2, label %9, label %3 + +3: ; preds = %0 + %4 = load i32, ptr @c, align 4 + %5 = icmp eq i32 %4, 0 + %6 = fptosi double %1 to i32 + %7 = sitofp i32 %6 to fp128 + %8 = select i1 %5, fp128 0xL00000000000000000000000000000000, fp128 %7 + br label %9 + +9: ; preds = %0, %3 + %10 = phi fp128 [ %8, %3 ], [ 0xL00000000000000000000000000000000, %0 ] + ret fp128 %10 +}