mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-06 12:26:45 +00:00
[ARM] Avoid using ARM instructions in Thumb mode
The Requires class overrides the target requirements of an instruction, rather than adding to them, so all ARM instructions need to include the IsARM predicate when they have overwitten requirements. This caused the swp and swpb instructions to be allowed in thumb mode assembly, and the ARM encoding of CDP to be selected in codegen (which is different for conditional instructions). Differential Revision: https://reviews.llvm.org/D29283 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293634 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3bfb126ba5
commit
d9605fec4b
@ -74,9 +74,9 @@ public:
|
||||
|
||||
SubtargetFeatures getFeatures() const override;
|
||||
|
||||
SubtargetFeatures getMIPSFeatures() const override;
|
||||
SubtargetFeatures getMIPSFeatures() const;
|
||||
|
||||
SubtargetFeatures getARMFeatures() const override;
|
||||
SubtargetFeatures getARMFeatures() const;
|
||||
|
||||
void setARMSubArch(Triple &TheTriple) const override;
|
||||
};
|
||||
|
@ -267,8 +267,6 @@ public:
|
||||
virtual StringRef getFileFormatName() const = 0;
|
||||
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
|
||||
virtual SubtargetFeatures getFeatures() const = 0;
|
||||
virtual SubtargetFeatures getMIPSFeatures() const { return SubtargetFeatures(); }
|
||||
virtual SubtargetFeatures getARMFeatures() const { return SubtargetFeatures(); }
|
||||
virtual void setARMSubArch(Triple &TheTriple) const { }
|
||||
|
||||
/// Returns platform-specific object flags, if any.
|
||||
|
@ -4831,14 +4831,15 @@ let AddedComplexity = 8 in {
|
||||
def : ARMPat<(atomic_store_release_32 addr_offset_none:$addr, GPR:$val), (STL GPR:$val, addr_offset_none:$addr)>;
|
||||
}
|
||||
|
||||
// SWP/SWPB are deprecated in V6/V7.
|
||||
// SWP/SWPB are deprecated in V6/V7 and optional in v7VE.
|
||||
// FIXME Use InstAlias to generate LDREX/STREX pairs instead.
|
||||
let mayLoad = 1, mayStore = 1 in {
|
||||
def SWP : AIswp<0, (outs GPRnopc:$Rt),
|
||||
(ins GPRnopc:$Rt2, addr_offset_none:$addr), "swp", []>,
|
||||
Requires<[PreV8]>;
|
||||
Requires<[IsARM,PreV8]>;
|
||||
def SWPB: AIswp<1, (outs GPRnopc:$Rt),
|
||||
(ins GPRnopc:$Rt2, addr_offset_none:$addr), "swpb", []>,
|
||||
Requires<[PreV8]>;
|
||||
Requires<[IsARM,PreV8]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -4850,7 +4851,7 @@ def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
|
||||
[(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
|
||||
imm:$CRm, imm:$opc2)]>,
|
||||
Requires<[PreV8]> {
|
||||
Requires<[IsARM,PreV8]> {
|
||||
bits<4> opc1;
|
||||
bits<4> CRn;
|
||||
bits<4> CRd;
|
||||
@ -4872,7 +4873,7 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
|
||||
[(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
|
||||
imm:$CRm, imm:$opc2)]>,
|
||||
Requires<[PreV8]> {
|
||||
Requires<[IsARM,PreV8]> {
|
||||
let Inst{31-28} = 0b1111;
|
||||
bits<4> opc1;
|
||||
bits<4> CRn;
|
||||
@ -5048,13 +5049,13 @@ multiclass LdSt2Cop<bit load, bit Dbit, string asm, list<dag> pattern> {
|
||||
|
||||
defm LDC : LdStCop <1, 0, "ldc", [(int_arm_ldc imm:$cop, imm:$CRd, addrmode5:$addr)]>;
|
||||
defm LDCL : LdStCop <1, 1, "ldcl", [(int_arm_ldcl imm:$cop, imm:$CRd, addrmode5:$addr)]>;
|
||||
defm LDC2 : LdSt2Cop<1, 0, "ldc2", [(int_arm_ldc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>;
|
||||
defm LDC2L : LdSt2Cop<1, 1, "ldc2l", [(int_arm_ldc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>;
|
||||
defm LDC2 : LdSt2Cop<1, 0, "ldc2", [(int_arm_ldc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>;
|
||||
defm LDC2L : LdSt2Cop<1, 1, "ldc2l", [(int_arm_ldc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>;
|
||||
|
||||
defm STC : LdStCop <0, 0, "stc", [(int_arm_stc imm:$cop, imm:$CRd, addrmode5:$addr)]>;
|
||||
defm STCL : LdStCop <0, 1, "stcl", [(int_arm_stcl imm:$cop, imm:$CRd, addrmode5:$addr)]>;
|
||||
defm STC2 : LdSt2Cop<0, 0, "stc2", [(int_arm_stc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>;
|
||||
defm STC2L : LdSt2Cop<0, 1, "stc2l", [(int_arm_stc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>;
|
||||
defm STC2 : LdSt2Cop<0, 0, "stc2", [(int_arm_stc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>;
|
||||
defm STC2L : LdSt2Cop<0, 1, "stc2l", [(int_arm_stc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Move between coprocessor and ARM core register.
|
||||
@ -5132,7 +5133,7 @@ def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */,
|
||||
c_imm:$CRm, imm0_7:$opc2),
|
||||
[(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
|
||||
imm:$CRm, imm:$opc2)]>,
|
||||
Requires<[PreV8]>;
|
||||
Requires<[IsARM,PreV8]>;
|
||||
def : ARMInstAlias<"mcr2 $cop, $opc1, $Rt, $CRn, $CRm",
|
||||
(MCR2 p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
|
||||
c_imm:$CRm, 0)>;
|
||||
@ -5140,7 +5141,7 @@ def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */,
|
||||
(outs GPRwithAPSR:$Rt),
|
||||
(ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm,
|
||||
imm0_7:$opc2), []>,
|
||||
Requires<[PreV8]>;
|
||||
Requires<[IsARM,PreV8]>;
|
||||
def : ARMInstAlias<"mrc2 $cop, $opc1, $Rt, $CRn, $CRm",
|
||||
(MRC2 GPRwithAPSR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
|
||||
c_imm:$CRm, 0)>;
|
||||
@ -5183,7 +5184,7 @@ class MovRRCopro2<string opc, bit direction, dag oops, dag iops,
|
||||
list<dag> pattern = []>
|
||||
: ABXI<0b1100, oops, iops, NoItinerary,
|
||||
!strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern>,
|
||||
Requires<[PreV8]> {
|
||||
Requires<[IsARM,PreV8]> {
|
||||
let Inst{31-28} = 0b1111;
|
||||
let Inst{23-21} = 0b010;
|
||||
let Inst{20} = direction;
|
||||
|
@ -1,5 +1,4 @@
|
||||
; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s
|
||||
; RUN: llc -mtriple=thumb-eabi %s -o - | FileCheck %s
|
||||
; PR4091
|
||||
|
||||
define void @foo(i32 %i, i32* %p) nounwind {
|
||||
|
@ -1,5 +1,4 @@
|
||||
; RUN: llc < %s -mtriple=armv7-eabi -mcpu=cortex-a8 | FileCheck %s
|
||||
; RUN: llc < %s -march=thumb -mtriple=thumbv7-eabi -mcpu=cortex-a8 | FileCheck %s
|
||||
|
||||
define void @coproc(i8* %i) nounwind {
|
||||
entry:
|
||||
|
93
test/CodeGen/Thumb2/intrinsics-coprocessor.ll
Normal file
93
test/CodeGen/Thumb2/intrinsics-coprocessor.ll
Normal file
@ -0,0 +1,93 @@
|
||||
; RUN: llc < %s -march=thumb -mtriple=thumbv7-eabi -mcpu=cortex-a8 -show-mc-encoding | FileCheck %s
|
||||
define void @coproc(i8* %i) nounwind {
|
||||
entry:
|
||||
; CHECK: mrc p7, #1, r{{[0-9]+}}, c1, c1, #4
|
||||
%0 = tail call i32 @llvm.arm.mrc(i32 7, i32 1, i32 1, i32 1, i32 4) nounwind
|
||||
; CHECK: mcr p7, #1, r{{[0-9]+}}, c1, c1, #4
|
||||
tail call void @llvm.arm.mcr(i32 7, i32 1, i32 %0, i32 1, i32 1, i32 4) nounwind
|
||||
; CHECK: mrc2 p7, #1, r{{[0-9]+}}, c1, c1, #4
|
||||
%1 = tail call i32 @llvm.arm.mrc2(i32 7, i32 1, i32 1, i32 1, i32 4) nounwind
|
||||
; CHECK: mcr2 p7, #1, r{{[0-9]+}}, c1, c1, #4
|
||||
tail call void @llvm.arm.mcr2(i32 7, i32 1, i32 %1, i32 1, i32 1, i32 4) nounwind
|
||||
; CHECK: mcrr p7, #1, r{{[0-9]+}}, r{{[0-9]+}}, c1
|
||||
tail call void @llvm.arm.mcrr(i32 7, i32 1, i32 %0, i32 %1, i32 1) nounwind
|
||||
; CHECK: mcrr2 p7, #1, r{{[0-9]+}}, r{{[0-9]+}}, c1
|
||||
tail call void @llvm.arm.mcrr2(i32 7, i32 1, i32 %0, i32 %1, i32 1) nounwind
|
||||
; CHECK: cdp p7, #3, c1, c1, c1, #5
|
||||
tail call void @llvm.arm.cdp(i32 7, i32 3, i32 1, i32 1, i32 1, i32 5) nounwind
|
||||
; CHECK: cdp2 p7, #3, c1, c1, c1, #5
|
||||
tail call void @llvm.arm.cdp2(i32 7, i32 3, i32 1, i32 1, i32 1, i32 5) nounwind
|
||||
; CHECK: ldc p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.ldc(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: ldcl p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.ldcl(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: ldc2 p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.ldc2(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: ldc2l p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.ldc2l(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: stc p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.stc(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: stcl p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.stcl(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: stc2 p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.stc2(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: stc2l p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.stc2l(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: mrrc p1, #2, r{{[0-9]+}}, r{{[0-9]+}}, c3
|
||||
%2 = tail call { i32, i32 } @llvm.arm.mrrc(i32 1, i32 2, i32 3) nounwind
|
||||
; CHECK: mrrc2 p1, #2, r{{[0-9]+}}, r{{[0-9]+}}, c3
|
||||
%3 = tail call { i32, i32 } @llvm.arm.mrrc2(i32 1, i32 2, i32 3) nounwind
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @cond_cdp(i32 %a) {
|
||||
; CHECK-LABEL: cond_cdp:
|
||||
entry:
|
||||
%tobool = icmp eq i32 %a, 0
|
||||
br i1 %tobool, label %if.end, label %if.then
|
||||
|
||||
if.then:
|
||||
; CHECK: it ne
|
||||
; CHECK: cdpne p15, #0, c0, c0, c0, #0 @ encoding: [0x00,0xee,0x00,0x0f]
|
||||
tail call void @llvm.arm.cdp(i32 15, i32 0, i32 0, i32 0, i32 0, i32 0)
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.arm.ldc(i32, i32, i8*) nounwind
|
||||
|
||||
declare void @llvm.arm.ldcl(i32, i32, i8*) nounwind
|
||||
|
||||
declare void @llvm.arm.ldc2(i32, i32, i8*) nounwind
|
||||
|
||||
declare void @llvm.arm.ldc2l(i32, i32, i8*) nounwind
|
||||
|
||||
declare void @llvm.arm.stc(i32, i32, i8*) nounwind
|
||||
|
||||
declare void @llvm.arm.stcl(i32, i32, i8*) nounwind
|
||||
|
||||
declare void @llvm.arm.stc2(i32, i32, i8*) nounwind
|
||||
|
||||
declare void @llvm.arm.stc2l(i32, i32, i8*) nounwind
|
||||
|
||||
declare void @llvm.arm.cdp2(i32, i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare void @llvm.arm.cdp(i32, i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare void @llvm.arm.mcrr2(i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare void @llvm.arm.mcrr(i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare void @llvm.arm.mcr2(i32, i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare i32 @llvm.arm.mrc2(i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare void @llvm.arm.mcr(i32, i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare i32 @llvm.arm.mrc(i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare { i32, i32 } @llvm.arm.mrrc(i32, i32, i32) nounwind
|
||||
|
||||
declare { i32, i32 } @llvm.arm.mrrc2(i32, i32, i32) nounwind
|
@ -117,4 +117,10 @@ foo2:
|
||||
@ CHECK-ERRORS: error: invalid operand for instruction
|
||||
@ CHECK-ERRORS: error: instruction requires: arm-mode
|
||||
@ CHECK-ERRORS: error: immediate value expected for vector index
|
||||
@ CHECK-ERRORS: error: instruction requires: arm-mode
|
||||
|
||||
@ SWP(B) is an ARM-only instruction
|
||||
swp r0, r1, [r2]
|
||||
swpb r3, r4, [r5]
|
||||
@ CHECK-ERRORS: error: instruction requires: arm-mode
|
||||
@ CHECK-ERRORS: error: instruction requires: arm-mode
|
||||
|
Loading…
x
Reference in New Issue
Block a user