diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 0dc5ae188eb..535e5bd7628 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -935,7 +935,14 @@ RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP, const SlotIndexes &Indexes = *LIS->getSlotIndexes(); for (LiveInterval::SubRange &SA : IntA.subranges()) { VNInfo *ASubValNo = SA.getVNInfoAt(AIdx); - assert(ASubValNo != nullptr); + // Even if we are dealing with a full copy, some lanes can + // still be undefined. + // E.g., + // undef A.subLow = ... + // B = COPY A <== A.subHigh is undefined here and does + // not have a value number. + if (!ASubValNo) + continue; MaskA |= SA.LaneMask; IntB.refineSubRanges( diff --git a/test/CodeGen/SystemZ/regcoal-undef-lane-4-rm-cp-commuting-def.mir b/test/CodeGen/SystemZ/regcoal-undef-lane-4-rm-cp-commuting-def.mir new file mode 100644 index 00000000000..4245dafb00d --- /dev/null +++ b/test/CodeGen/SystemZ/regcoal-undef-lane-4-rm-cp-commuting-def.mir @@ -0,0 +1,131 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -run-pass simple-register-coalescing %s -systemz-subreg-liveness -O3 -mtriple s390x-ibm-linux -mcpu z13 -o - | FileCheck %s +# +# When the coalescing tries to coalesce `%20 = COPY %18`, +# %18 has been coalesced all the way up to %15 = ROSBG. +# ROSBG has tied operands and can be commuted, thus it +# maybe possible to swap the arguments of ROSBG to coalesce +# this copy. That's what the coalescer attempts. +# +# This used to produce an assertion failure in the coalescer, +# because this particular coalescing trick is used only on +# full copy. Therefore we were asserting that all the subranges +# at the point of the copy had a value number. +# This is actually not true in that example, because %18 is +# only partial defined before being fully copied. +# +# PR40215. +--- +name: main +alignment: 4 +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + ; CHECK-LABEL: name: main + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: [[LGHI:%[0-9]+]]:addr64bit = LGHI -30 + ; CHECK: [[LHIMux:%[0-9]+]]:grx32bit = LHIMux 1 + ; CHECK: [[LHIMux1:%[0-9]+]]:grx32bit = LHIMux 0 + ; CHECK: undef %20.subreg_l32:gr64bit = IMPLICIT_DEF + ; CHECK: bb.1: + ; CHECK: successors: %bb.3(0x00000001), %bb.4(0x7fffffff) + ; CHECK: CHIMux [[LHIMux]], 0, implicit-def $cc + ; CHECK: BRC 14, 6, %bb.3, implicit killed $cc + ; CHECK: J %bb.4 + ; CHECK: bb.2: + ; CHECK: successors: + ; CHECK: STMux %20.subreg_l32, undef %8:addr64bit, 0, $noreg :: (store 4 into `i32* undef`) + ; CHECK: bb.3: + ; CHECK: successors: + ; CHECK: bb.4: + ; CHECK: successors: %bb.5(0x30000000), %bb.6(0x50000000) + ; CHECK: [[LAY:%[0-9]+]]:gr64bit = LAY [[LGHI]], 19838, $noreg + ; CHECK: [[LAY1:%[0-9]+]]:gr64bit = LAY [[LGHI]], 19840, $noreg + ; CHECK: [[LAY2:%[0-9]+]]:gr64bit = LAY [[LGHI]], 19844, $noreg + ; CHECK: [[OGR:%[0-9]+]]:gr64bit = OGR [[OGR]], [[LAY]], implicit-def dead $cc + ; CHECK: undef %19.subreg_l32:gr64bit = AHIMuxK [[LGHI]].subreg_l32, 19843, implicit-def dead $cc + ; CHECK: [[ROSBG:%[0-9]+]]:gr64bit = ROSBG [[ROSBG]], [[OGR]], 32, 63, 0, implicit-def dead $cc + ; The coalescer should have been able to swap the operands of + ; the OR, hence eliminating the copy of %20 and %18. + ; This is also visible here because the ROSBG operand was LHS + ; before the coalescer, now it is RHS. + ; CHECK: %20.subreg_l32:gr64bit = OR %20.subreg_l32, [[ROSBG]].subreg_l32, implicit-def dead $cc + ; CHECK: [[ROSBG1:%[0-9]+]]:gr64bit = ROSBG [[ROSBG1]], [[LAY1]], 32, 63, 0, implicit-def dead $cc + ; CHECK: CHIMux [[LHIMux1]], 0, implicit-def $cc + ; CHECK: BRC 14, 6, %bb.6, implicit killed $cc + ; CHECK: J %bb.5 + ; CHECK: bb.5: + ; CHECK: successors: %bb.6(0x80000000) + ; CHECK: bb.6: + ; CHECK: successors: %bb.2(0x00000001), %bb.7(0x7fffffff) + ; CHECK: [[LGHI]]:addr64bit = nuw nsw LA [[LGHI]], 6, $noreg + ; CHECK: CGHI [[LGHI]], 0, implicit-def $cc + ; CHECK: BRC 14, 8, %bb.2, implicit killed $cc + ; CHECK: bb.7: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: J %bb.1 + bb.0: + %6:gr64bit = LGHI -30 + %8:grx32bit = LHIMux 1 + %21:grx32bit = LHIMux 0 + %23:addr64bit = COPY killed %6 + %24:gr32bit = IMPLICIT_DEF + + bb.1: + successors: %bb.3(0x00000001), %bb.4(0x7fffffff) + + %1:gr32bit = COPY killed %24 + %0:addr64bit = COPY killed %23 + CHIMux %8, 0, implicit-def $cc + BRC 14, 6, %bb.3, implicit killed $cc + J %bb.4 + + bb.2: + successors: + + STMux killed %4, undef %22:addr64bit, 0, $noreg :: (store 4 into `i32* undef`) + + bb.3: + successors: + + + bb.4: + successors: %bb.5(0x30000000), %bb.6(0x50000000) + + %2:gr64bit = LAY %0, 19838, $noreg + %3:gr64bit = LAY %0, 19840, $noreg + %9:gr64bit = LAY %0, 19844, $noreg + %10:gr64bit = COPY killed %9 + %10:gr64bit = OGR %10, killed %2, implicit-def dead $cc + %11:gr32bit = COPY %0.subreg_l32 + %12:gr32bit = AHIMuxK killed %11, 19843, implicit-def dead $cc + undef %13.subreg_l32:gr64bit = COPY killed %12 + %15:gr64bit = COPY killed %13 + %15:gr64bit = ROSBG %15, killed %10, 32, 63, 0, implicit-def dead $cc + %16:gr32bit = COPY killed %15.subreg_l32 + %17:gr32bit = COPY killed %16 + %17:gr32bit = OR %17, killed %1, implicit-def dead $cc + undef %18.subreg_l32:gr64bit = COPY killed %17 + %20:gr64bit = COPY killed %18 + %20:gr64bit = ROSBG %20, killed %3, 32, 63, 0, implicit-def dead $cc + CHIMux %21, 0, implicit-def $cc + BRC 14, 6, %bb.6, implicit killed $cc + J %bb.5 + + bb.5: + + bb.6: + successors: %bb.2(0x00000001), %bb.7(0x7fffffff) + + %4:grx32bit = COPY killed %20.subreg_l32 + %5:gr64bit = nuw nsw LA killed %0, 6, $noreg + CGHI %5, 0, implicit-def $cc + BRC 14, 8, %bb.2, implicit killed $cc + + bb.7: + %23:addr64bit = COPY killed %5 + %24:gr32bit = COPY killed %4 + J %bb.1 + +...