[llvm-branch-commits] [llvm] f744390 - [Statepoint] Handle `undef` operands in statepoint.
Author: Denis Antrushin Date: 2021-01-18T15:20:54+03:00 New Revision: f7443905af1e06eaacda1e437fff8d54dc89c487 URL: https://github.com/llvm/llvm-project/commit/f7443905af1e06eaacda1e437fff8d54dc89c487 DIFF: https://github.com/llvm/llvm-project/commit/f7443905af1e06eaacda1e437fff8d54dc89c487.diff LOG: [Statepoint] Handle `undef` operands in statepoint. Currently when spilling statepoint register operands in FixupStatepoints we do not pay attention that it might be `undef`. We just generate a spill, which may lead to verifier error because we have a use without def. To handle it, let FixupStateponts ignore `undef` register operands completely and change them to some constant value when generating stack map. Use same value as used by ISel for this purpose (0xFEFEFEFE). Reviewed By: reames Differential Revision: https://reviews.llvm.org/D94703 Added: llvm/test/CodeGen/X86/statepoint-fixup-undef.mir Modified: llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp llvm/lib/CodeGen/StackMaps.cpp Removed: diff --git a/llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp b/llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp index 662bd1a3646f..f8f99b7e87f2 100644 --- a/llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp +++ b/llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp @@ -380,7 +380,9 @@ class StatepointState { EndIdx = MI.getNumOperands(); Idx < EndIdx; ++Idx) { MachineOperand &MO = MI.getOperand(Idx); - if (!MO.isReg() || MO.isImplicit()) + // Leave `undef` operands as is, StackMaps will rewrite them + // into a constant. + if (!MO.isReg() || MO.isImplicit() || MO.isUndef()) continue; Register Reg = MO.getReg(); assert(Reg.isPhysical() && "Only physical regs are expected"); diff --git a/llvm/lib/CodeGen/StackMaps.cpp b/llvm/lib/CodeGen/StackMaps.cpp index 220e85fe90dc..faf07e90c39c 100644 --- a/llvm/lib/CodeGen/StackMaps.cpp +++ b/llvm/lib/CodeGen/StackMaps.cpp @@ -234,6 +234,12 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI, if (MOI->isImplicit()) return ++MOI; +if (MOI->isUndef()) { + // Record `undef` register as constant. Use same value as ISel uses. + Locs.emplace_back(Location::Constant, sizeof(int64_t), 0, 0xFEFEFEFE); + return ++MOI; +} + assert(Register::isPhysicalRegister(MOI->getReg()) && "Virtreg operands should have been rewritten before now."); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(MOI->getReg()); diff --git a/llvm/test/CodeGen/X86/statepoint-fixup-undef.mir b/llvm/test/CodeGen/X86/statepoint-fixup-undef.mir new file mode 100644 index ..434c8400316d --- /dev/null +++ b/llvm/test/CodeGen/X86/statepoint-fixup-undef.mir @@ -0,0 +1,234 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -x mir -run-pass fixup-statepoint-caller-saved -verify-machineinstrs < %s | FileCheck %s +# RUN: llc -x mir -start-before fixup-statepoint-caller-saved -verify-machineinstrs < %s | FileCheck %s -check-prefix=STACKMAP + +--- | + ; ModuleID = 'undef.ll' + source_filename = "test_undef.ll" + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-unknown-linux-gnu" + + define void @test_undef(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3, i8 addrspace(1)* %arg4) #0 gc "statepoint-example" { + bb: +%tmp1 = lshr i32 0, undef +%tmp2 = load atomic i32, i32 addrspace(1)* undef unordered, align 8 +%tmp3 = load atomic i32, i32 addrspace(1)* undef unordered, align 8 +br label %bb7 + + bb7: ; preds = %bb +%tmp4 = icmp slt i32 %tmp3, undef +%tmp5 = select i1 %tmp4, i32 6, i32 undef +%tmp6 = add i32 %tmp5, %tmp2 +%tmp7 = call i8 addrspace(1)* @wombat() +%tmp20 = call token (i64, i32, void (i8 addrspace(1)*, i32, i32, i8 addrspace(1)*, i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i8i32i32p1i8i32f(i64 2, i32 5, void (i8 addrspace(1)*, i32, i32, i8 addrspace(1)*, i32)* nonnull @hoge, i32 5, i32 0, i8 addrspace(1)* %arg3, i32 %tmp2, i32 %tmp6, i8 addrspace(1)* %tmp7, i32 0, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg3, i8 addrspace(1)* %arg4, i32 %tmp2, i32 %tmp1, i32 %tmp5), "gc-live"() ] +ret void + } + + declare void @hoge(i8 addrspace(1)*, i32, i32, i8 addrspace(1)*, i32) #0 + + declare i8 addrspace(1)* @wombat() #0 + + ; Function Attrs: nounwind readonly + declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32 immarg, i32 immarg) #1 + + declare token @llvm.experimental.gc.statepoint.p0f_isVoidp1i8i32i32p1i8i32f(i64 immarg, i32 immarg, void (i8 addrspace(1)*, i32, i32, i8 addrspace(1)*, i32)*, i32 immarg, i32 immarg,
[llvm-branch-commits] [llvm] c5771a2 - [Statepoints] Extract invoke tests into separate file. NFC.
Author: Denis Antrushin Date: 2020-12-16T20:53:28+07:00 New Revision: c5771a2f2df995b312a7d5dfc899d7869d6f26d1 URL: https://github.com/llvm/llvm-project/commit/c5771a2f2df995b312a7d5dfc899d7869d6f26d1 DIFF: https://github.com/llvm/llvm-project/commit/c5771a2f2df995b312a7d5dfc899d7869d6f26d1.diff LOG: [Statepoints] Extract invoke tests into separate file. NFC. Extract VReg lowering tests with invokes into separate file for easier maintenance/modification. Check MIR after register allocation - at this point all transformations we're interested in has been applied and verifying of MIR is simpler than that of assembly. Added: llvm/test/CodeGen/X86/statepoint-vreg-invoke.ll Modified: llvm/test/CodeGen/X86/statepoint-vreg-details.ll llvm/test/CodeGen/X86/statepoint-vreg.ll Removed: diff --git a/llvm/test/CodeGen/X86/statepoint-vreg-details.ll b/llvm/test/CodeGen/X86/statepoint-vreg-details.ll index 5f6f9c7091e4..39ee1506a39e 100644 --- a/llvm/test/CodeGen/X86/statepoint-vreg-details.ll +++ b/llvm/test/CodeGen/X86/statepoint-vreg-details.ll @@ -16,8 +16,6 @@ declare dso_local void @consume(i32 addrspace(1)*) declare dso_local void @consume2(i32 addrspace(1)*, i32 addrspace(1)*) declare dso_local void @consume5(i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*) declare dso_local void @use1(i32 addrspace(1)*, i8 addrspace(1)*) -declare dso_local i32* @fake_personality_function() -declare dso_local i32 @foo(i32, i8 addrspace(1)*, i32, i32, i32) declare dso_local void @bar(i8 addrspace(1)*, i8 addrspace(1)*) ; test most simple relocate @@ -317,46 +315,6 @@ entry: ret void } -; Different IR Values which maps to the same SDValue must be assigned to the same VReg. -; This is test is similar to test_gcptr_uniqueing but explicitly uses invokes for which this is important -; Otherwise we may get a copy of statepoint result, inserted at the end ot statepoint block and used at landing pad -define void @test_duplicate_ir_values() gc "statepoint-example" personality i32* ()* @fake_personality_function{ -;CHECK-VREG-LABEL: name:test_duplicate_ir_values -;CHECK-VREG: bb.0.entry: -;CHECK-VREG: %0:gr64 = STATEPOINT 1, 16, 5, %8, $edi, $rsi, $edx, $ecx, $r8d, 2, 0, 2, 0, 2, 0, 2, 1, killed %1(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def $eax -;CHECK-VREG: JMP_1 %bb.1 -;CHECK-VREG: bb.1.normal_continue: -;CHECK-VREG: MOV64mr %stack.0, 1, $noreg, 0, $noreg, %0 :: (store 8 into %stack.0) -;CHECK-VREG: %13:gr32 = MOV32ri 10 -;CHECK-VREG: $edi = COPY %13 -;CHECK-VREG: STATEPOINT 288240, 0, 1, @__llvm_deoptimize, $edi, 2, 0, 2, 2, 2, 2, 1, 8, %stack.0, 0, 1, 8, %stack.0, 0, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store 8 on %stack.0) -;CHECK-VREG: bb.2.exceptional_return (landing-pad): -;CHECK-VREG: EH_LABEL -;CHECK-VREG: MOV64mr %stack.0, 1, $noreg, 0, $noreg, %0 :: (store 8 into %stack.0) -;CHECK-VREG: %12:gr32 = MOV32ri -271 -;CHECK-VREG: $edi = COPY %12 -;CHECK-VREG: STATEPOINT 288240, 0, 1, @__llvm_deoptimize, $edi, 2, 0, 2, 0, 2, 1, 1, 8, %stack.0, 0, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store 8 on %stack.0) - -entry: - %local.0 = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* undef, align 8 - %local.9 = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* undef, align 8 - %statepoint_token1 = invoke token (i64, i32, i32 (i32, i8 addrspace(1)*, i32, i32, i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32p1i8i32i32i32f(i64 1, i32 16, i32 (i32, i8 addrspace(1)*, i32, i32, i32)* nonnull @foo, i32 5, i32 0, i32 undef, i8 addrspace(1)* undef, i32 undef, i32 undef, i32 undef, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* %local.0, i8 addrspace(1)* %local.9) ] - to label %normal_continue unwind label %exceptional_return - -normal_continue: ; preds = %entry - %local.0.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token1, i32 0, i32 0) ; (%local.0, %local.0) - %local.9.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token1, i32 1, i32 1) ; (%local.9, %local.9) - %safepoint_token2 = call token (i64, i32, void (i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32f(i64 288240, i32 0, void (i32)* nonnull @__llvm_deoptimize, i32 1, i32 2, i32 10, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* %local.0.relocated1, i8 addrspace(1)* %local.9.relocated1), "gc-live"() ] - unreachable - -exceptional_return: ; preds = %entry - %lpad_token11090 = landingpad token - cleanup - %local.9.relocated2 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %lp
[llvm-branch-commits] [llvm] 6f45049 - [Statepoints] Disable VReg lowering for values used on exception path of invoke.
Author: Denis Antrushin Date: 2020-12-21T20:27:05+07:00 New Revision: 6f45049fb6e5c6d573ef5bae338da822f6cbaa53 URL: https://github.com/llvm/llvm-project/commit/6f45049fb6e5c6d573ef5bae338da822f6cbaa53 DIFF: https://github.com/llvm/llvm-project/commit/6f45049fb6e5c6d573ef5bae338da822f6cbaa53.diff LOG: [Statepoints] Disable VReg lowering for values used on exception path of invoke. Currently we lower invokes the same way as usual calls, e.g.: V1 = STATEPOINT ... V (tied-def 0) But this is incorrect is V1 is used on exceptional path. By LLVM rules V1 neither dominates its uses in landing pad, nor its live range is live on entry to landing pad. So compiler is allowed to do various weird transformations like splitting live range after statepoint and use split LR in catch block. Until (and if) we find better solution to this problem, let's use old lowering (spilling) for those values which are used on exceptional path and allow VReg lowering for values used only on normal path. Differential Revision: https://reviews.llvm.org/D93449 Added: Modified: llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp llvm/test/CodeGen/X86/statepoint-vreg-invoke.ll Removed: diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index 2d2eb252e4e2..65ad5b0b5d8f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -546,6 +546,18 @@ lowerStatepointMetaArgs(SmallVectorImpl &Ops, // Decide which deriver pointers will go on VRegs unsigned MaxVRegPtrs = MaxRegistersForGCPointers.getValue(); + // Pointers used on exceptional path of invoke statepoint. + // We cannot assing them to VRegs. + SmallSet LPadPointers; + if (auto *StInvoke = dyn_cast_or_null(SI.StatepointInstr)) { +LandingPadInst *LPI = StInvoke->getLandingPadInst(); +for (auto *Relocate : SI.GCRelocates) + if (Relocate->getOperand(0) == LPI) { +LPadPointers.insert(Builder.getValue(Relocate->getBasePtr())); +LPadPointers.insert(Builder.getValue(Relocate->getDerivedPtr())); + } + } + LLVM_DEBUG(dbgs() << "Deciding how to lower GC Pointers:\n"); // List of unique lowered GC Pointer values. @@ -555,6 +567,14 @@ lowerStatepointMetaArgs(SmallVectorImpl &Ops, unsigned CurNumVRegs = 0; + auto canPassGCPtrOnVReg = [&](SDValue SD) { +if (SD.getValueType().isVector()) + return false; +if (LPadPointers.count(SD)) + return false; +return !willLowerDirectly(SD); + }; + auto processGCPtr = [&](const Value *V) { SDValue PtrSD = Builder.getValue(V); if (!LoweredGCPtrs.insert(PtrSD)) @@ -564,7 +584,9 @@ lowerStatepointMetaArgs(SmallVectorImpl &Ops, assert(!LowerAsVReg.count(PtrSD) && "must not have been seen"); if (LowerAsVReg.size() == MaxVRegPtrs) return; -if (willLowerDirectly(PtrSD) || V->getType()->isVectorTy()) { +assert(V->getType()->isVectorTy() == PtrSD.getValueType().isVector() && + "IR and SD types disagree"); +if (!canPassGCPtrOnVReg(PtrSD)) { LLVM_DEBUG(dbgs() << "direct/spill "; PtrSD.dump(&Builder.DAG)); return; } diff --git a/llvm/test/CodeGen/X86/statepoint-vreg-invoke.ll b/llvm/test/CodeGen/X86/statepoint-vreg-invoke.ll index b734dca622ae..7c5a734acd6a 100644 --- a/llvm/test/CodeGen/X86/statepoint-vreg-invoke.ll +++ b/llvm/test/CodeGen/X86/statepoint-vreg-invoke.ll @@ -10,14 +10,16 @@ declare dso_local i32* @personality_function() define i64 addrspace(1)* @test_basic_invoke(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) ; CHECK-LABEL:name: test_basic_invoke ; CHECK: bb.0.entry: -; CHECK: renamable $r14, renamable $rbx = STATEPOINT 0, 0, 1, @some_call, $rdi, 2, 0, 2, 0, 2, 5, 2, 0, 2, -1, 2, 0, 2, 0, 2, 0, 2, 2, killed renamable $r14(tied-def 0), killed renamable $rbx(tied-def 1), 2, 0, 2, 2, 0, 0, 1, 1, csr_64, implicit-def $rsp, implicit-def $ssp +; CHECK: MOV64mr %stack.1, 1, $noreg, 0, $noreg, renamable $rdi :: (store 8 into %stack.1) +; CHECK: MOV64mr %stack.0, 1, $noreg, 0, $noreg, killed renamable $rsi :: (store 8 into %stack.0) +; CHECK: STATEPOINT 0, 0, 1, @some_call, $rdi, 2, 0, 2, 0, 2, 5, 2, 0, 2, -1, 2, 0, 2, 0, 2, 0, 2, 2, 1, 8, %stack.0, 0, 1, 8, %stack.1, 0, 2, 0, 2, 2, 0, 0, 1, 1, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store 8 on %stack.0), (volatile load store 8 on %stack.1) ; CHECK: JMP_1 %bb.1 ; CHECK: bb.1.safepoint_normal_dest: +; CHECK: renamable $rax = MOV64rm %stack.1, 1, $noreg, 0, $noreg :: (load 8 from %stack.1) ; CHECK: bb.2.normal_return: -; CHECK: $rax = COPY killed renamable $rbx ; CHECK: RET 0, $rax ; CHECK: bb.3.exceptional_return (landing-pad): -; CHECK: $rax = COPY ki