Skip to content

Commit 9d51dd0

Browse files
committed
Implement ppc/ppc64 preserves_flags option for inline asm
Treat cr0 and xer as implicitly clobbered flags if preserves_flags is not specified. cr0 is commonly used, and xer can be tricky as it is modified by some shift operations. These are both caller-save in all ABIs, so neglicting to specify preserves_flags should have little overhead in cases where it could, but is not set. fpscr and vscr are not tracked as they contain sticky bits which are generally assumed to be volatile, but do not contains flags used to control branches. cr1 (fpr '.' ops), and cr6 (vmx/vsx '.' ops) are not considered as the instructions which could modify them are both explicitly '.' ops which almost always have a non-'.' version which does not modify a cr.
1 parent fb006ee commit 9d51dd0

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed

compiler/rustc_codegen_gcc/src/asm.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,26 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
546546
}
547547

548548
if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) {
549-
// TODO(@Commeownist): I'm not 100% sure this one clobber is sufficient
550-
// on all architectures. For instance, what about FP stack?
551-
extended_asm.add_clobber("cc");
549+
match asm_arch {
550+
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
551+
let clobbers = ["cr0", "xer"];
552+
clobbers.into_iter().for_each(|x| extended_asm.add_clobber(x));
553+
}
554+
_ => {
555+
// The machine specific flag preservation should be consistent across codegen
556+
// backends.
557+
//
558+
// gcc documents "cc" as being supported by all targets, but what flags are
559+
// clobbered is architecture specific. On many targets, this has no effect.
560+
// See documentation for target specific details.
561+
//
562+
// https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers
563+
//
564+
// At the time of commenting, cc is only documented as having an effect on
565+
// x86/arm/aarch64/s390.
566+
extended_asm.add_clobber("cc");
567+
}
568+
}
552569
}
553570
if !options.contains(InlineAsmOptions::NOMEM) {
554571
extended_asm.add_clobber("memory");

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,9 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
251251
constraints.push("~{sreg}".to_string());
252252
}
253253
InlineAsmArch::Nvptx64 => {}
254-
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {}
254+
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
255+
constraints.extend_from_slice(&["~{cr0}".to_string(), "~{xer}".to_string()]);
256+
}
255257
InlineAsmArch::Hexagon => {}
256258
InlineAsmArch::LoongArch32 | InlineAsmArch::LoongArch64 => {
257259
constraints.extend_from_slice(&[

src/doc/unstable-book/src/language-features/asm-experimental-arch.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ These flags registers must be restored upon exiting the asm block if the `preser
201201
- The status register `r2`.
202202
- M68k
203203
- The condition code register `ccr`.
204+
- PowerPC
205+
- The condition register `cr0`
206+
- The fixed-point exception register `xer`
204207
- SPARC
205208
- Integer condition codes (`icc` and `xcc`)
206209
- Floating-point condition codes (`fcc[0-3]`)

tests/codegen-llvm/asm/powerpc-clobbers.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,28 @@ pub unsafe fn vs32_clobber() {
7777
pub unsafe fn clobber_abi() {
7878
asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
7979
}
80+
81+
// CHECK-LABEL: @clobber_no_preserves_flags
82+
// CHECK: call void asm sideeffect "", "~{cr0},~{xer}"()
83+
#[no_mangle]
84+
pub unsafe fn clobber_no_preserves_flags() {
85+
asm!("", options(nostack, nomem));
86+
}
87+
88+
// CHECK-LABEL: @clobber_preservesflags
89+
// CHECK: call void asm sideeffect "", "~{memory}"()
90+
#[no_mangle]
91+
pub unsafe fn clobber_preservesflags() {
92+
asm!("", options(nostack, preserves_flags));
93+
}
94+
95+
// Output format depends on the availability of altivec and vsx
96+
// CHECK-LABEL: @clobber_abi_no_preserves_flags
97+
#[no_mangle]
98+
// powerpc: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{vs0},~{vs1},~{vs2},~{vs3},~{vs4},~{vs5},~{vs6},~{vs7},~{vs8},~{vs9},~{vs10},~{vs11},~{vs12},~{vs13},~{vs14},~{vs15},~{vs16},~{vs17},~{vs18},~{vs19},~{vs20},~{vs21},~{vs22},~{vs23},~{vs24},~{vs25},~{vs26},~{vs27},~{vs28},~{vs29},~{vs30},~{vs31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{ctr},~{lr},~{xer},~{cr0},~{xer}"()
99+
// powerpc64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{vs0},~{vs1},~{vs2},~{vs3},~{vs4},~{vs5},~{vs6},~{vs7},~{vs8},~{vs9},~{vs10},~{vs11},~{vs12},~{vs13},~{vs14},~{vs15},~{vs16},~{vs17},~{vs18},~{vs19},~{vs20},~{vs21},~{vs22},~{vs23},~{vs24},~{vs25},~{vs26},~{vs27},~{vs28},~{vs29},~{vs30},~{vs31},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{ctr},~{lr},~{xer},~{cr0},~{xer}"()
100+
// powerpc64le: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={vs0},={vs1},={vs2},={vs3},={vs4},={vs5},={vs6},={vs7},={vs8},={vs9},={vs10},={vs11},={vs12},={vs13},={vs14},={vs15},={vs16},={vs17},={vs18},={vs19},={vs20},={vs21},={vs22},={vs23},={vs24},={vs25},={vs26},={vs27},={vs28},={vs29},={vs30},={vs31},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{ctr},~{lr},~{xer},~{cr0},~{xer}"()
101+
// aix64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={vs0},={vs1},={vs2},={vs3},={vs4},={vs5},={vs6},={vs7},={vs8},={vs9},={vs10},={vs11},={vs12},={vs13},={vs14},={vs15},={vs16},={vs17},={vs18},={vs19},={vs20},={vs21},={vs22},={vs23},={vs24},={vs25},={vs26},={vs27},={vs28},={vs29},={vs30},={vs31},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{ctr},~{lr},~{xer},~{cr0},~{xer}"()
102+
pub unsafe fn clobber_abi_no_preserves_flags() {
103+
asm!("", clobber_abi("C"), options(nostack, nomem));
104+
}

0 commit comments

Comments
 (0)