From 58a9482211f8f0be24a72ede2e77cd0c094d9b65 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 28 Jun 2020 10:06:58 -0400 Subject: [PATCH] GlobalISel: Disallow undef generic virtual register uses With an undef operand, it's possible for getVRegDef to fail and return null. This is an edge case very little code bothered to consider. Proper gMIR should use G_IMPLICIT_DEF instead. I initially tried to apply this restriction to all SSA MIR, so then getVRegDef would never fail anywhere. However, ProcessImplicitDefs does technically run while the function is in SSA. ProcessImplicitDefs and DetectDeadLanes would need to either move, or a new pseudo-SSA type of function property would need to be introduced. --- lib/CodeGen/MachineVerifier.cpp | 9 +++++++ .../generic-vreg-undef-use.mir | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 test/MachineVerifier/generic-vreg-undef-use.mir diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index c032b6989c8..d19e295538d 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -1695,6 +1695,15 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { if (!RC) { // This is a generic virtual register. + // Do not allow undef uses for generic virtual registers. This ensures + // getVRegDef can never fail and return null on a generic register. + // + // FIXME: This restriction should probably be broadened to all SSA + // MIR. However, DetectDeadLanes/ProcessImplicitDefs technically still + // run on the SSA function just before phi elimination. + if (MO->isUndef()) + report("Generic virtual register use cannot be undef", MO, MONum); + // If we're post-Select, we can't have gvregs anymore. if (isFunctionSelected) { report("Generic virtual register invalid in a Selected function", diff --git a/test/MachineVerifier/generic-vreg-undef-use.mir b/test/MachineVerifier/generic-vreg-undef-use.mir new file mode 100644 index 00000000000..d35ca618318 --- /dev/null +++ b/test/MachineVerifier/generic-vreg-undef-use.mir @@ -0,0 +1,25 @@ +# RUN: not --crash llc -march=aarch64 -o /dev/null -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: aarch64-registered-target + +# Undef uses are illegal for generic vregs. + +--- +name: test_undef_use +liveins: +body: | + bb.0: + %0:_(s32) = G_CONSTANT i32 0 + + ; Test generic instruction + ; CHECK: *** Bad machine code: Generic virtual register use cannot be undef *** + G_STORE %0, undef %1:_(p0) :: (store 4) + + ; Make sure this fails on a post-isel generic instruction. + ; CHECK: *** Bad machine code: Generic virtual register use cannot be undef *** + $x0 = COPY undef %2:_(s64) + + ; Make sure this fails with a target instruction + ; CHECK: *** Bad machine code: Generic virtual register use cannot be undef *** + RET_ReallyLR implicit $x0, implicit undef %3:_(s32) +... +