[ARM] Guard against WhileLoopStart kill flags
authorDavid Green <david.green@arm.com>
Sat, 29 May 2021 20:04:26 +0000 (21:04 +0100)
committerDavid Green <david.green@arm.com>
Sat, 29 May 2021 20:04:26 +0000 (21:04 +0100)
If the operand of the WhileLoopStart is flagged as killed, that
currently gets propogated to both the t2CMPri as the instruction is
reverted, and the newly created t2DoLoopStart. Only the second should
remain as killing the operand, the first dropping the flags.

llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp
llvm/test/CodeGen/Thumb2/LowOverheadLoops/wls-search-killed.mir [new file with mode: 0644]

index 3ae8187..2aa5d6a 100644 (file)
@@ -290,6 +290,9 @@ MachineInstr *MVETPAndVPTOptimisations::CheckForLRUseInPredecessors(
       MIB.add(LoopStart->getOperand(0));
       MIB.add(LoopStart->getOperand(1));
 
+      // Make sure to remove the kill flags, to prevent them from being invalid.
+      LoopStart->getOperand(1).setIsKill(false);
+
       // Revert the t2WhileLoopStartLR to a CMP and Br.
       RevertWhileLoopStartLR(LoopStart, TII, ARM::t2Bcc, true);
       return MIB;
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/wls-search-killed.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/wls-search-killed.mir
new file mode 100644 (file)
index 0000000..1b4523e
--- /dev/null
@@ -0,0 +1,176 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=thumbv8.1m.main-none-eabi -mattr=+mve %s -run-pass=arm-mve-vpt-opts --verify-machineinstrs -o - | FileCheck %s
+
+--- |
+  target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+  target triple = "thumbv8.1m.main-none-eabi"
+
+  define i32 @test(i64* nocapture %x, i32 %n, i64 %a, i32 %m) {
+  entry:
+    %cmp.not = icmp eq i32 %n, 0
+    %0 = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %n)
+    %1 = extractvalue { i32, i1 } %0, 1
+    %2 = extractvalue { i32, i1 } %0, 0
+    br i1 %1, label %if.then, label %if.end
+
+  if.then:                                          ; preds = %entry
+    %conv = sext i32 %m to i64
+    %div = sdiv i64 %a, %conv
+    %scevgep = getelementptr i64, i64* %x, i32 %m
+    br label %do.body
+
+  do.body:                                          ; preds = %do.body, %if.then
+    %lsr.iv = phi i64* [ %scevgep1, %do.body ], [ %scevgep, %if.then ]
+    %3 = phi i32 [ %2, %if.then ], [ %4, %do.body ]
+    store i64 %div, i64* %lsr.iv, align 8
+    %scevgep1 = getelementptr i64, i64* %lsr.iv, i32 1
+    %4 = call i32 @llvm.loop.decrement.reg.i32(i32 %3, i32 1)
+    %5 = icmp ne i32 %4, 0
+    br i1 %5, label %do.body, label %if.end
+
+  if.end:                                           ; preds = %do.body, %entry
+    ret i32 undef
+  }
+
+  declare { i32, i1 } @llvm.test.start.loop.iterations.i32(i32)
+  declare i32 @llvm.loop.decrement.reg.i32(i32, i32)
+
+...
+---
+name:            test
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gpr, preferred-register: '' }
+  - { id: 1, class: gpr, preferred-register: '' }
+  - { id: 2, class: gpr, preferred-register: '' }
+  - { id: 3, class: gpr, preferred-register: '' }
+  - { id: 4, class: gprnopc, preferred-register: '' }
+  - { id: 5, class: gprlr, preferred-register: '' }
+  - { id: 6, class: gpr, preferred-register: '' }
+  - { id: 7, class: gpr, preferred-register: '' }
+  - { id: 8, class: gprnopc, preferred-register: '' }
+  - { id: 9, class: rgpr, preferred-register: '' }
+  - { id: 10, class: gpr, preferred-register: '' }
+  - { id: 11, class: gpr, preferred-register: '' }
+  - { id: 12, class: gpr, preferred-register: '' }
+  - { id: 13, class: gpr, preferred-register: '' }
+  - { id: 14, class: rgpr, preferred-register: '' }
+  - { id: 15, class: gprlr, preferred-register: '' }
+  - { id: 16, class: rgpr, preferred-register: '' }
+  - { id: 17, class: gpr, preferred-register: '' }
+  - { id: 18, class: gpr, preferred-register: '' }
+  - { id: 19, class: gprnopc, preferred-register: '' }
+  - { id: 20, class: rgpr, preferred-register: '' }
+  - { id: 21, class: gprlr, preferred-register: '' }
+  - { id: 22, class: gprlr, preferred-register: '' }
+  - { id: 23, class: gpr, preferred-register: '' }
+liveins:
+  - { reg: '$r0', virtual-reg: '%8' }
+  - { reg: '$r1', virtual-reg: '%9' }
+  - { reg: '$r2', virtual-reg: '%10' }
+  - { reg: '$r3', virtual-reg: '%11' }
+fixedStack:
+  - { id: 0, type: default, offset: 0, size: 4, alignment: 8, stack-id: default,
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body:             |
+  ; CHECK-LABEL: name: test
+  ; CHECK: bb.0.entry:
+  ; CHECK:   successors: %bb.1(0x40000000), %bb.3(0x40000000)
+  ; CHECK:   liveins: $r0, $r1, $r2, $r3
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr = COPY $r3
+  ; CHECK:   [[COPY1:%[0-9]+]]:gpr = COPY $r2
+  ; CHECK:   [[COPY2:%[0-9]+]]:rgpr = COPY $r1
+  ; CHECK:   [[COPY3:%[0-9]+]]:gprnopc = COPY $r0
+  ; CHECK:   t2CMPri [[COPY2]], 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
+  ; CHECK:   t2Bcc %bb.3, 0 /* CC::eq */, $cpsr
+  ; CHECK:   t2B %bb.1, 14 /* CC::al */, $noreg
+  ; CHECK: bb.1.if.then:
+  ; CHECK:   successors: %bb.2(0x80000000)
+  ; CHECK:   [[COPY4:%[0-9]+]]:gpr = COPY [[COPY]]
+  ; CHECK:   [[COPY5:%[0-9]+]]:gpr = COPY [[COPY1]]
+  ; CHECK:   [[t2LDRi12_:%[0-9]+]]:rgpr = t2LDRi12 %fixed-stack.0, 0, 14 /* CC::al */, $noreg :: (load 4 from %fixed-stack.0, align 8)
+  ; CHECK:   [[t2ASRri:%[0-9]+]]:rgpr = t2ASRri [[t2LDRi12_]], 31, 14 /* CC::al */, $noreg, $noreg
+  ; CHECK:   ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp
+  ; CHECK:   $r0 = COPY [[COPY5]]
+  ; CHECK:   $r1 = COPY [[COPY4]]
+  ; CHECK:   $r2 = COPY [[t2LDRi12_]]
+  ; CHECK:   $r3 = COPY [[t2ASRri]]
+  ; CHECK:   tBL 14 /* CC::al */, $noreg, &__aeabi_ldivmod, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $sp, implicit-def $r0, implicit-def $r1
+  ; CHECK:   ADJCALLSTACKUP 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp
+  ; CHECK:   [[COPY6:%[0-9]+]]:gpr = COPY $r0
+  ; CHECK:   [[COPY7:%[0-9]+]]:gpr = COPY $r1
+  ; CHECK:   [[COPY8:%[0-9]+]]:gpr = COPY [[COPY7]]
+  ; CHECK:   [[COPY9:%[0-9]+]]:gpr = COPY [[COPY6]]
+  ; CHECK:   [[t2ADDrs:%[0-9]+]]:gprnopc = t2ADDrs [[COPY3]], [[t2LDRi12_]], 26, 14 /* CC::al */, $noreg, $noreg
+  ; CHECK:   [[COPY10:%[0-9]+]]:gpr = COPY [[t2ADDrs]]
+  ; CHECK:   [[t2DoLoopStart:%[0-9]+]]:gprlr = t2DoLoopStart killed [[COPY2]]
+  ; CHECK: bb.2.do.body:
+  ; CHECK:   successors: %bb.2(0x7c000000), %bb.3(0x04000000)
+  ; CHECK:   [[PHI:%[0-9]+]]:gprnopc = PHI [[COPY10]], %bb.1, %6, %bb.2
+  ; CHECK:   [[PHI1:%[0-9]+]]:gprlr = PHI [[t2DoLoopStart]], %bb.1, %21, %bb.2
+  ; CHECK:   t2STRi12 [[COPY9]], [[PHI]], 0, 14 /* CC::al */, $noreg :: (store 4 into %ir.lsr.iv, align 8)
+  ; CHECK:   t2STRi12 [[COPY8]], [[PHI]], 4, 14 /* CC::al */, $noreg :: (store 4 into %ir.lsr.iv + 4, basealign 8)
+  ; CHECK:   [[t2ADDri:%[0-9]+]]:rgpr = t2ADDri [[PHI]], 8, 14 /* CC::al */, $noreg, $noreg
+  ; CHECK:   [[COPY11:%[0-9]+]]:gpr = COPY [[t2ADDri]]
+  ; CHECK:   [[t2LoopEndDec:%[0-9]+]]:gprlr = t2LoopEndDec [[PHI1]], %bb.2, implicit-def $cpsr
+  ; CHECK:   t2B %bb.3, 14 /* CC::al */, $noreg
+  ; CHECK: bb.3.if.end:
+  ; CHECK:   [[DEF:%[0-9]+]]:gpr = IMPLICIT_DEF
+  ; CHECK:   $r0 = COPY [[DEF]]
+  ; CHECK:   tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+  bb.0.entry:
+    successors: %bb.1(0x40000000), %bb.3(0x40000000)
+    liveins: $r0, $r1, $r2, $r3
+
+    %11:gpr = COPY $r3
+    %10:gpr = COPY $r2
+    %9:rgpr = COPY $r1
+    %8:gprnopc = COPY $r0
+    %15:gprlr = t2WhileLoopSetup killed %9
+    t2WhileLoopStart %15, %bb.3, implicit-def dead $cpsr
+    t2B %bb.1, 14 /* CC::al */, $noreg
+
+  bb.1.if.then:
+    successors: %bb.2(0x80000000)
+
+    %13:gpr = COPY %11
+    %12:gpr = COPY %10
+    %14:rgpr = t2LDRi12 %fixed-stack.0, 0, 14 /* CC::al */, $noreg :: (load 4 from %fixed-stack.0, align 8)
+    %0:gpr = COPY %15
+    %16:rgpr = t2ASRri %14, 31, 14 /* CC::al */, $noreg, $noreg
+    ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp
+    $r0 = COPY %12
+    $r1 = COPY %13
+    $r2 = COPY %14
+    $r3 = COPY %16
+    tBL 14 /* CC::al */, $noreg, &__aeabi_ldivmod, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $sp, implicit-def $r0, implicit-def $r1
+    ADJCALLSTACKUP 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp
+    %17:gpr = COPY $r0
+    %18:gpr = COPY $r1
+    %2:gpr = COPY %18
+    %1:gpr = COPY %17
+    %19:gprnopc = t2ADDrs %8, %14, 26, 14 /* CC::al */, $noreg, $noreg
+    %3:gpr = COPY %19
+
+  bb.2.do.body:
+    successors: %bb.2(0x7c000000), %bb.3(0x04000000)
+
+    %4:gprnopc = PHI %3, %bb.1, %6, %bb.2
+    %5:gprlr = PHI %0, %bb.1, %7, %bb.2
+    t2STRi12 %1, %4, 0, 14 /* CC::al */, $noreg :: (store 4 into %ir.lsr.iv, align 8)
+    t2STRi12 %2, %4, 4, 14 /* CC::al */, $noreg :: (store 4 into %ir.lsr.iv + 4, basealign 8)
+    %20:rgpr = t2ADDri %4, 8, 14 /* CC::al */, $noreg, $noreg
+    %6:gpr = COPY %20
+    %21:gprlr = t2LoopDec %5, 1
+    %7:gpr = COPY %21
+    t2LoopEnd %21, %bb.2, implicit-def dead $cpsr
+    t2B %bb.3, 14 /* CC::al */, $noreg
+
+  bb.3.if.end:
+    %23:gpr = IMPLICIT_DEF
+    $r0 = COPY %23
+    tBX_RET 14 /* CC::al */, $noreg, implicit $r0
+
+...