Guozhi Wei cbdccb30c2 [RA] Split a virtual register in cold blocks if it is not assigned preferred physical register
If a virtual register is not assigned preferred physical register, it means some
COPY instructions will be changed to real register move instructions. In this
case we can try to split the virtual register in colder blocks, if success, the
original COPY instructions can be deleted, and the new COPY instructions in
colder blocks will be generated as register move instructions. It results in
fewer dynamic register move instructions executed.

The new test case split-reg-with-hint.ll gives an example, the hot path contains
24 instructions without this patch, now it is only 4 instructions with this
patch.

Differential Revision: https://reviews.llvm.org/D156491
2023-09-15 19:52:50 +00:00

137 lines
4.2 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -verify-machineinstrs -mtriple=arm-unknown-linux < %s | FileCheck %s
; Check CSR split can work properly for tests below.
@a = common dso_local local_unnamed_addr global i32 0, align 4
define dso_local signext i32 @test1(ptr %b) local_unnamed_addr {
; CHECK-LABEL: test1:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: ldr r1, .LCPI0_0
; CHECK-NEXT: ldr r1, [r1]
; CHECK-NEXT: cmp r1, r0
; CHECK-NEXT: movne pc, lr
; CHECK-NEXT: .LBB0_1: @ %if.then
; CHECK-NEXT: push {r4, lr}
; CHECK-NEXT: mov r4, r0
; CHECK-NEXT: bl callVoid
; CHECK-NEXT: mov r0, r4
; CHECK-NEXT: pop {r4, lr}
; CHECK-NEXT: b callNonVoid
; CHECK-NEXT: .p2align 2
; CHECK-NEXT: @ %bb.2:
; CHECK-NEXT: .LCPI0_0:
; CHECK-NEXT: .long a
entry:
%0 = load i32, ptr @a, align 4, !tbaa !2
%conv = sext i32 %0 to i64
%1 = inttoptr i64 %conv to ptr
%cmp = icmp eq ptr %1, %b
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
%call = tail call signext i32 @callVoid()
%call2 = tail call signext i32 @callNonVoid(ptr %b)
br label %if.end
if.end: ; preds = %if.then, %entry
%retval.0 = phi i32 [ %call2, %if.then ], [ undef, %entry ]
ret i32 %retval.0
}
declare signext i32 @callVoid(...) local_unnamed_addr
declare signext i32 @callNonVoid(ptr) local_unnamed_addr
define dso_local signext i32 @test2(ptr %p1) local_unnamed_addr {
; CHECK-LABEL: test2:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: cmp r0, #0
; CHECK-NEXT: beq .LBB1_2
; CHECK-NEXT: @ %bb.1: @ %if.end
; CHECK-NEXT: ldr r1, .LCPI1_0
; CHECK-NEXT: ldr r1, [r1]
; CHECK-NEXT: cmp r1, r0
; CHECK-NEXT: beq .LBB1_3
; CHECK-NEXT: .LBB1_2: @ %return
; CHECK-NEXT: mov r0, #0
; CHECK-NEXT: mov pc, lr
; CHECK-NEXT: .LBB1_3: @ %if.then2
; CHECK-NEXT: push {r4, lr}
; CHECK-NEXT: mov r4, r0
; CHECK-NEXT: bl callVoid
; CHECK-NEXT: mov r0, r4
; CHECK-NEXT: pop {r4, lr}
; CHECK-NEXT: b callNonVoid
; CHECK-NEXT: .p2align 2
; CHECK-NEXT: @ %bb.4:
; CHECK-NEXT: .LCPI1_0:
; CHECK-NEXT: .long a
entry:
%tobool = icmp eq ptr %p1, null
br i1 %tobool, label %return, label %if.end
if.end: ; preds = %entry
%0 = load i32, ptr @a, align 4, !tbaa !2
%conv = sext i32 %0 to i64
%1 = inttoptr i64 %conv to ptr
%cmp = icmp eq ptr %1, %p1
br i1 %cmp, label %if.then2, label %return
if.then2: ; preds = %if.end
%call = tail call signext i32 @callVoid()
%call3 = tail call signext i32 @callNonVoid(ptr nonnull %p1)
br label %return
return: ; preds = %if.end, %entry, %if.then2
%retval.0 = phi i32 [ %call3, %if.then2 ], [ 0, %entry ], [ 0, %if.end ]
ret i32 %retval.0
}
define dso_local ptr @test3(ptr nocapture %p1, i8 zeroext %p2) local_unnamed_addr {
; CHECK-LABEL: test3:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: push {r4, r5, r11, lr}
; CHECK-NEXT: ldr r4, [r0]
; CHECK-NEXT: cmp r4, #0
; CHECK-NEXT: beq .LBB2_2
; CHECK-NEXT: @ %bb.1: @ %land.rhs
; CHECK-NEXT: mov r5, r0
; CHECK-NEXT: mov r0, r4
; CHECK-NEXT: bl bar
; CHECK-NEXT: str r0, [r5]
; CHECK-NEXT: .LBB2_2: @ %land.end
; CHECK-NEXT: mov r0, r4
; CHECK-NEXT: pop {r4, r5, r11, lr}
; CHECK-NEXT: mov pc, lr
entry:
%0 = load ptr, ptr %p1, align 8, !tbaa !6
%tobool = icmp eq ptr %0, null
br i1 %tobool, label %land.end, label %land.rhs
land.rhs: ; preds = %entry
%call = tail call ptr @bar(ptr nonnull %0, i8 zeroext %p2)
store ptr %call, ptr %p1, align 8, !tbaa !6
br label %land.end
land.end: ; preds = %entry, %land.rhs
ret ptr %0
}
declare ptr @bar(ptr, i8 zeroext) local_unnamed_addr
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 10.0.0 (trunk 367381) (llvm/trunk 367388)"}
!2 = !{!3, !3, i64 0}
!3 = !{!"int", !4, i64 0}
!4 = !{!"omnipotent char", !5, i64 0}
!5 = !{!"Simple C/C++ TBAA"}
!6 = !{!7, !7, i64 0}
!7 = !{!"any pointer", !4, i64 0}