Skip to content

Commit d7e28cd

Browse files
authored
MIPS: Support -m(no-)unaligned-access for r6 (#85174)
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.
1 parent 6960ace commit d7e28cd

File tree

10 files changed

+145
-13
lines changed

10 files changed

+145
-13
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4704,9 +4704,9 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group<m_Group>,
47044704
" (RISC-V only)")>;
47054705

47064706
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>,
4707-
HelpText<"Allow memory accesses to be unaligned (AArch32 only)">;
4707+
HelpText<"Allow memory accesses to be unaligned (AArch32/MIPSr6 only)">;
47084708
def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_Group>,
4709-
HelpText<"Force all memory accesses to be aligned (AArch32 only)">;
4709+
HelpText<"Force all memory accesses to be aligned (AArch32/MIPSr6 only)">;
47104710
def munaligned_symbols : Flag<["-"], "munaligned-symbols">, Group<m_Group>,
47114711
HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">;
47124712
def mno_unaligned_symbols : Flag<["-"], "mno-unaligned-symbols">, Group<m_Group>,

clang/lib/Driver/ToolChains/Arch/Mips.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,15 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
341341
"dspr2");
342342
AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
343343
"msa");
344+
if (Arg *A = Args.getLastArg(
345+
options::OPT_mstrict_align, options::OPT_mno_strict_align,
346+
options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
347+
if (A->getOption().matches(options::OPT_mstrict_align) ||
348+
A->getOption().matches(options::OPT_mno_unaligned_access))
349+
Features.push_back(Args.MakeArgString("+strict-align"));
350+
else
351+
Features.push_back(Args.MakeArgString("-strict-align"));
352+
}
344353

345354
// Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
346355
// pass -mfpxx, or if none are given and fp64a is default, pass fp64 and

clang/test/Driver/mips-features.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,3 +462,29 @@
462462
// RUN: -mrelax-pic-calls -mno-relax-pic-calls 2>&1 \
463463
// RUN: | FileCheck --check-prefix=CHECK-NO-RELAX-PIC-CALLS %s
464464
// CHECK-NO-RELAX-PIC-CALLS: "-mllvm" "-mips-jalr-reloc=0"
465+
//
466+
// -mno-unaligned-access
467+
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
468+
// RUN: -munaligned-access -mno-strict-align \
469+
// RUN: -mno-unaligned-access 2>&1 \
470+
// RUN: | FileCheck --check-prefix=CHECK-STRICT-ALIGN %s
471+
// CHECK-STRICT-ALIGN: "-target-feature" "+strict-align"
472+
//
473+
// -munaligned-access
474+
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
475+
// RUN: -mno-unaligned-access -mstrict-align \
476+
// RUN: -munaligned-access 2>&1 \
477+
// RUN: | FileCheck --check-prefix=CHECK-NO-STRICT-ALIGN %s
478+
// CHECK-NO-STRICT-ALIGN: "-target-feature" "-strict-align"
479+
//
480+
// -mstrict-align
481+
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
482+
// RUN: -munaligned-access -mno-strict-align \
483+
// RUN: -mstrict-align 2>&1 \
484+
// RUN: | FileCheck --check-prefix=CHECK-STRICT-ALIGN %s
485+
//
486+
// -mno-strict-align
487+
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
488+
// RUN: -mno-unaligned-access -mstrict-align \
489+
// RUN: -mno-strict-align 2>&1 \
490+
// RUN: | FileCheck --check-prefix=CHECK-NO-STRICT-ALIGN %s

llvm/lib/Target/Mips/Mips.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ def FeatureUseIndirectJumpsHazard : SubtargetFeature<"use-indirect-jump-hazard",
208208
"true", "Use indirect jump"
209209
" guards to prevent certain speculation based attacks">;
210210

211+
def FeatureStrictAlign
212+
: SubtargetFeature<"strict-align", "StrictAlign", "true",
213+
"Disable unaligned load store for r6">;
214+
211215
//===----------------------------------------------------------------------===//
212216
// Register File, Calling Conv, Instruction Descriptions
213217
//===----------------------------------------------------------------------===//

llvm/lib/Target/Mips/MipsISelLowering.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,13 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
365365
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
366366
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
367367
setOperationAction(ISD::SELECT, MVT::i64, Custom);
368-
setOperationAction(ISD::LOAD, MVT::i64, Custom);
369-
setOperationAction(ISD::STORE, MVT::i64, Custom);
368+
if (Subtarget.hasMips64r6()) {
369+
setOperationAction(ISD::LOAD, MVT::i64, Legal);
370+
setOperationAction(ISD::STORE, MVT::i64, Legal);
371+
} else {
372+
setOperationAction(ISD::LOAD, MVT::i64, Custom);
373+
setOperationAction(ISD::STORE, MVT::i64, Custom);
374+
}
370375
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
371376
setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom);
372377
setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom);
@@ -481,7 +486,12 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
481486
if (!Subtarget.hasMips64r2())
482487
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
483488

484-
if (Subtarget.isGP64bit()) {
489+
if (Subtarget.isGP64bit() && Subtarget.hasMips64r6()) {
490+
setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Legal);
491+
setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Legal);
492+
setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Legal);
493+
setTruncStoreAction(MVT::i64, MVT::i32, Legal);
494+
} else if (Subtarget.isGP64bit()) {
485495
setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom);
486496
setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom);
487497
setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom);

llvm/lib/Target/Mips/MipsSEISelLowering.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,13 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM,
197197
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
198198
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
199199
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
200-
setOperationAction(ISD::LOAD, MVT::i32, Custom);
201-
setOperationAction(ISD::STORE, MVT::i32, Custom);
200+
if (Subtarget.hasMips32r6()) {
201+
setOperationAction(ISD::LOAD, MVT::i32, Legal);
202+
setOperationAction(ISD::STORE, MVT::i32, Legal);
203+
} else {
204+
setOperationAction(ISD::LOAD, MVT::i32, Custom);
205+
setOperationAction(ISD::STORE, MVT::i32, Custom);
206+
}
202207

203208
setTargetDAGCombine(ISD::MUL);
204209

@@ -425,6 +430,8 @@ bool MipsSETargetLowering::allowsMisalignedMemoryAccesses(
425430
if (Fast)
426431
*Fast = 1;
427432
return true;
433+
} else if (Subtarget.hasMips32r6()) {
434+
return false;
428435
}
429436

430437
switch (SVT) {

llvm/lib/Target/Mips/MipsSubtarget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
8282
HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 || Mips_Os16),
8383
Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false),
8484
HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false),
85-
HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false),
85+
HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false), StrictAlign(false),
8686
StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT),
8787
TSInfo(), InstrInfo(MipsInstrInfo::create(
8888
initializeSubtargetDependencies(CPU, FS, TM))),

llvm/lib/Target/Mips/MipsSubtarget.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
200200
// Assume 32-bit GOT.
201201
bool UseXGOT = false;
202202

203+
// Disable unaligned load store for r6.
204+
bool StrictAlign;
205+
203206
/// The minimum alignment known to hold of the stack frame on
204207
/// entry to the function and which must be maintained by every function.
205208
Align stackAlignment;
@@ -372,7 +375,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
372375
/// MIPS32r6/MIPS64r6 require full unaligned access support but does not
373376
/// specify which component of the system provides it. Hardware, software, and
374377
/// hybrid implementations are all valid.
375-
bool systemSupportsUnalignedAccess() const { return hasMips32r6(); }
378+
bool systemSupportsUnalignedAccess() const {
379+
return hasMips32r6() && !StrictAlign;
380+
}
376381

377382
// Set helper classes
378383
void setHelperClassesMips16();

llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,9 @@ define void @uitofp(i32 %a) {
405405
; MIPS64-N32-NEXT: addiu $1, $1, %lo(%neg(%gp_rel(uitofp)))
406406
; MIPS64-N32-NEXT: lui $2, 17200
407407
; MIPS64-N32-NEXT: sw $2, 12($sp)
408-
; MIPS64-N32-NEXT: sll $2, $4, 0
409-
; MIPS64-N32-NEXT: sw $2, 8($sp)
408+
; MIPS64R5-N32-NEXT: sll $2, $4, 0
409+
; MIPS64R5-N32-NEXT: sw $2, 8($sp)
410+
; MIPSR6-N32-NEXT: sw $4, 8($sp)
410411
; MIPS64-N32-NEXT: lw $2, %got_page(.LCPI5_0)($1)
411412
; MIPS64-N32-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2)
412413
; MIPS64-N32-NEXT: ldc1 $f1, 8($sp)
@@ -430,8 +431,9 @@ define void @uitofp(i32 %a) {
430431
; MIPS64-N64-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(uitofp)))
431432
; MIPS64-N64-NEXT: lui $2, 17200
432433
; MIPS64-N64-NEXT: sw $2, 12($sp)
433-
; MIPS64-N64-NEXT: sll $2, $4, 0
434-
; MIPS64-N64-NEXT: sw $2, 8($sp)
434+
; MIPS64R5-N64-NEXT: sll $2, $4, 0
435+
; MIPS64R5-N64-NEXT: sw $2, 8($sp)
436+
; MIPSR6-N64-NEXT: sw $4, 8($sp)
435437
; MIPS64-N64-NEXT: ld $2, %got_page(.LCPI5_0)($1)
436438
; MIPS64-N64-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2)
437439
; MIPS64-N64-NEXT: ldc1 $f1, 8($sp)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2+
;; Test the strict-align feature which is similar to AArch64/arm64-strict-align.ll.
3+
4+
; RUN: llc --mtriple=mipsisa32r6 < %s | FileCheck %s --check-prefix=MIPS32R6-UNALIGNED
5+
; RUN: llc --mtriple=mipsisa32r6 --mattr=-strict-align < %s | FileCheck %s --check-prefix=MIPS32R6-UNALIGNED
6+
; RUN: llc --mtriple=mipsisa32r6 --mattr=+strict-align < %s | FileCheck %s --check-prefix=MIPS32R6-ALIGNED
7+
8+
; RUN: llc --mtriple=mipsisa64r6 < %s | FileCheck %s --check-prefix=MIPS64R6-UNALIGNED
9+
; RUN: llc --mtriple=mipsisa64r6 --mattr=-strict-align < %s | FileCheck %s --check-prefix=MIPS64R6-UNALIGNED
10+
; RUN: llc --mtriple=mipsisa64r6 --mattr=+strict-align < %s | FileCheck %s --check-prefix=MIPS64R6-ALIGNED
11+
12+
define i32 @f0(ptr %p) nounwind {
13+
; MIPS32R6-UNALIGNED-LABEL: f0:
14+
; MIPS32R6-UNALIGNED: # %bb.0:
15+
; MIPS32R6-UNALIGNED-NEXT: lw $2, 0($4)
16+
; MIPS32R6-UNALIGNED-NEXT: jrc $ra
17+
;
18+
; MIPS32R6-ALIGNED-LABEL: f0:
19+
; MIPS32R6-ALIGNED: # %bb.0:
20+
; MIPS32R6-ALIGNED-NEXT: lhu $1, 2($4)
21+
; MIPS32R6-ALIGNED-NEXT: lhu $2, 0($4)
22+
; MIPS32R6-ALIGNED-NEXT: sll $2, $2, 16
23+
; MIPS32R6-ALIGNED-NEXT: jr $ra
24+
; MIPS32R6-ALIGNED-NEXT: or $2, $2, $1
25+
;
26+
; MIPS64R6-UNALIGNED-LABEL: f0:
27+
; MIPS64R6-UNALIGNED: # %bb.0:
28+
; MIPS64R6-UNALIGNED-NEXT: lw $2, 0($4)
29+
; MIPS64R6-UNALIGNED-NEXT: jrc $ra
30+
;
31+
; MIPS64R6-ALIGNED-LABEL: f0:
32+
; MIPS64R6-ALIGNED: # %bb.0:
33+
; MIPS64R6-ALIGNED-NEXT: lhu $1, 2($4)
34+
; MIPS64R6-ALIGNED-NEXT: lhu $2, 0($4)
35+
; MIPS64R6-ALIGNED-NEXT: sll $2, $2, 16
36+
; MIPS64R6-ALIGNED-NEXT: jr $ra
37+
; MIPS64R6-ALIGNED-NEXT: or $2, $2, $1
38+
%tmp = load i32, ptr %p, align 2
39+
ret i32 %tmp
40+
}
41+
42+
define i64 @f1(ptr %p) nounwind {
43+
; MIPS32R6-UNALIGNED-LABEL: f1:
44+
; MIPS32R6-UNALIGNED: # %bb.0:
45+
; MIPS32R6-UNALIGNED-NEXT: lw $2, 0($4)
46+
; MIPS32R6-UNALIGNED-NEXT: lw $3, 4($4)
47+
; MIPS32R6-UNALIGNED-NEXT: jrc $ra
48+
;
49+
; MIPS32R6-ALIGNED-LABEL: f1:
50+
; MIPS32R6-ALIGNED: # %bb.0:
51+
; MIPS32R6-ALIGNED-NEXT: lw $2, 0($4)
52+
; MIPS32R6-ALIGNED-NEXT: lw $3, 4($4)
53+
; MIPS32R6-ALIGNED-NEXT: jrc $ra
54+
;
55+
; MIPS64R6-UNALIGNED-LABEL: f1:
56+
; MIPS64R6-UNALIGNED: # %bb.0:
57+
; MIPS64R6-UNALIGNED-NEXT: ld $2, 0($4)
58+
; MIPS64R6-UNALIGNED-NEXT: jrc $ra
59+
;
60+
; MIPS64R6-ALIGNED-LABEL: f1:
61+
; MIPS64R6-ALIGNED: # %bb.0:
62+
; MIPS64R6-ALIGNED-NEXT: lwu $1, 4($4)
63+
; MIPS64R6-ALIGNED-NEXT: lwu $2, 0($4)
64+
; MIPS64R6-ALIGNED-NEXT: dsll $2, $2, 32
65+
; MIPS64R6-ALIGNED-NEXT: jr $ra
66+
; MIPS64R6-ALIGNED-NEXT: or $2, $2, $1
67+
%tmp = load i64, ptr %p, align 4
68+
ret i64 %tmp
69+
}

0 commit comments

Comments
 (0)