[ARM] MSR instructions implicitly set CPSR

The MSR instructions can write to the CPSR, but we did not model this
fact, so we could emit them in the middle of IT blocks, changing the
condition flags for later instructions in the block.

The tests use two calls to llvm.write_register.i32 because it is valid
to use these instructions at the end of an IT block, which if conversion
does do in some cases. With two calls, the first clobbers the flags, so
a branch has to be used to make the second one conditional.

Differential Revision: http://reviews.llvm.org/D21139

llvm-svn: 272154
This commit is contained in:
Oliver Stannard 2016-06-08 15:26:34 +00:00
parent c564701fbd
commit b3378e2f3c
3 changed files with 59 additions and 0 deletions

View File

@ -5233,6 +5233,7 @@ def MRSbanked : ABI<0b0001, (outs GPRnopc:$Rd), (ins banked_reg:$banked),
// to distinguish between them. The mask operand contains the special register
// (R Bit) in bit 4 and bits 3-0 contains the mask with the fields to be
// accessed in the special register.
let Defs = [CPSR] in
def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary,
"msr", "\t$mask, $Rn", []> {
bits<5> mask;
@ -5247,6 +5248,7 @@ def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary,
let Inst{3-0} = Rn;
}
let Defs = [CPSR] in
def MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask, mod_imm:$imm), NoItinerary,
"msr", "\t$mask, $imm", []> {
bits<5> mask;

View File

@ -4083,6 +4083,7 @@ def t2MRS_M : T2I<(outs rGPR:$Rd), (ins msr_mask:$SYSm), NoItinerary,
// same and the assembly parser has no way to distinguish between them. The mask
// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains
// the mask with the fields to be accessed in the special register.
let Defs = [CPSR] in
def t2MSR_AR : T2I<(outs), (ins msr_mask:$mask, rGPR:$Rn),
NoItinerary, "msr", "\t$mask, $Rn", []>,
Requires<[IsThumb2,IsNotMClass]> {
@ -4118,6 +4119,7 @@ def t2MSRbanked : T2I<(outs), (ins banked_reg:$banked, rGPR:$Rn),
// M class MSR.
//
// Move from ARM core register to Special Register
let Defs = [CPSR] in
def t2MSR_M : T2I<(outs), (ins msr_mask:$SYSm, rGPR:$Rn),
NoItinerary, "msr", "\t$SYSm, $Rn", []>,
Requires<[IsThumb,IsMClass]> {

View File

@ -0,0 +1,55 @@
; RUN: llc < %s -mtriple=thumbv6m-none-eabi | FileCheck %s --check-prefix=V6M --check-prefix=CHECK
; RUN: llc < %s -mtriple=thumbv7m-none-eabi | FileCheck %s --check-prefix=V7M --check-prefix=CHECK
; RUN: llc < %s -mtriple=thumbv7a-none-eabi | FileCheck %s --check-prefix=V7A --check-prefix=CHECK
; RUN: llc < %s -mtriple=armv7a-none-eabi | FileCheck %s --check-prefix=V7A --check-prefix=CHECK
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armv7a-arm-none-eabi"
define void @test_const(i32 %val) {
; CHECK-LABEL: test_const:
entry:
%cmp = icmp eq i32 %val, 0
br i1 %cmp, label %write_reg, label %exit
write_reg:
tail call void @llvm.write_register.i32(metadata !0, i32 0)
tail call void @llvm.write_register.i32(metadata !0, i32 0)
; V6M: msr apsr, {{r[0-9]+}}
; V6M: msr apsr, {{r[0-9]+}}
; V7M: msr apsr_nzcvq, {{r[0-9]+}}
; V7M: msr apsr_nzcvq, {{r[0-9]+}}
; V7A: msr APSR_nzcvqg, {{r[0-9]+}}
; V7A: msr APSR_nzcvqg, {{r[0-9]+}}
br label %exit
exit:
ret void
}
define void @test_var(i32 %val, i32 %apsr) {
; CHECK-LABEL: test_var:
entry:
%cmp = icmp eq i32 %val, 0
br i1 %cmp, label %write_reg, label %exit
write_reg:
tail call void @llvm.write_register.i32(metadata !0, i32 %apsr)
tail call void @llvm.write_register.i32(metadata !0, i32 %apsr)
; V6M: msr apsr, {{r[0-9]+}}
; V6M: msr apsr, {{r[0-9]+}}
; V7M: msr apsr_nzcvq, {{r[0-9]+}}
; V7M: msr apsr_nzcvq, {{r[0-9]+}}
; V7A: msr APSR_nzcvqg, {{r[0-9]+}}
; V7A: msr APSR_nzcvqg, {{r[0-9]+}}
br label %exit
exit:
ret void
}
declare void @llvm.write_register.i32(metadata, i32)
!0 = !{!"apsr"}