[PowerPC] Implemented mtmsr, mfspr, mtspr Builtins
authorAlbion Fung <albionapc@gmail.com>
Tue, 20 Jul 2021 21:58:20 +0000 (16:58 -0500)
committerAlbion Fung <albionapc@gmail.com>
Tue, 20 Jul 2021 22:51:00 +0000 (17:51 -0500)
Implemented builtins for mtmsr, mfspr, mtspr on PowerPC;
the patch is intended for XL Compatibility.

Differential revision: https://reviews.llvm.org/D106130

clang/include/clang/Basic/BuiltinsPPC.def
clang/lib/Basic/Targets/PPC.cpp
clang/lib/CodeGen/CGBuiltin.cpp
clang/test/CodeGen/builtins-ppc-xlcompat-error.c
clang/test/CodeGen/builtins-ppc-xlcompat-move-tofrom-regs.c
llvm/include/llvm/IR/IntrinsicsPowerPC.td
llvm/lib/Target/PowerPC/PPCInstr64Bit.td
llvm/lib/Target/PowerPC/PPCInstrInfo.td
llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-mfspr-mtspr-64bit-only.ll [new file with mode: 0644]
llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-mfspr-mtspr-aix32.ll [new file with mode: 0644]
llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-move-tofrom-regs.ll

index 10743ac..7d46cb9 100644 (file)
@@ -124,6 +124,9 @@ BUILTIN(__builtin_ppc_dcbtstt, "vv*", "")
 BUILTIN(__builtin_ppc_dcbtt, "vv*", "")
 BUILTIN(__builtin_ppc_mftbu, "Ui","")
 BUILTIN(__builtin_ppc_mfmsr, "Ui", "")
+BUILTIN(__builtin_ppc_mfspr, "ULiIi", "")
+BUILTIN(__builtin_ppc_mtmsr, "vUi", "")
+BUILTIN(__builtin_ppc_mtspr, "vIiULi", "")
 BUILTIN(__builtin_ppc_stfiw, "viC*d", "")
 
 BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
index dd8e92e..a8dd6a3 100644 (file)
@@ -217,6 +217,9 @@ static void defineXLCompatMacros(MacroBuilder &Builder) {
   Builder.defineMacro("__dcbtt", "__builtin_ppc_dcbtt");
   Builder.defineMacro("__mftbu", "__builtin_ppc_mftbu");
   Builder.defineMacro("__mfmsr", "__builtin_ppc_mfmsr");
+  Builder.defineMacro("__mtmsr", "__builtin_ppc_mtmsr");
+  Builder.defineMacro("__mfspr", "__builtin_ppc_mfspr");
+  Builder.defineMacro("__mtspr", "__builtin_ppc_mtspr");
 }
 
 /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
index 1551ddd..46316d0 100644 (file)
@@ -15690,6 +15690,20 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
   case PPC::BI__builtin_ppc_lharx:
   case PPC::BI__builtin_ppc_lbarx:
     return emitPPCLoadReserveIntrinsic(*this, BuiltinID, E);
+  case PPC::BI__builtin_ppc_mfspr: {
+    llvm::Type *RetType = CGM.getDataLayout().getTypeSizeInBits(VoidPtrTy) == 32
+                              ? Int32Ty
+                              : Int64Ty;
+    Function *F = CGM.getIntrinsic(Intrinsic::ppc_mfspr, RetType);
+    return Builder.CreateCall(F, Ops);
+  }
+  case PPC::BI__builtin_ppc_mtspr: {
+    llvm::Type *RetType = CGM.getDataLayout().getTypeSizeInBits(VoidPtrTy) == 32
+                              ? Int32Ty
+                              : Int64Ty;
+    Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtspr, RetType);
+    return Builder.CreateCall(F, Ops);
+  }
   case PPC::BI__builtin_ppc_popcntb: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
index 1220576..1f18134 100644 (file)
@@ -12,6 +12,8 @@ extern long long lla, llb;
 extern int ia, ib;
 extern unsigned int ui;
 extern unsigned long long ull;
+extern const int cia;
+extern unsigned long ula;
 
 void test_trap(void) {
 #ifdef __PPC64__
@@ -93,3 +95,11 @@ unsigned long long testdivdeu(unsigned long long dividend, unsigned long long di
   return __divdeu(dividend, divisor); //expected-error {{this builtin is only available on 64-bit targets}}
 }
 #endif
+
+unsigned long test_mfspr(void) {
+  return __mfspr(cia); //expected-error {{argument to '__builtin_ppc_mfspr' must be a constant integer}}
+}
+
+void test_mtspr(void) {
+   __mtspr(cia, ula); //expected-error {{argument to '__builtin_ppc_mtspr' must be a constant integer}}
+}
index c05b1eb..ea9a221 100644 (file)
@@ -3,10 +3,13 @@
 // RUN: %clang_cc1 -O2 -triple powerpc64le-unknown-unknown \
 // RUN:   -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s
 // RUN: %clang_cc1 -O2 -triple powerpc-unknown-aix \
-// RUN:   -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s
+// RUN:   -emit-llvm %s -o - -target-cpu pwr7 | \
+// RUN:   FileCheck %s --check-prefix=CHECK-32BIT
 // RUN: %clang_cc1 -O2 -triple powerpc64-unknown-aix \
 // RUN:   -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s
 
+extern unsigned long ula;
+
 unsigned int test_mftbu(void) {
   // CHECK-LABEL: @test_mftbu
   // CHECK: %0 = tail call i32 @llvm.ppc.mftbu()
@@ -18,3 +21,23 @@ unsigned long test_mfmsr(void) {
   // CHECK: %0 = tail call i32 @llvm.ppc.mfmsr()
   return __mfmsr();
 }
+
+void test_mtmsr(void) {
+  // CHECK-LABEL: @test_mtmsr
+  // CHECK: tail call void @llvm.ppc.mtmsr(i32 %conv)
+  // CHECK-32BIT-LABEL: @test_mtmsr
+  // CHECK-32BIT: tail call void @llvm.ppc.mtmsr(i32 %0)
+  __mtmsr(ula);
+}
+
+unsigned long test_mfspr(void) {
+  // CHECK-LABEL: @test_mfspr
+  // CHECK: %0 = tail call i64 @llvm.ppc.mfspr.i64(i32 898)
+  return __mfspr(898);
+}
+
+void test_mtspr(void) {
+  // CHECK-LABEL: @test_mtspr
+  // CHECK: tail call void @llvm.ppc.mtspr.i64(i32 1, i64 %0)
+  __mtspr(1, ula);
+}
index 1af8c02..69f2346 100644 (file)
@@ -1576,6 +1576,12 @@ let TargetPrefix = "ppc" in {
                       Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
   def int_ppc_mfmsr : GCCBuiltin<"__builtin_ppc_mfmsr">,
                       Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
+  def int_ppc_mfspr
+      : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>;
+  def int_ppc_mtmsr
+      : GCCBuiltin<"__builtin_ppc_mtmsr">, Intrinsic<[], [llvm_i32_ty], []>;
+  def int_ppc_mtspr
+      : Intrinsic<[], [llvm_i32_ty, llvm_anyint_ty], [ImmArg<ArgIndex<0>>]>;
   def int_ppc_stfiw : GCCBuiltin<"__builtin_ppc_stfiw">,
                       Intrinsic<[], [llvm_ptr_ty, llvm_double_ty],
                                 [IntrWriteMem]>;
index 0e20dc3..92712c5 100644 (file)
@@ -1839,3 +1839,7 @@ def : Pat<(int_ppc_tdw g8rc:$A, g8rc:$B, i32:$IMM),
 // trapd
 def : Pat<(int_ppc_trapd g8rc:$A),
           (TDI 24, $A, 0)>;
+def : Pat<(i64 (int_ppc_mfspr timm:$SPR)),
+          (MFSPR8 $SPR)>;
+def : Pat<(int_ppc_mtspr timm:$SPR, g8rc:$RT),
+          (MTSPR8 $SPR, $RT)>;
index d04d828..79e5583 100644 (file)
@@ -5483,6 +5483,12 @@ def : Pat<(int_ppc_fctuwz f64:$A),
 
 def : Pat<(int_ppc_mfmsr), (MFMSR)>;
 def : Pat<(int_ppc_mftbu), (MFTB 269)>;
+def : Pat<(i32 (int_ppc_mfspr timm:$SPR)),
+          (MFSPR $SPR)>;
+def : Pat<(int_ppc_mtspr timm:$SPR, gprc:$RT),
+          (MTSPR $SPR, $RT)>;
+def : Pat<(int_ppc_mtmsr gprc:$RS),
+          (MTMSR $RS, 0)>;
 
 let Predicates = [IsISA2_07] in {
   def : Pat<(int_ppc_sthcx ForceXForm:$dst, gprc:$A),
diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-mfspr-mtspr-64bit-only.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-mfspr-mtspr-64bit-only.ll
new file mode 100644 (file)
index 0000000..4fd3877
--- /dev/null
@@ -0,0 +1,192 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:   -mcpu=pwr8 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
+; RUN:   -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
+; RUN:   -mcpu=pwr7 < %s | FileCheck %s --check-prefix=CHECK-AIX64
+
+declare i64 @llvm.ppc.mfspr.i64(i32 immarg)
+declare void @llvm.ppc.mtspr.i64(i32 immarg, i64)
+
+@ula = external local_unnamed_addr global i64, align 8
+
+define dso_local i64 @test_mfxer() {
+; CHECK-LABEL: test_mfxer:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfxer 3
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mfxer:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    mfxer 3
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = call i64 @llvm.ppc.mfspr.i64(i32 1)
+  ret i64 %0
+}
+
+define dso_local i64 @test_mflr() {
+; CHECK-LABEL: test_mflr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mflr 3
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mflr:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    mfspr 3, 8
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = call i64 @llvm.ppc.mfspr.i64(i32 8)
+  ret i64 %0
+}
+
+define dso_local i64 @test_mfctr() {
+; CHECK-LABEL: test_mfctr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfctr 3
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mfctr:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    mfspr 3, 9
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = call i64 @llvm.ppc.mfspr.i64(i32 9)
+  ret i64 %0
+}
+
+define dso_local i64 @test_mfppr() {
+; CHECK-LABEL: test_mfppr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfspr 3, 896
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mfppr:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    mfspr 3, 896
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = call i64 @llvm.ppc.mfspr.i64(i32 896)
+  ret i64 %0
+}
+
+define dso_local i64 @test_mfppr32() {
+; CHECK-LABEL: test_mfppr32:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfspr 3, 898
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mfppr32:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    mfspr 3, 898
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = call i64 @llvm.ppc.mfspr.i64(i32 898)
+  ret i64 %0
+}
+
+define dso_local void @test_mtxer() {
+; CHECK-LABEL: test_mtxer:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, .LC0@toc@ha
+; CHECK-NEXT:    ld 3, .LC0@toc@l(3)
+; CHECK-NEXT:    ld 3, 0(3)
+; CHECK-NEXT:    mtxer 3
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mtxer:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    ld 3, L..C0(2) # @ula
+; CHECK-AIX64-NEXT:    ld 3, 0(3)
+; CHECK-AIX64-NEXT:    mtxer 3
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = load i64, i64* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i64(i32 1, i64 %0)
+  ret void
+}
+
+define dso_local void @test_mtlr() {
+; CHECK-LABEL: test_mtlr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, .LC0@toc@ha
+; CHECK-NEXT:    ld 3, .LC0@toc@l(3)
+; CHECK-NEXT:    ld 3, 0(3)
+; CHECK-NEXT:    mtlr 3
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mtlr:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    ld 3, L..C0(2) # @ula
+; CHECK-AIX64-NEXT:    ld 3, 0(3)
+; CHECK-AIX64-NEXT:    mtspr 8, 3
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = load i64, i64* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i64(i32 8, i64 %0)
+  ret void
+}
+
+define dso_local void @test_mtctr() {
+; CHECK-LABEL: test_mtctr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, .LC0@toc@ha
+; CHECK-NEXT:    ld 3, .LC0@toc@l(3)
+; CHECK-NEXT:    ld 3, 0(3)
+; CHECK-NEXT:    mtctr 3
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mtctr:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    ld 3, L..C0(2) # @ula
+; CHECK-AIX64-NEXT:    ld 3, 0(3)
+; CHECK-AIX64-NEXT:    mtspr 9, 3
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = load i64, i64* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i64(i32 9, i64 %0)
+  ret void
+}
+
+define dso_local void @test_mtppr() {
+; CHECK-LABEL: test_mtppr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, .LC0@toc@ha
+; CHECK-NEXT:    ld 3, .LC0@toc@l(3)
+; CHECK-NEXT:    ld 3, 0(3)
+; CHECK-NEXT:    mtspr 896, 3
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mtppr:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    ld 3, L..C0(2) # @ula
+; CHECK-AIX64-NEXT:    ld 3, 0(3)
+; CHECK-AIX64-NEXT:    mtspr 896, 3
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = load i64, i64* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i64(i32 896, i64 %0)
+  ret void
+}
+
+define dso_local void @test_mtppr32() {
+; CHECK-LABEL: test_mtppr32:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addis 3, 2, .LC0@toc@ha
+; CHECK-NEXT:    ld 3, .LC0@toc@l(3)
+; CHECK-NEXT:    ld 3, 0(3)
+; CHECK-NEXT:    mtspr 898, 3
+; CHECK-NEXT:    blr
+;
+; CHECK-AIX64-LABEL: test_mtppr32:
+; CHECK-AIX64:       # %bb.0: # %entry
+; CHECK-AIX64-NEXT:    ld 3, L..C0(2) # @ula
+; CHECK-AIX64-NEXT:    ld 3, 0(3)
+; CHECK-AIX64-NEXT:    mtspr 898, 3
+; CHECK-AIX64-NEXT:    blr
+entry:
+  %0 = load i64, i64* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i64(i32 898, i64 %0)
+  ret void
+}
diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-mfspr-mtspr-aix32.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-mfspr-mtspr-aix32.ll
new file mode 100644 (file)
index 0000000..8f58855
--- /dev/null
@@ -0,0 +1,123 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
+; RUN:   -mcpu=pwr7 < %s | FileCheck %s
+
+declare i32 @llvm.ppc.mfspr.i32(i32 immarg)
+declare void @llvm.ppc.mtspr.i32(i32 immarg, i32)
+
+@ula = external dso_local global i32, align 4
+
+define dso_local i32 @test_mfxer() {
+; CHECK-LABEL: test_mfxer:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfxer 3
+; CHECK-NEXT:    blr
+entry:
+  %0 = call i32 @llvm.ppc.mfspr.i32(i32 1)
+  ret i32 %0
+}
+
+define dso_local i32 @test_mflr() {
+; CHECK-LABEL: test_mflr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfspr 3, 8
+; CHECK-NEXT:    blr
+entry:
+  %0 = call i32 @llvm.ppc.mfspr.i32(i32 8)
+  ret i32 %0
+}
+
+define dso_local i32 @test_mfctr() {
+; CHECK-LABEL: test_mfctr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfspr 3, 9
+; CHECK-NEXT:    blr
+entry:
+  %0 = call i32 @llvm.ppc.mfspr.i32(i32 9)
+  ret i32 %0
+}
+
+define dso_local i32 @test_mfppr() {
+; CHECK-LABEL: test_mfppr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfspr 3, 896
+; CHECK-NEXT:    blr
+entry:
+  %0 = call i32 @llvm.ppc.mfspr.i32(i32 896)
+  ret i32 %0
+}
+
+define dso_local i32 @test_mfppr32() {
+; CHECK-LABEL: test_mfppr32:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mfspr 3, 898
+; CHECK-NEXT:    blr
+entry:
+  %0 = call i32 @llvm.ppc.mfspr.i32(i32 898)
+  ret i32 %0
+}
+
+define dso_local void @test_mtxer() {
+; CHECK-LABEL: test_mtxer:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lwz 3, L..C0(2) # @ula
+; CHECK-NEXT:    lwz 3, 0(3)
+; CHECK-NEXT:    mtxer 3
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i32(i32 1, i32 %0)
+  ret void
+}
+
+define dso_local void @test_mtlr() {
+; CHECK-LABEL: test_mtlr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lwz 3, L..C0(2) # @ula
+; CHECK-NEXT:    lwz 3, 0(3)
+; CHECK-NEXT:    mtspr 8, 3
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i32(i32 8, i32 %0)
+  ret void
+}
+
+define dso_local void @test_mtctr() {
+; CHECK-LABEL: test_mtctr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lwz 3, L..C0(2) # @ula
+; CHECK-NEXT:    lwz 3, 0(3)
+; CHECK-NEXT:    mtspr 9, 3
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i32(i32 9, i32 %0)
+  ret void
+}
+
+define dso_local void @test_mtppr() {
+; CHECK-LABEL: test_mtppr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lwz 3, L..C0(2) # @ula
+; CHECK-NEXT:    lwz 3, 0(3)
+; CHECK-NEXT:    mtspr 896, 3
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i32(i32 896, i32 %0)
+  ret void
+}
+
+define dso_local void @test_mtppr32() {
+; CHECK-LABEL: test_mtppr32:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lwz 3, L..C0(2) # @ula
+; CHECK-NEXT:    lwz 3, 0(3)
+; CHECK-NEXT:    mtspr 898, 3
+; CHECK-NEXT:    blr
+entry:
+  %0 = load i32, i32* @ula, align 8
+  tail call void @llvm.ppc.mtspr.i32(i32 898, i32 %0)
+  ret void
+}
index b3d51d6..35c1b9c 100644 (file)
@@ -3,13 +3,16 @@
 ; RUN:   -mcpu=pwr8 < %s | FileCheck %s
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
 ; RUN:   -mcpu=pwr7 < %s | FileCheck %s
-; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
-; RUN:   -mcpu=pwr7 < %s | FileCheck %s --check-prefix=CHECK-32BIT
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
 ; RUN:   -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
+; RUN:   -mcpu=pwr7 < %s | FileCheck %s --check-prefix=CHECK-32BIT
 
 declare i32 @llvm.ppc.mftbu()
 declare i32 @llvm.ppc.mfmsr()
+declare void @llvm.ppc.mtmsr(i32)
+
+@ula = external local_unnamed_addr global i64, align 8
 
 define dso_local zeroext i32 @test_mftbu() {
 ; CHECK-LABEL: test_mftbu:
@@ -44,3 +47,21 @@ entry:
   %conv = zext i32 %0 to i64
   ret i64 %conv
 }
+
+define dso_local void @test_mtmsr() {
+; CHECK-LABEL: test_mtmsr:
+; CHECK:    mtmsr 3
+; CHECK-NEXT:    blr
+;
+; CHECK-32BIT-LABEL: test_mtmsr:
+; CHECK-32BIT:       # %bb.0: # %entry
+; CHECK-32BIT-NEXT:    lwz 3, L..C0(2) # @ula
+; CHECK-32BIT-NEXT:    lwz 3, 4(3)
+; CHECK-32BIT-NEXT:    mtmsr 3, 0
+; CHECK-32BIT-NEXT:    blr
+entry:
+  %0 = load i64, i64* @ula, align 8
+  %conv = trunc i64 %0 to i32
+  call void @llvm.ppc.mtmsr(i32 %conv)
+  ret void
+}