Skip to content

Commit

Permalink
MIPS: Support -m(no-)unaligned-access for r6 (#85174)
Browse files Browse the repository at this point in the history
MIPSr6 ISA requires normal load/store instructions support
misunaligned memory access, while it is not always do so
by hardware. On some microarchitectures or some corner cases
it may need support by OS.

Don't confuse with pre-R6's lwl/lwr famlily: MIPSr6 doesn't
support them, instead, r6 requires lw instruction support
misunaligned memory access. So, if -mstrict-align is used for
pre-R6, lwl/lwr won't be disabled.

If -mstrict-align is used for r6 and the access is not well
aligned, some lb/lh instructions will be used to replace lw.
This is useful for OS kernels.

To be back-compatible with GCC, -m(no-)unaligned-access are also
added as Neg-Alias of -m(no-)strict-align.
  • Loading branch information
wzssyqa committed Mar 20, 2024
1 parent 6960ace commit d7e28cd
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 13 deletions.
4 changes: 2 additions & 2 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4704,9 +4704,9 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group<m_Group>,
" (RISC-V only)")>;

def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32 only)">;
HelpText<"Allow memory accesses to be unaligned (AArch32/MIPSr6 only)">;
def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_Group>,
HelpText<"Force all memory accesses to be aligned (AArch32 only)">;
HelpText<"Force all memory accesses to be aligned (AArch32/MIPSr6 only)">;
def munaligned_symbols : Flag<["-"], "munaligned-symbols">, Group<m_Group>,
HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">;
def mno_unaligned_symbols : Flag<["-"], "mno-unaligned-symbols">, Group<m_Group>,
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/Mips.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,15 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
"dspr2");
AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
"msa");
if (Arg *A = Args.getLastArg(
options::OPT_mstrict_align, options::OPT_mno_strict_align,
options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
if (A->getOption().matches(options::OPT_mstrict_align) ||
A->getOption().matches(options::OPT_mno_unaligned_access))
Features.push_back(Args.MakeArgString("+strict-align"));
else
Features.push_back(Args.MakeArgString("-strict-align"));
}

// Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
// pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
Expand Down
26 changes: 26 additions & 0 deletions clang/test/Driver/mips-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -462,3 +462,29 @@
// RUN: -mrelax-pic-calls -mno-relax-pic-calls 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-RELAX-PIC-CALLS %s
// CHECK-NO-RELAX-PIC-CALLS: "-mllvm" "-mips-jalr-reloc=0"
//
// -mno-unaligned-access
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -munaligned-access -mno-strict-align \
// RUN: -mno-unaligned-access 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-STRICT-ALIGN %s
// CHECK-STRICT-ALIGN: "-target-feature" "+strict-align"
//
// -munaligned-access
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mno-unaligned-access -mstrict-align \
// RUN: -munaligned-access 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-STRICT-ALIGN %s
// CHECK-NO-STRICT-ALIGN: "-target-feature" "-strict-align"
//
// -mstrict-align
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -munaligned-access -mno-strict-align \
// RUN: -mstrict-align 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-STRICT-ALIGN %s
//
// -mno-strict-align
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mno-unaligned-access -mstrict-align \
// RUN: -mno-strict-align 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-STRICT-ALIGN %s
4 changes: 4 additions & 0 deletions llvm/lib/Target/Mips/Mips.td
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ def FeatureUseIndirectJumpsHazard : SubtargetFeature<"use-indirect-jump-hazard",
"true", "Use indirect jump"
" guards to prevent certain speculation based attacks">;

def FeatureStrictAlign
: SubtargetFeature<"strict-align", "StrictAlign", "true",
"Disable unaligned load store for r6">;

//===----------------------------------------------------------------------===//
// Register File, Calling Conv, Instruction Descriptions
//===----------------------------------------------------------------------===//
Expand Down
16 changes: 13 additions & 3 deletions llvm/lib/Target/Mips/MipsISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,13 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
setOperationAction(ISD::SELECT, MVT::i64, Custom);
setOperationAction(ISD::LOAD, MVT::i64, Custom);
setOperationAction(ISD::STORE, MVT::i64, Custom);
if (Subtarget.hasMips64r6()) {
setOperationAction(ISD::LOAD, MVT::i64, Legal);
setOperationAction(ISD::STORE, MVT::i64, Legal);
} else {
setOperationAction(ISD::LOAD, MVT::i64, Custom);
setOperationAction(ISD::STORE, MVT::i64, Custom);
}
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom);
setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom);
Expand Down Expand Up @@ -481,7 +486,12 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
if (!Subtarget.hasMips64r2())
setOperationAction(ISD::BSWAP, MVT::i64, Expand);

if (Subtarget.isGP64bit()) {
if (Subtarget.isGP64bit() && Subtarget.hasMips64r6()) {
setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Legal);
setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Legal);
setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Legal);
setTruncStoreAction(MVT::i64, MVT::i32, Legal);
} else if (Subtarget.isGP64bit()) {
setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom);
setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom);
setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom);
Expand Down
11 changes: 9 additions & 2 deletions llvm/lib/Target/Mips/MipsSEISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,13 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
setOperationAction(ISD::LOAD, MVT::i32, Custom);
setOperationAction(ISD::STORE, MVT::i32, Custom);
if (Subtarget.hasMips32r6()) {
setOperationAction(ISD::LOAD, MVT::i32, Legal);
setOperationAction(ISD::STORE, MVT::i32, Legal);
} else {
setOperationAction(ISD::LOAD, MVT::i32, Custom);
setOperationAction(ISD::STORE, MVT::i32, Custom);
}

setTargetDAGCombine(ISD::MUL);

Expand Down Expand Up @@ -425,6 +430,8 @@ bool MipsSETargetLowering::allowsMisalignedMemoryAccesses(
if (Fast)
*Fast = 1;
return true;
} else if (Subtarget.hasMips32r6()) {
return false;
}

switch (SVT) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/Mips/MipsSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 || Mips_Os16),
Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false),
HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false),
HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false),
HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false), StrictAlign(false),
StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT),
TSInfo(), InstrInfo(MipsInstrInfo::create(
initializeSubtargetDependencies(CPU, FS, TM))),
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/Mips/MipsSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
// Assume 32-bit GOT.
bool UseXGOT = false;

// Disable unaligned load store for r6.
bool StrictAlign;

/// The minimum alignment known to hold of the stack frame on
/// entry to the function and which must be maintained by every function.
Align stackAlignment;
Expand Down Expand Up @@ -372,7 +375,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
/// MIPS32r6/MIPS64r6 require full unaligned access support but does not
/// specify which component of the system provides it. Hardware, software, and
/// hybrid implementations are all valid.
bool systemSupportsUnalignedAccess() const { return hasMips32r6(); }
bool systemSupportsUnalignedAccess() const {
return hasMips32r6() && !StrictAlign;
}

// Set helper classes
void setHelperClassesMips16();
Expand Down
10 changes: 6 additions & 4 deletions llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,9 @@ define void @uitofp(i32 %a) {
; MIPS64-N32-NEXT: addiu $1, $1, %lo(%neg(%gp_rel(uitofp)))
; MIPS64-N32-NEXT: lui $2, 17200
; MIPS64-N32-NEXT: sw $2, 12($sp)
; MIPS64-N32-NEXT: sll $2, $4, 0
; MIPS64-N32-NEXT: sw $2, 8($sp)
; MIPS64R5-N32-NEXT: sll $2, $4, 0
; MIPS64R5-N32-NEXT: sw $2, 8($sp)
; MIPSR6-N32-NEXT: sw $4, 8($sp)
; MIPS64-N32-NEXT: lw $2, %got_page(.LCPI5_0)($1)
; MIPS64-N32-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2)
; MIPS64-N32-NEXT: ldc1 $f1, 8($sp)
Expand All @@ -430,8 +431,9 @@ define void @uitofp(i32 %a) {
; MIPS64-N64-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(uitofp)))
; MIPS64-N64-NEXT: lui $2, 17200
; MIPS64-N64-NEXT: sw $2, 12($sp)
; MIPS64-N64-NEXT: sll $2, $4, 0
; MIPS64-N64-NEXT: sw $2, 8($sp)
; MIPS64R5-N64-NEXT: sll $2, $4, 0
; MIPS64R5-N64-NEXT: sw $2, 8($sp)
; MIPSR6-N64-NEXT: sw $4, 8($sp)
; MIPS64-N64-NEXT: ld $2, %got_page(.LCPI5_0)($1)
; MIPS64-N64-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2)
; MIPS64-N64-NEXT: ldc1 $f1, 8($sp)
Expand Down
69 changes: 69 additions & 0 deletions llvm/test/CodeGen/Mips/no-unaligned-access-r6.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
;; Test the strict-align feature which is similar to AArch64/arm64-strict-align.ll.

; RUN: llc --mtriple=mipsisa32r6 < %s | FileCheck %s --check-prefix=MIPS32R6-UNALIGNED
; RUN: llc --mtriple=mipsisa32r6 --mattr=-strict-align < %s | FileCheck %s --check-prefix=MIPS32R6-UNALIGNED
; RUN: llc --mtriple=mipsisa32r6 --mattr=+strict-align < %s | FileCheck %s --check-prefix=MIPS32R6-ALIGNED

; RUN: llc --mtriple=mipsisa64r6 < %s | FileCheck %s --check-prefix=MIPS64R6-UNALIGNED
; RUN: llc --mtriple=mipsisa64r6 --mattr=-strict-align < %s | FileCheck %s --check-prefix=MIPS64R6-UNALIGNED
; RUN: llc --mtriple=mipsisa64r6 --mattr=+strict-align < %s | FileCheck %s --check-prefix=MIPS64R6-ALIGNED

define i32 @f0(ptr %p) nounwind {
; MIPS32R6-UNALIGNED-LABEL: f0:
; MIPS32R6-UNALIGNED: # %bb.0:
; MIPS32R6-UNALIGNED-NEXT: lw $2, 0($4)
; MIPS32R6-UNALIGNED-NEXT: jrc $ra
;
; MIPS32R6-ALIGNED-LABEL: f0:
; MIPS32R6-ALIGNED: # %bb.0:
; MIPS32R6-ALIGNED-NEXT: lhu $1, 2($4)
; MIPS32R6-ALIGNED-NEXT: lhu $2, 0($4)
; MIPS32R6-ALIGNED-NEXT: sll $2, $2, 16
; MIPS32R6-ALIGNED-NEXT: jr $ra
; MIPS32R6-ALIGNED-NEXT: or $2, $2, $1
;
; MIPS64R6-UNALIGNED-LABEL: f0:
; MIPS64R6-UNALIGNED: # %bb.0:
; MIPS64R6-UNALIGNED-NEXT: lw $2, 0($4)
; MIPS64R6-UNALIGNED-NEXT: jrc $ra
;
; MIPS64R6-ALIGNED-LABEL: f0:
; MIPS64R6-ALIGNED: # %bb.0:
; MIPS64R6-ALIGNED-NEXT: lhu $1, 2($4)
; MIPS64R6-ALIGNED-NEXT: lhu $2, 0($4)
; MIPS64R6-ALIGNED-NEXT: sll $2, $2, 16
; MIPS64R6-ALIGNED-NEXT: jr $ra
; MIPS64R6-ALIGNED-NEXT: or $2, $2, $1
%tmp = load i32, ptr %p, align 2
ret i32 %tmp
}

define i64 @f1(ptr %p) nounwind {
; MIPS32R6-UNALIGNED-LABEL: f1:
; MIPS32R6-UNALIGNED: # %bb.0:
; MIPS32R6-UNALIGNED-NEXT: lw $2, 0($4)
; MIPS32R6-UNALIGNED-NEXT: lw $3, 4($4)
; MIPS32R6-UNALIGNED-NEXT: jrc $ra
;
; MIPS32R6-ALIGNED-LABEL: f1:
; MIPS32R6-ALIGNED: # %bb.0:
; MIPS32R6-ALIGNED-NEXT: lw $2, 0($4)
; MIPS32R6-ALIGNED-NEXT: lw $3, 4($4)
; MIPS32R6-ALIGNED-NEXT: jrc $ra
;
; MIPS64R6-UNALIGNED-LABEL: f1:
; MIPS64R6-UNALIGNED: # %bb.0:
; MIPS64R6-UNALIGNED-NEXT: ld $2, 0($4)
; MIPS64R6-UNALIGNED-NEXT: jrc $ra
;
; MIPS64R6-ALIGNED-LABEL: f1:
; MIPS64R6-ALIGNED: # %bb.0:
; MIPS64R6-ALIGNED-NEXT: lwu $1, 4($4)
; MIPS64R6-ALIGNED-NEXT: lwu $2, 0($4)
; MIPS64R6-ALIGNED-NEXT: dsll $2, $2, 32
; MIPS64R6-ALIGNED-NEXT: jr $ra
; MIPS64R6-ALIGNED-NEXT: or $2, $2, $1
%tmp = load i64, ptr %p, align 4
ret i64 %tmp
}

0 comments on commit d7e28cd

Please sign in to comment.