From: Craig Topper Date: Tue, 21 Sep 2021 21:35:11 +0000 (-0700) Subject: Recommit "[X86] Clear kill flags when rewriting SETCC uses in flag copy lowering." X-Git-Tag: upstream/15.0.7~30921 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b81e26c7f470ee324095f7adfbe0384974db4375;p=platform%2Fupstream%2Fllvm.git Recommit "[X86] Clear kill flags when rewriting SETCC uses in flag copy lowering." This time with the right bug number. When we rewrite the setcc we replace set old setcc output register with the new CondReg. But since CondReg can be shared by other replacements, we don't know if the kill flags for the old register are valid for CondReg. So be conservative and remove them. The test case has a SETCCr and a SETCCm on the same condition so they end up sharing the same CondReg. The SETCCr had one use with a kill flag. This kill flag isn't valid after the replacement because CondReg needs a live range extending to the later SETCCm replacment. Fixes PR51903. --- diff --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp index 2d9886e..f24dbcf 100644 --- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp +++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp @@ -964,7 +964,11 @@ void X86FlagsCopyLoweringPass::rewriteSetCC(MachineBasicBlock &TestMBB, if (!SetCCI.mayStore()) { assert(SetCCI.getOperand(0).isReg() && "Cannot have a non-register defined operand to SETcc!"); - MRI->replaceRegWith(SetCCI.getOperand(0).getReg(), CondReg); + Register OldReg = SetCCI.getOperand(0).getReg(); + // Drop Kill flags on the old register before replacing. CondReg may have + // a longer live range. + MRI->clearKillFlags(OldReg); + MRI->replaceRegWith(OldReg, CondReg); SetCCI.eraseFromParent(); return; } diff --git a/llvm/test/CodeGen/X86/flags-copy-lowering.mir b/llvm/test/CodeGen/X86/flags-copy-lowering.mir index dfb5f7d..069afd0 100644 --- a/llvm/test/CodeGen/X86/flags-copy-lowering.mir +++ b/llvm/test/CodeGen/X86/flags-copy-lowering.mir @@ -250,10 +250,10 @@ body: | MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %5 ; CHECK-NOT: $eflags = ; CHECK-NOT: = SET{{.*}} - ; CHECK: MOV8mr {{.*}}, killed %[[A_REG]] - ; CHECK-NEXT: MOV8mr {{.*}}, killed %[[B_REG]] - ; CHECK-NEXT: MOV8mr {{.*}}, killed %[[E_REG]] - ; CHECK-NOT: MOV8mr {{.*}}, killed %[[NE_REG]] + ; CHECK: MOV8mr {{.*}}, %[[A_REG]] + ; CHECK-NEXT: MOV8mr {{.*}}, %[[B_REG]] + ; CHECK-NEXT: MOV8mr {{.*}}, %[[E_REG]] + ; CHECK-NOT: MOV8mr {{.*}}, %[[NE_REG]] RET 0 diff --git a/llvm/test/CodeGen/X86/pr51903.mir b/llvm/test/CodeGen/X86/pr51903.mir new file mode 100644 index 0000000..f9d0416 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr51903.mir @@ -0,0 +1,108 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc %s -o - -mtriple=x86_64-unknown-linux-gnu -run-pass=x86-flags-copy-lowering -verify-machineinstrs | FileCheck %s + +--- | + ; ModuleID = 'bugpoint-reduced-simplified.ll' + source_filename = "test.c" + 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" + + @a = external global i32, align 4 + + declare void @e() + + define void @f() { + entry: + br label %for.body + + for.body: ; preds = %for.body, %entry + %0 = load i32, i32* @a, align 4 + %conv = sext i32 %0 to i64 + %1 = load i64, i64* undef, align 8 + %or = or i64 %1, %conv + store i64 %or, i64* undef, align 8 + call void @e() + %cmp4 = icmp eq i64 %or, 0 + %conv5 = zext i1 %cmp4 to i32 + %conv6 = trunc i32 %conv5 to i8 + store i8 %conv6, i8* undef, align 1 + %conv7 = sext i8 %conv6 to i32 + %bf.cast = trunc i40 undef to i32 + %xor = xor i32 %conv7, %bf.cast + %conv8 = sext i32 %xor to i64 + store i64 %conv8, i64* undef, align 8 + br label %for.body + } + +... +--- +name: f +alignment: 16 +tracksRegLiveness: true +registers: + - { id: 0, class: gr64 } + - { id: 1, class: gr64 } + - { id: 2, class: gr32 } + - { id: 3, class: gr64 } + - { id: 4, class: gr32 } + - { id: 5, class: gr32 } + - { id: 6, class: gr32 } + - { id: 7, class: gr64 } + - { id: 8, class: gr64 } + - { id: 9, class: gr64 } + - { id: 10, class: gr64 } + - { id: 11, class: gr8 } + - { id: 12, class: gr64 } +frameInfo: + maxAlignment: 1 + hasCalls: true +machineFunctionInfo: {} +body: | + ; CHECK-LABEL: name: f + ; CHECK: bb.0.entry: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: JMP_1 %bb.1 + ; CHECK: bb.1.for.body: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @a, $noreg :: (load (s64) from got) + ; CHECK: [[MOVSX64rm32_:%[0-9]+]]:gr64 = MOVSX64rm32 killed [[MOV64rm]], 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from @a) + ; CHECK: [[DEF:%[0-9]+]]:gr64 = IMPLICIT_DEF + ; CHECK: OR64mr [[DEF]], 1, $noreg, 0, $noreg, [[MOVSX64rm32_]], implicit-def $eflags :: (store (s64) into `i64* undef`), (load (s64) from `i64* undef`) + ; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 4, implicit $eflags + ; CHECK: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + ; CHECK: CALL64pcrel32 target-flags(x86-plt) @e, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + ; CHECK: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + ; CHECK: [[MOVZX32rr8_:%[0-9]+]]:gr32 = MOVZX32rr8 [[SETCCr]] + ; CHECK: [[DEF1:%[0-9]+]]:gr64 = IMPLICIT_DEF + ; CHECK: MOV8mr [[DEF1]], 1, $noreg, 0, $noreg, [[SETCCr]] :: (store (s8) into `i8* undef`) + ; CHECK: [[DEF2:%[0-9]+]]:gr32 = IMPLICIT_DEF + ; CHECK: [[XOR32rr:%[0-9]+]]:gr32 = XOR32rr [[MOVZX32rr8_]], [[DEF2]], implicit-def $eflags + ; CHECK: [[MOVSX64rr32_:%[0-9]+]]:gr64 = MOVSX64rr32 [[XOR32rr]] + ; CHECK: [[DEF3:%[0-9]+]]:gr64 = IMPLICIT_DEF + ; CHECK: MOV64mr [[DEF3]], 1, $noreg, 0, $noreg, [[MOVSX64rr32_]] :: (store (s64) into `i64* undef`) + ; CHECK: JMP_1 %bb.1 + bb.0.entry: + JMP_1 %bb.1 + + bb.1.for.body: + %7:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @a, $noreg :: (load (s64) from got) + %8:gr64 = MOVSX64rm32 killed %7, 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from @a) + %9:gr64 = IMPLICIT_DEF + OR64mr %9, 1, $noreg, 0, $noreg, %8, implicit-def $eflags :: (store (s64) into `i64* undef`), (load (s64) from `i64* undef`) + %10:gr64 = COPY $eflags + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 target-flags(x86-plt) @e, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $eflags = COPY %10 + %11:gr8 = SETCCr 4, implicit $eflags + %4:gr32 = MOVZX32rr8 killed %11 + %12:gr64 = IMPLICIT_DEF + SETCCm %12, 1, $noreg, 0, $noreg, 4, implicit $eflags :: (store (s8) into `i8* undef`) + %5:gr32 = IMPLICIT_DEF + %6:gr32 = XOR32rr %4, %5, implicit-def $eflags + %3:gr64 = MOVSX64rr32 %6 + %0:gr64 = IMPLICIT_DEF + MOV64mr %0, 1, $noreg, 0, $noreg, %3 :: (store (s64) into `i64* undef`) + JMP_1 %bb.1 + +...