Skip to content

Commit

Permalink
[RISCV] Insert simple landing pad before indirect jumps for Zicfilp. (#…
Browse files Browse the repository at this point in the history
…91860)

This patch is based on #91855.
This patch inserts simple landing pad
([pr])before indirct jumps. And this also make option
riscv-landing-pad-label influence this feature.
[pr]: riscv-non-isa/riscv-elf-psabi-doc#417
  • Loading branch information
yetingk authored Aug 8, 2024
1 parent 3c9e345 commit e80d8e1
Show file tree
Hide file tree
Showing 8 changed files with 275 additions and 5 deletions.
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ add_llvm_target(RISCVCodeGen
RISCVInstrInfo.cpp
RISCVISelDAGToDAG.cpp
RISCVISelLowering.cpp
RISCVLandingPadSetup.cpp
RISCVMachineFunctionInfo.cpp
RISCVMergeBaseOffset.cpp
RISCVOptWInstrs.cpp
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ void initializeRISCVDeadRegisterDefinitionsPass(PassRegistry &);
FunctionPass *createRISCVIndirectBranchTrackingPass();
void initializeRISCVIndirectBranchTrackingPass(PassRegistry &);

FunctionPass *createRISCVLandingPadSetupPass();
void initializeRISCVLandingPadSetupPass(PassRegistry &);

FunctionPass *createRISCVISelDag(RISCVTargetMachine &TM,
CodeGenOptLevel OptLevel);

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

using namespace llvm;

static cl::opt<uint32_t> PreferredLandingPadLabel(
cl::opt<uint32_t> PreferredLandingPadLabel(
"riscv-landing-pad-label", cl::ReallyHidden,
cl::desc("Use preferred fixed label for all labels"));

Expand Down
89 changes: 89 additions & 0 deletions llvm/lib/Target/RISCV/RISCVLandingPadSetup.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//===------------ RISCVLandingPadSetup.cpp ---------------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This is a RISC-V pass to setup landing pad labels for indirect jumps.
// Currently this pass only supports fixed labels.
//
//===----------------------------------------------------------------------===//

#include "RISCV.h"
#include "RISCVInstrInfo.h"
#include "RISCVSubtarget.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/InitializePasses.h"

using namespace llvm;

#define DEBUG_TYPE "riscv-lpad-setup"
#define PASS_NAME "RISC-V Landing Pad Setup"

extern cl::opt<uint32_t> PreferredLandingPadLabel;

namespace {

class RISCVLandingPadSetup : public MachineFunctionPass {
public:
static char ID;

RISCVLandingPadSetup() : MachineFunctionPass(ID) {}

bool runOnMachineFunction(MachineFunction &F) override;

StringRef getPassName() const override { return PASS_NAME; }

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
MachineFunctionPass::getAnalysisUsage(AU);
}
};

} // end anonymous namespace

bool RISCVLandingPadSetup::runOnMachineFunction(MachineFunction &MF) {
const auto &STI = MF.getSubtarget<RISCVSubtarget>();
const RISCVInstrInfo &TII = *STI.getInstrInfo();

if (!STI.hasStdExtZicfilp())
return false;

uint32_t Label = 0;
if (PreferredLandingPadLabel.getNumOccurrences() > 0) {
if (!isUInt<20>(PreferredLandingPadLabel))
report_fatal_error("riscv-landing-pad-label=<val>, <val> needs to fit in "
"unsigned 20-bits");
Label = PreferredLandingPadLabel;
}

// Zicfilp does not check X7 if landing pad label is zero.
if (Label == 0)
return false;

bool Changed = false;
for (MachineBasicBlock &MBB : MF)
for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
if (MI.getOpcode() != RISCV::PseudoBRINDNonX7 &&
MI.getOpcode() != RISCV::PseudoCALLIndirectNonX7 &&
MI.getOpcode() != RISCV::PseudoTAILIndirectNonX7)
continue;
BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(RISCV::LUI), RISCV::X7)
.addImm(Label);
MachineInstrBuilder(MF, &MI).addUse(RISCV::X7, RegState::ImplicitKill);
Changed = true;
}

return Changed;
}

INITIALIZE_PASS(RISCVLandingPadSetup, DEBUG_TYPE, PASS_NAME, false, false)

char RISCVLandingPadSetup::ID = 0;

FunctionPass *llvm::createRISCVLandingPadSetupPass() {
return new RISCVLandingPadSetup();
}
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ void RISCVPassConfig::addPreRegAlloc() {

addPass(createRISCVInsertReadWriteCSRPass());
addPass(createRISCVInsertWriteVXRMPass());
addPass(createRISCVLandingPadSetupPass());

// Run RISCVInsertVSETVLI after PHI elimination. On O1 and above do it after
// register coalescing so needVSETVLIPHI doesn't need to look through COPYs.
Expand Down
1 change: 1 addition & 0 deletions llvm/test/CodeGen/RISCV/O0-pipeline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
; CHECK-NEXT: RISC-V Pre-RA pseudo instruction expansion pass
; CHECK-NEXT: RISC-V Insert Read/Write CSR Pass
; CHECK-NEXT: RISC-V Insert Write VXRM Pass
; CHECK-NEXT: RISC-V Landing Pad Setup
; CHECK-NEXT: Init Undef Pass
; CHECK-NEXT: Eliminate PHI nodes for register allocation
; CHECK-NEXT: Two-Address instruction pass
Expand Down
1 change: 1 addition & 0 deletions llvm/test/CodeGen/RISCV/O3-pipeline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
; CHECK-NEXT: RISC-V Merge Base Offset
; CHECK-NEXT: RISC-V Insert Read/Write CSR Pass
; CHECK-NEXT: RISC-V Insert Write VXRM Pass
; CHECK-NEXT: RISC-V Landing Pad Setup
; CHECK-NEXT: Detect Dead Lanes
; CHECK-NEXT: Init Undef Pass
; CHECK-NEXT: Process Implicit Definitions
Expand Down
182 changes: 178 additions & 4 deletions llvm/test/CodeGen/RISCV/lpad.ll
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp < %s | FileCheck %s --check-prefixes=CHECK,RV32
; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp < %s | FileCheck %s --check-prefixes=CHECK,RV64
; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp \
; RUN: -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=FIXED-ONE,FIXED-ONE-RV32
; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp \
; RUN: -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=FIXED-ONE,FIXED-ONE-RV64

; Check indirectbr.
@__const.indirctbr.addr = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@indirctbr, %labelA), ptr blockaddress(@indirctbr, %labelB)], align 8
Expand All @@ -15,13 +19,13 @@ define void @indirctbr(i32 %i, ptr %p) {
; RV32-NEXT: lw a0, 0(a0)
; RV32-NEXT: jr a0
; RV32-NEXT: .p2align 2
; RV32-NEXT: .Ltmp0: # Block address taken
; RV32-NEXT: .Ltmp3: # Block address taken
; RV32-NEXT: .LBB0_1: # %labelA
; RV32-NEXT: lpad 0
; RV32-NEXT: li a0, 1
; RV32-NEXT: sw a0, 0(a1)
; RV32-NEXT: .p2align 2
; RV32-NEXT: .Ltmp1: # Block address taken
; RV32-NEXT: .Ltmp4: # Block address taken
; RV32-NEXT: .LBB0_2: # %labelB
; RV32-NEXT: lpad 0
; RV32-NEXT: li a0, 2
Expand All @@ -39,18 +43,67 @@ define void @indirctbr(i32 %i, ptr %p) {
; RV64-NEXT: ld a0, 0(a0)
; RV64-NEXT: jr a0
; RV64-NEXT: .p2align 2
; RV64-NEXT: .Ltmp0: # Block address taken
; RV64-NEXT: .Ltmp3: # Block address taken
; RV64-NEXT: .LBB0_1: # %labelA
; RV64-NEXT: lpad 0
; RV64-NEXT: li a0, 1
; RV64-NEXT: sw a0, 0(a1)
; RV64-NEXT: .p2align 2
; RV64-NEXT: .Ltmp1: # Block address taken
; RV64-NEXT: .Ltmp4: # Block address taken
; RV64-NEXT: .LBB0_2: # %labelB
; RV64-NEXT: lpad 0
; RV64-NEXT: li a0, 2
; RV64-NEXT: sw a0, 0(a1)
; RV64-NEXT: ret
;
; FIXED-ONE-RV32-LABEL: indirctbr:
; FIXED-ONE-RV32: # %bb.0: # %entry
; FIXED-ONE-RV32-NEXT: lpad 1
; FIXED-ONE-RV32-NEXT: slli a0, a0, 2
; FIXED-ONE-RV32-NEXT: lui a2, %hi(.L__const.indirctbr.addr)
; FIXED-ONE-RV32-NEXT: addi a2, a2, %lo(.L__const.indirctbr.addr)
; FIXED-ONE-RV32-NEXT: add a0, a2, a0
; FIXED-ONE-RV32-NEXT: lw a0, 0(a0)
; FIXED-ONE-RV32-NEXT: lui t2, 1
; FIXED-ONE-RV32-NEXT: jr a0
; FIXED-ONE-RV32-NEXT: .p2align 2
; FIXED-ONE-RV32-NEXT: .Ltmp3: # Block address taken
; FIXED-ONE-RV32-NEXT: .LBB0_1: # %labelA
; FIXED-ONE-RV32-NEXT: lpad 1
; FIXED-ONE-RV32-NEXT: li a0, 1
; FIXED-ONE-RV32-NEXT: sw a0, 0(a1)
; FIXED-ONE-RV32-NEXT: .p2align 2
; FIXED-ONE-RV32-NEXT: .Ltmp4: # Block address taken
; FIXED-ONE-RV32-NEXT: .LBB0_2: # %labelB
; FIXED-ONE-RV32-NEXT: lpad 1
; FIXED-ONE-RV32-NEXT: li a0, 2
; FIXED-ONE-RV32-NEXT: sw a0, 0(a1)
; FIXED-ONE-RV32-NEXT: ret
;
; FIXED-ONE-RV64-LABEL: indirctbr:
; FIXED-ONE-RV64: # %bb.0: # %entry
; FIXED-ONE-RV64-NEXT: lpad 1
; FIXED-ONE-RV64-NEXT: sext.w a0, a0
; FIXED-ONE-RV64-NEXT: slli a0, a0, 3
; FIXED-ONE-RV64-NEXT: lui a2, %hi(.L__const.indirctbr.addr)
; FIXED-ONE-RV64-NEXT: addi a2, a2, %lo(.L__const.indirctbr.addr)
; FIXED-ONE-RV64-NEXT: add a0, a2, a0
; FIXED-ONE-RV64-NEXT: ld a0, 0(a0)
; FIXED-ONE-RV64-NEXT: lui t2, 1
; FIXED-ONE-RV64-NEXT: jr a0
; FIXED-ONE-RV64-NEXT: .p2align 2
; FIXED-ONE-RV64-NEXT: .Ltmp3: # Block address taken
; FIXED-ONE-RV64-NEXT: .LBB0_1: # %labelA
; FIXED-ONE-RV64-NEXT: lpad 1
; FIXED-ONE-RV64-NEXT: li a0, 1
; FIXED-ONE-RV64-NEXT: sw a0, 0(a1)
; FIXED-ONE-RV64-NEXT: .p2align 2
; FIXED-ONE-RV64-NEXT: .Ltmp4: # Block address taken
; FIXED-ONE-RV64-NEXT: .LBB0_2: # %labelB
; FIXED-ONE-RV64-NEXT: lpad 1
; FIXED-ONE-RV64-NEXT: li a0, 2
; FIXED-ONE-RV64-NEXT: sw a0, 0(a1)
; FIXED-ONE-RV64-NEXT: ret
entry:
%arrayidx = getelementptr inbounds [2 x ptr], ptr @__const.indirctbr.addr, i64 0, i32 %i
%0 = load ptr, ptr %arrayidx
Expand All @@ -65,12 +118,120 @@ labelB: ; preds = %labelA, %entry
ret void
}

; Check indirect call.
define void @call(ptr %0) {
; CHECK-LABEL: call:
; CHECK: # %bb.0:
; CHECK-NEXT: lpad 0
; CHECK-NEXT: jr a0
;
; FIXED-ONE-LABEL: call:
; FIXED-ONE: # %bb.0:
; FIXED-ONE-NEXT: lpad 1
; FIXED-ONE-NEXT: lui t2, 1
; FIXED-ONE-NEXT: jr a0
tail call void %0()
ret void
}

; Check invoke.
declare dso_local i32 @__gxx_personality_v0(...)
define void @invoke(ptr %f) personality ptr @__gxx_personality_v0 {
; RV32-LABEL: invoke:
; RV32: # %bb.0: # %entry
; RV32-NEXT: lpad 0
; RV32-NEXT: addi sp, sp, -16
; RV32-NEXT: .cfi_def_cfa_offset 16
; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32-NEXT: .cfi_offset ra, -4
; RV32-NEXT: .Ltmp0:
; RV32-NEXT: jalr a0
; RV32-NEXT: .Ltmp1:
; RV32-NEXT: .LBB2_1: # %try.cont
; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32-NEXT: addi sp, sp, 16
; RV32-NEXT: ret
; RV32-NEXT: .LBB2_2: # %lpad
; RV32-NEXT: .Ltmp2:
; RV32-NEXT: j .LBB2_1
;
; RV64-LABEL: invoke:
; RV64: # %bb.0: # %entry
; RV64-NEXT: lpad 0
; RV64-NEXT: addi sp, sp, -16
; RV64-NEXT: .cfi_def_cfa_offset 16
; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-NEXT: .cfi_offset ra, -8
; RV64-NEXT: .Ltmp0:
; RV64-NEXT: jalr a0
; RV64-NEXT: .Ltmp1:
; RV64-NEXT: .LBB2_1: # %try.cont
; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-NEXT: addi sp, sp, 16
; RV64-NEXT: ret
; RV64-NEXT: .LBB2_2: # %lpad
; RV64-NEXT: .Ltmp2:
; RV64-NEXT: j .LBB2_1
;
; FIXED-ONE-RV32-LABEL: invoke:
; FIXED-ONE-RV32: # %bb.0: # %entry
; FIXED-ONE-RV32-NEXT: lpad 1
; FIXED-ONE-RV32-NEXT: addi sp, sp, -16
; FIXED-ONE-RV32-NEXT: .cfi_def_cfa_offset 16
; FIXED-ONE-RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; FIXED-ONE-RV32-NEXT: .cfi_offset ra, -4
; FIXED-ONE-RV32-NEXT: .Ltmp0:
; FIXED-ONE-RV32-NEXT: lui t2, 1
; FIXED-ONE-RV32-NEXT: jalr a0
; FIXED-ONE-RV32-NEXT: .Ltmp1:
; FIXED-ONE-RV32-NEXT: .LBB2_1: # %try.cont
; FIXED-ONE-RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; FIXED-ONE-RV32-NEXT: addi sp, sp, 16
; FIXED-ONE-RV32-NEXT: ret
; FIXED-ONE-RV32-NEXT: .LBB2_2: # %lpad
; FIXED-ONE-RV32-NEXT: .Ltmp2:
; FIXED-ONE-RV32-NEXT: j .LBB2_1
;
; FIXED-ONE-RV64-LABEL: invoke:
; FIXED-ONE-RV64: # %bb.0: # %entry
; FIXED-ONE-RV64-NEXT: lpad 1
; FIXED-ONE-RV64-NEXT: addi sp, sp, -16
; FIXED-ONE-RV64-NEXT: .cfi_def_cfa_offset 16
; FIXED-ONE-RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; FIXED-ONE-RV64-NEXT: .cfi_offset ra, -8
; FIXED-ONE-RV64-NEXT: .Ltmp0:
; FIXED-ONE-RV64-NEXT: lui t2, 1
; FIXED-ONE-RV64-NEXT: jalr a0
; FIXED-ONE-RV64-NEXT: .Ltmp1:
; FIXED-ONE-RV64-NEXT: .LBB2_1: # %try.cont
; FIXED-ONE-RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; FIXED-ONE-RV64-NEXT: addi sp, sp, 16
; FIXED-ONE-RV64-NEXT: ret
; FIXED-ONE-RV64-NEXT: .LBB2_2: # %lpad
; FIXED-ONE-RV64-NEXT: .Ltmp2:
; FIXED-ONE-RV64-NEXT: j .LBB2_1
entry:
invoke void %f() to label %try.cont unwind label %lpad

lpad:
%0 = landingpad { ptr, i32 } cleanup
br label %try.cont

try.cont:
ret void
}

; Check external linkage function.
define void @external() {
; CHECK-LABEL: external:
; CHECK: # %bb.0:
; CHECK-NEXT: lpad 0
; CHECK-NEXT: ret
;
; FIXED-ONE-LABEL: external:
; FIXED-ONE: # %bb.0:
; FIXED-ONE-NEXT: lpad 1
; FIXED-ONE-NEXT: ret
ret void
}

Expand All @@ -79,6 +240,10 @@ define internal void @internal() {
; CHECK-LABEL: internal:
; CHECK: # %bb.0:
; CHECK-NEXT: ret
;
; FIXED-ONE-LABEL: internal:
; FIXED-ONE: # %bb.0:
; FIXED-ONE-NEXT: ret
ret void
}

Expand All @@ -89,6 +254,11 @@ define internal void @internal2() {
; CHECK: # %bb.0:
; CHECK-NEXT: lpad 0
; CHECK-NEXT: ret
;
; FIXED-ONE-LABEL: internal2:
; FIXED-ONE: # %bb.0:
; FIXED-ONE-NEXT: lpad 1
; FIXED-ONE-NEXT: ret
ret void
}

Expand All @@ -97,5 +267,9 @@ define void @interrupt() "interrupt"="user" {
; CHECK-LABEL: interrupt:
; CHECK: # %bb.0:
; CHECK-NEXT: mret
;
; FIXED-ONE-LABEL: interrupt:
; FIXED-ONE: # %bb.0:
; FIXED-ONE-NEXT: mret
ret void
}

0 comments on commit e80d8e1

Please sign in to comment.