Since the `RISCVExpandPseudo` pass has been split from `RISCVExpandAtomicPseudo` pass, it would be nice to run the former as early as possible (The latter has to be run as late as possible to ensure correctness). Running earlier means we can reschedule these pairs as we see fit. Running earlier in the machine pass pipeline is good, but would mean teaching many more passes about `hasLabelMustBeEmitted`. Splitting the basic blocks also pessimises possible optimisations because some optimisations are MBB-local, and others are disabled if the block has its address taken (which is notionally what `hasLabelMustBeEmitted` means). This patch uses a new approach of setting the pre-instruction symbol on the AUIPC instruction to a temporary symbol and referencing that. This avoids splitting the basic block, but allows us to reference exactly the instruction that we need to. Notionally, this approach seems more correct because we do actually want to address a specific instruction. This then allows the pass to be moved much earlier in the pass pipeline, before both scheduling and register allocation. However, to do so we must leave the MIR in SSA form (by not redefining registers), and so use a virtual register for the intermediate value. By using this virtual register, this pass now has to come before register allocation. Reviewed By: luismarques, asb Differential Revision: https://reviews.llvm.org/D82988
153 lines
4.9 KiB
LLVM
153 lines
4.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=riscv32 -mattr=+f -code-model=small -verify-machineinstrs < %s \
|
|
; RUN: | FileCheck %s -check-prefix=RV32I-SMALL
|
|
; RUN: llc -mtriple=riscv32 -mattr=+f -code-model=medium -verify-machineinstrs < %s \
|
|
; RUN: | FileCheck %s -check-prefix=RV32I-MEDIUM
|
|
|
|
; Check lowering of globals
|
|
@G = global i32 0
|
|
|
|
define i32 @lower_global(i32 %a) nounwind {
|
|
; RV32I-SMALL-LABEL: lower_global:
|
|
; RV32I-SMALL: # %bb.0:
|
|
; RV32I-SMALL-NEXT: lui a0, %hi(G)
|
|
; RV32I-SMALL-NEXT: lw a0, %lo(G)(a0)
|
|
; RV32I-SMALL-NEXT: ret
|
|
;
|
|
; RV32I-MEDIUM-LABEL: lower_global:
|
|
; RV32I-MEDIUM: # %bb.0:
|
|
; RV32I-MEDIUM-NEXT: .Ltmp0:
|
|
; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(G)
|
|
; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Ltmp0)
|
|
; RV32I-MEDIUM-NEXT: lw a0, 0(a0)
|
|
; RV32I-MEDIUM-NEXT: ret
|
|
%1 = load volatile i32, i32* @G
|
|
ret i32 %1
|
|
}
|
|
|
|
; Check lowering of blockaddresses
|
|
|
|
@addr = global i8* null
|
|
|
|
define void @lower_blockaddress() nounwind {
|
|
; RV32I-SMALL-LABEL: lower_blockaddress:
|
|
; RV32I-SMALL: # %bb.0:
|
|
; RV32I-SMALL-NEXT: lui a0, %hi(addr)
|
|
; RV32I-SMALL-NEXT: addi a1, zero, 1
|
|
; RV32I-SMALL-NEXT: sw a1, %lo(addr)(a0)
|
|
; RV32I-SMALL-NEXT: ret
|
|
;
|
|
; RV32I-MEDIUM-LABEL: lower_blockaddress:
|
|
; RV32I-MEDIUM: # %bb.0:
|
|
; RV32I-MEDIUM-NEXT: .Ltmp1:
|
|
; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(addr)
|
|
; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Ltmp1)
|
|
; RV32I-MEDIUM-NEXT: addi a1, zero, 1
|
|
; RV32I-MEDIUM-NEXT: sw a1, 0(a0)
|
|
; RV32I-MEDIUM-NEXT: ret
|
|
store volatile i8* blockaddress(@lower_blockaddress, %block), i8** @addr
|
|
ret void
|
|
|
|
block:
|
|
unreachable
|
|
}
|
|
|
|
; Check lowering of blockaddress that forces a displacement to be added
|
|
|
|
define signext i32 @lower_blockaddress_displ(i32 signext %w) nounwind {
|
|
; RV32I-SMALL-LABEL: lower_blockaddress_displ:
|
|
; RV32I-SMALL: # %bb.0: # %entry
|
|
; RV32I-SMALL-NEXT: addi sp, sp, -16
|
|
; RV32I-SMALL-NEXT: sw ra, 12(sp)
|
|
; RV32I-SMALL-NEXT: lui a1, %hi(.Ltmp0)
|
|
; RV32I-SMALL-NEXT: addi a1, a1, %lo(.Ltmp0)
|
|
; RV32I-SMALL-NEXT: addi a2, zero, 101
|
|
; RV32I-SMALL-NEXT: sw a1, 8(sp)
|
|
; RV32I-SMALL-NEXT: blt a0, a2, .LBB2_3
|
|
; RV32I-SMALL-NEXT: # %bb.1: # %if.then
|
|
; RV32I-SMALL-NEXT: lw a0, 8(sp)
|
|
; RV32I-SMALL-NEXT: jr a0
|
|
; RV32I-SMALL-NEXT: .Ltmp0: # Block address taken
|
|
; RV32I-SMALL-NEXT: .LBB2_2: # %return
|
|
; RV32I-SMALL-NEXT: addi a0, zero, 4
|
|
; RV32I-SMALL-NEXT: j .LBB2_4
|
|
; RV32I-SMALL-NEXT: .LBB2_3: # %return.clone
|
|
; RV32I-SMALL-NEXT: addi a0, zero, 3
|
|
; RV32I-SMALL-NEXT: .LBB2_4: # %.split
|
|
; RV32I-SMALL-NEXT: lw ra, 12(sp)
|
|
; RV32I-SMALL-NEXT: addi sp, sp, 16
|
|
; RV32I-SMALL-NEXT: ret
|
|
;
|
|
; RV32I-MEDIUM-LABEL: lower_blockaddress_displ:
|
|
; RV32I-MEDIUM: # %bb.0: # %entry
|
|
; RV32I-MEDIUM-NEXT: addi sp, sp, -16
|
|
; RV32I-MEDIUM-NEXT: sw ra, 12(sp)
|
|
; RV32I-MEDIUM-NEXT: .Ltmp2:
|
|
; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(.Ltmp3)
|
|
; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Ltmp2)
|
|
; RV32I-MEDIUM-NEXT: addi a2, zero, 101
|
|
; RV32I-MEDIUM-NEXT: sw a1, 8(sp)
|
|
; RV32I-MEDIUM-NEXT: blt a0, a2, .LBB2_3
|
|
; RV32I-MEDIUM-NEXT: # %bb.1: # %if.then
|
|
; RV32I-MEDIUM-NEXT: lw a0, 8(sp)
|
|
; RV32I-MEDIUM-NEXT: jr a0
|
|
; RV32I-MEDIUM-NEXT: .Ltmp3: # Block address taken
|
|
; RV32I-MEDIUM-NEXT: .LBB2_2: # %return
|
|
; RV32I-MEDIUM-NEXT: addi a0, zero, 4
|
|
; RV32I-MEDIUM-NEXT: j .LBB2_4
|
|
; RV32I-MEDIUM-NEXT: .LBB2_3: # %return.clone
|
|
; RV32I-MEDIUM-NEXT: addi a0, zero, 3
|
|
; RV32I-MEDIUM-NEXT: .LBB2_4: # %.split
|
|
; RV32I-MEDIUM-NEXT: lw ra, 12(sp)
|
|
; RV32I-MEDIUM-NEXT: addi sp, sp, 16
|
|
; RV32I-MEDIUM-NEXT: ret
|
|
entry:
|
|
%x = alloca i8*, align 8
|
|
store i8* blockaddress(@lower_blockaddress_displ, %test_block), i8** %x, align 8
|
|
%cmp = icmp sgt i32 %w, 100
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
%addr = load i8*, i8** %x, align 8
|
|
br label %indirectgoto
|
|
|
|
if.end:
|
|
br label %return
|
|
|
|
test_block:
|
|
br label %return
|
|
|
|
return:
|
|
%retval = phi i32 [ 3, %if.end ], [ 4, %test_block ]
|
|
ret i32 %retval
|
|
|
|
indirectgoto:
|
|
indirectbr i8* %addr, [ label %test_block ]
|
|
}
|
|
|
|
; Check lowering of constantpools
|
|
|
|
define float @lower_constantpool(float %a) nounwind {
|
|
; RV32I-SMALL-LABEL: lower_constantpool:
|
|
; RV32I-SMALL: # %bb.0:
|
|
; RV32I-SMALL-NEXT: lui a1, %hi(.LCPI3_0)
|
|
; RV32I-SMALL-NEXT: flw ft0, %lo(.LCPI3_0)(a1)
|
|
; RV32I-SMALL-NEXT: fmv.w.x ft1, a0
|
|
; RV32I-SMALL-NEXT: fadd.s ft0, ft1, ft0
|
|
; RV32I-SMALL-NEXT: fmv.x.w a0, ft0
|
|
; RV32I-SMALL-NEXT: ret
|
|
;
|
|
; RV32I-MEDIUM-LABEL: lower_constantpool:
|
|
; RV32I-MEDIUM: # %bb.0:
|
|
; RV32I-MEDIUM-NEXT: .Ltmp4:
|
|
; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(.LCPI3_0)
|
|
; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Ltmp4)
|
|
; RV32I-MEDIUM-NEXT: flw ft0, 0(a1)
|
|
; RV32I-MEDIUM-NEXT: fmv.w.x ft1, a0
|
|
; RV32I-MEDIUM-NEXT: fadd.s ft0, ft1, ft0
|
|
; RV32I-MEDIUM-NEXT: fmv.x.w a0, ft0
|
|
; RV32I-MEDIUM-NEXT: ret
|
|
%1 = fadd float %a, 1.0
|
|
ret float %1
|
|
}
|