Index: lib/Target/WebAssembly/WebAssemblyRegStackify.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyRegStackify.cpp +++ lib/Target/WebAssembly/WebAssemblyRegStackify.cpp @@ -81,6 +81,7 @@ // more precise. static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert, AliasAnalysis &AA) { + assert(Def->getParent() == Insert->getParent()); bool SawStore = false, SawSideEffects = false; MachineBasicBlock::const_iterator D(Def), I(Insert); for (--I; I != D; --I) @@ -155,17 +156,15 @@ Def->getOpcode() == WebAssembly::ARGUMENT_F64) continue; - // Single-use expression trees require defs that have one use, or that - // they be trivially clonable. + // Single-use expression trees require defs that have one use. // TODO: Eventually we'll relax this, to take advantage of set_local // returning its result. if (!MRI.hasOneUse(Reg)) continue; - // For now, be conservative and don't look across block boundaries, - // unless we have something trivially clonable. + // For now, be conservative and don't look across block boundaries. // TODO: Be more aggressive. - if (Def->getParent() != &MBB && !Def->isMoveImmediate()) + if (Def->getParent() != &MBB) continue; // Don't move instructions that have side effects or memory dependencies Index: lib/Target/WebAssembly/WebAssemblyStoreResults.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyStoreResults.cpp +++ lib/Target/WebAssembly/WebAssemblyStoreResults.cpp @@ -89,12 +89,18 @@ for (auto I = MRI.use_begin(FromReg), E = MRI.use_end(); I != E;) { MachineOperand &O = *I++; MachineInstr *Where = O.getParent(); - if (Where->getOpcode() == TargetOpcode::PHI) - Where = Where->getOperand(&O - &Where->getOperand(0) + 1) - .getMBB() - ->getFirstTerminator(); - if (&MI == Where || !MDT.dominates(&MI, Where)) - continue; + if (Where->getOpcode() == TargetOpcode::PHI) { + // For a PHI, check that MI dominates the edge on which the operand + // is used. + MachineBasicBlock *Pred = Where->getOperand(&O - &Where->getOperand(0) + 1).getMBB(); + if (!MDT.dominates(&MBB, Pred)) + continue; + } else { + // For a non-PHI, check that MI dominates the instruction in the + // normal way. + if (&MI == Where || !MDT.dominates(&MI, Where)) + continue; + } DEBUG(dbgs() << "Setting operand " << O << " in " << *Where << " from " << MI <<"\n"); O.setReg(ToReg); Index: test/CodeGen/WebAssembly/store-results.ll =================================================================== --- test/CodeGen/WebAssembly/store-results.ll +++ test/CodeGen/WebAssembly/store-results.ll @@ -16,3 +16,44 @@ store i32 0, i32* %p ret i32 0 } + +; Test interesting corner cases for wasm-store-results. + +%class.Vec3 = type { float, float, float } + +@pos = global %class.Vec3 zeroinitializer, align 4 + +; CHECK-LABEL: foo: +; CHECK: i32.store $discard=, $pop0, $0 +define void @foo() { +for.body.i: + br label %for.body5.i + +for.body5.i: + %i.0168.i = phi i32 [ 0, %for.body.i ], [ %inc.i, %for.body5.i ] + %conv6.i = sitofp i32 %i.0168.i to float + store volatile float 0.0, float* getelementptr inbounds (%class.Vec3, %class.Vec3* @pos, i32 0, i32 0) + %inc.i = add nuw nsw i32 %i.0168.i, 1 + %exitcond.i = icmp eq i32 %inc.i, 256 + br i1 %exitcond.i, label %for.cond.cleanup4.i, label %for.body5.i + +for.cond.cleanup4.i: + ret void +} + +; CHECK-LABEL: bar: +; CHECK: i32.store $discard=, $0, $pop0 +define void @bar() { +for.body.i: + br label %for.body5.i + +for.body5.i: + %i.0168.i = phi float [ 0.0, %for.body.i ], [ %inc.i, %for.body5.i ] + store volatile float 0.0, float* getelementptr inbounds (%class.Vec3, %class.Vec3* @pos, i32 0, i32 0) + %inc.i = fadd float %i.0168.i, 1.0 + %exitcond.i = fcmp oeq float %inc.i, 256.0 + br i1 %exitcond.i, label %for.cond.cleanup4.i, label %for.body5.i + +for.cond.cleanup4.i: + ret void +}