diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index 19b7ded40402a6..1eb0317af60b62 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -734,23 +734,28 @@ ArrayRef PPCTargetInfo::getGCCRegNames() const { const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = { // While some of these aliases do map to different registers // they still share the same register name. - {{"0"}, "r0"}, {{"1"}, "r1"}, {{"2"}, "r2"}, {{"3"}, "r3"}, - {{"4"}, "r4"}, {{"5"}, "r5"}, {{"6"}, "r6"}, {{"7"}, "r7"}, - {{"8"}, "r8"}, {{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"}, - {{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"}, {{"15"}, "r15"}, - {{"16"}, "r16"}, {{"17"}, "r17"}, {{"18"}, "r18"}, {{"19"}, "r19"}, - {{"20"}, "r20"}, {{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"}, - {{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"}, {{"27"}, "r27"}, - {{"28"}, "r28"}, {{"29"}, "r29"}, {{"30"}, "r30"}, {{"31"}, "r31"}, - {{"fr0"}, "f0"}, {{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"}, - {{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"}, {{"fr7"}, "f7"}, - {{"fr8"}, "f8"}, {{"fr9"}, "f9"}, {{"fr10"}, "f10"}, {{"fr11"}, "f11"}, - {{"fr12"}, "f12"}, {{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"}, - {{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"}, {{"fr19"}, "f19"}, - {{"fr20"}, "f20"}, {{"fr21"}, "f21"}, {{"fr22"}, "f22"}, {{"fr23"}, "f23"}, - {{"fr24"}, "f24"}, {{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"}, - {{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"}, {{"fr31"}, "f31"}, - {{"cc"}, "cr0"}, + {{"0"}, "r0"}, {{"1", "sp"}, "r1"}, {{"2"}, "r2"}, + {{"3"}, "r3"}, {{"4"}, "r4"}, {{"5"}, "r5"}, + {{"6"}, "r6"}, {{"7"}, "r7"}, {{"8"}, "r8"}, + {{"9"}, "r9"}, {{"10"}, "r10"}, {{"11"}, "r11"}, + {{"12"}, "r12"}, {{"13"}, "r13"}, {{"14"}, "r14"}, + {{"15"}, "r15"}, {{"16"}, "r16"}, {{"17"}, "r17"}, + {{"18"}, "r18"}, {{"19"}, "r19"}, {{"20"}, "r20"}, + {{"21"}, "r21"}, {{"22"}, "r22"}, {{"23"}, "r23"}, + {{"24"}, "r24"}, {{"25"}, "r25"}, {{"26"}, "r26"}, + {{"27"}, "r27"}, {{"28"}, "r28"}, {{"29"}, "r29"}, + {{"30"}, "r30"}, {{"31"}, "r31"}, {{"fr0"}, "f0"}, + {{"fr1"}, "f1"}, {{"fr2"}, "f2"}, {{"fr3"}, "f3"}, + {{"fr4"}, "f4"}, {{"fr5"}, "f5"}, {{"fr6"}, "f6"}, + {{"fr7"}, "f7"}, {{"fr8"}, "f8"}, {{"fr9"}, "f9"}, + {{"fr10"}, "f10"}, {{"fr11"}, "f11"}, {{"fr12"}, "f12"}, + {{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"}, + {{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"}, + {{"fr19"}, "f19"}, {{"fr20"}, "f20"}, {{"fr21"}, "f21"}, + {{"fr22"}, "f22"}, {{"fr23"}, "f23"}, {{"fr24"}, "f24"}, + {{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"}, + {{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"}, + {{"fr31"}, "f31"}, {{"cc"}, "cr0"}, }; ArrayRef PPCTargetInfo::getGCCRegAliases() const { diff --git a/clang/test/Misc/ppc-inline-asm-clobber-warning.c b/clang/test/Misc/ppc-inline-asm-clobber-warning.c new file mode 100644 index 00000000000000..bc323243b6e2dc --- /dev/null +++ b/clang/test/Misc/ppc-inline-asm-clobber-warning.c @@ -0,0 +1,38 @@ +/// This test checks that the warning includes the location in the C source +/// file that contains the inline asm. Although this warning is emitted in llvm +/// it cannot be tested from IR as it does not have that location information at +/// that stage. + +// REQUIRES: powerpc-registered-target + +// RUN: %clang --target=powerpc-unknown-unknown -mcpu=pwr7 \ +// RUN: -c %s -o /dev/null 2>&1 | FileCheck %s +// RUN: %clang --target=powerpc64-unknown-unknown -mcpu=pwr7 \ +// RUN: -c %s -o /dev/null 2>&1 | FileCheck %s + +void test_r1_clobber() { + __asm__("nop":::"r1"); +} + +// CHECK: ppc-inline-asm-clobber-warning.c:14:11: warning: inline asm clobber list contains reserved registers: R1 [-Winline-asm] +// CHECK-NEXT: __asm__("nop":::"r1"); +// CHECK-NEXT: ^ +// CHECK-NEXT: ppc-inline-asm-clobber-warning.c:14:11: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour. + +void test_1_clobber() { + __asm__("nop":::"1"); +} + +// CHECK: ppc-inline-asm-clobber-warning.c:23:11: warning: inline asm clobber list contains reserved registers: R1 [-Winline-asm] +// CHECK-NEXT: __asm__("nop":::"1"); +// CHECK-NEXT: ^ +// CHECK-NEXT: ppc-inline-asm-clobber-warning.c:23:11: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour. + +void test_sp_clobber() { + __asm__("nop":::"sp"); +} + +// CHECK: ppc-inline-asm-clobber-warning.c:32:11: warning: inline asm clobber list contains reserved registers: R1 [-Winline-asm] +// CHECK-NEXT: __asm__("nop":::"sp"); +// CHECK-NEXT: ^ +// CHECK-NEXT: ppc-inline-asm-clobber-warning.c:32:11: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour. diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp index 422b3db4f978a8..76b016c0ee7921 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -390,6 +390,18 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const { return Reserved; } +bool PPCRegisterInfo::isAsmClobberable(const MachineFunction &MF, + MCRegister PhysReg) const { + // We cannot use getReservedRegs() to find the registers that are not asm + // clobberable because there are some reserved registers which can be + // clobbered by inline asm. For example, when LR is clobbered, the register is + // saved and restored. We will hardcode the registers that are not asm + // cloberable in this function. + + // The stack pointer (R1/X1) is not clobberable by inline asm + return PhysReg != PPC::R1 && PhysReg != PPC::X1; +} + bool PPCRegisterInfo::requiresFrameIndexScavenging(const MachineFunction &MF) const { const PPCSubtarget &Subtarget = MF.getSubtarget(); const PPCInstrInfo *InstrInfo = Subtarget.getInstrInfo(); diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h index ce2a343cfa3572..114f6d0f4c666c 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h @@ -91,6 +91,8 @@ class PPCRegisterInfo : public PPCGenRegisterInfo { void adjustStackMapLiveOutMask(uint32_t *Mask) const override; BitVector getReservedRegs(const MachineFunction &MF) const override; + bool isAsmClobberable(const MachineFunction &MF, + MCRegister PhysReg) const override; bool isCallerPreservedPhysReg(MCRegister PhysReg, const MachineFunction &MF) const override; diff --git a/llvm/test/CodeGen/PowerPC/inline-asm-clobber-warning.ll b/llvm/test/CodeGen/PowerPC/inline-asm-clobber-warning.ll new file mode 100644 index 00000000000000..7f13f5072d97f1 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/inline-asm-clobber-warning.ll @@ -0,0 +1,22 @@ +; RUN: llc < %s -verify-machineinstrs -mtriple=powerpc-unknown-unkown \ +; RUN: -mcpu=pwr7 2>&1 | FileCheck %s +; RUN: llc < %s -verify-machineinstrs -mtriple=powerpc64-unknown-unkown \ +; RUN: -mcpu=pwr7 2>&1 | FileCheck %s + +define void @test_r1_clobber() { +entry: + call void asm sideeffect "nop", "~{r1}"() + ret void +} + +; CHECK: warning: inline asm clobber list contains reserved registers: R1 +; CHECK-NEXT: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour. + +define void @test_x1_clobber() { +entry: + call void asm sideeffect "nop", "~{x1}"() + ret void +} + +; CHECK: warning: inline asm clobber list contains reserved registers: X1 +; CHECK-NEXT: note: Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour.