From c05e81481a21b94385a593679ad537a837cdab4b Mon Sep 17 00:00:00 2001 From: Sanne Wouda <sanne.wouda@arm.com> Date: Tue, 28 Mar 2017 10:02:56 +0000 Subject: [PATCH] [AArch64] [Assembler] option to disable negative immediate conversions Summary: Similar to the ARM target in https://reviews.llvm.org/rL298380, this patch adds identical infrastructure for disabling negative immediate conversions, and converts the existing aliases to the new infrastucture. Reviewers: rengolin, javed.absar, olista01, SjoerdMeijer, samparker Reviewed By: samparker Subscribers: samparker, aemerson, llvm-commits Differential Revision: https://reviews.llvm.org/D31243 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298908 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64.td | 8 ++++++++ lib/Target/AArch64/AArch64InstrFormats.td | 23 +++++++++++++---------- lib/Target/AArch64/AArch64InstrInfo.td | 5 +++++ lib/Target/AArch64/AArch64Subtarget.h | 4 ++++ test/MC/AArch64/alias-addsubimm.s | 21 +++++++++++++++++++++ test/MC/AArch64/alias-logicalimm.s | 9 +++++++++ 6 files changed, 60 insertions(+), 10 deletions(-) diff --git a/lib/Target/AArch64/AArch64.td b/lib/Target/AArch64/AArch64.td index a6dbb2a1c39..09897104f32 100644 --- a/lib/Target/AArch64/AArch64.td +++ b/lib/Target/AArch64/AArch64.td @@ -118,6 +118,14 @@ def FeatureDisableLatencySchedHeuristic : SubtargetFeature< def FeatureUseRSqrt : SubtargetFeature< "use-reciprocal-square-root", "UseRSqrt", "true", "Use the reciprocal square root approximation">; + +def FeatureNoNegativeImmediates : SubtargetFeature<"no-neg-immediates", + "NegativeImmediates", "false", + "Convert immediates and instructions " + "to their negated or complemented " + "equivalent when the immediate does " + "not fit in the encoding.">; + //===----------------------------------------------------------------------===// // Architectures. // diff --git a/lib/Target/AArch64/AArch64InstrFormats.td b/lib/Target/AArch64/AArch64InstrFormats.td index 6da730618e0..16be4432b16 100644 --- a/lib/Target/AArch64/AArch64InstrFormats.td +++ b/lib/Target/AArch64/AArch64InstrFormats.td @@ -39,6 +39,9 @@ class AArch64Inst<Format f, string cstr> : Instruction { let Constraints = cstr; } +class InstSubst<string Asm, dag Result, bit EmitPriority = 0> + : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>; + // Pseudo instructions (don't have encoding information) class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = ""> : AArch64Inst<PseudoFrm, cstr> { @@ -1798,10 +1801,10 @@ multiclass AddSub<bit isSub, string mnemonic, string alias, } // add Rd, Rb, -imm -> sub Rd, Rn, imm - def : InstAlias<alias#"\t$Rd, $Rn, $imm", + def : InstSubst<alias#"\t$Rd, $Rn, $imm", (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn, addsub_shifted_imm32_neg:$imm), 0>; - def : InstAlias<alias#"\t$Rd, $Rn, $imm", + def : InstSubst<alias#"\t$Rd, $Rn, $imm", (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn, addsub_shifted_imm64_neg:$imm), 0>; @@ -1873,10 +1876,10 @@ multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp, } // Defs = [NZCV] // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm - def : InstAlias<alias#"\t$Rd, $Rn, $imm", + def : InstSubst<alias#"\t$Rd, $Rn, $imm", (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn, addsub_shifted_imm32_neg:$imm), 0>; - def : InstAlias<alias#"\t$Rd, $Rn, $imm", + def : InstSubst<alias#"\t$Rd, $Rn, $imm", (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn, addsub_shifted_imm64_neg:$imm), 0>; @@ -1897,9 +1900,9 @@ multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp, XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>; // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm - def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri") + def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri") WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>; - def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri") + def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri") XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>; // Compare shorthands @@ -2114,10 +2117,10 @@ multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode, let Inst{31} = 1; } - def : InstAlias<Alias # "\t$Rd, $Rn, $imm", + def : InstSubst<Alias # "\t$Rd, $Rn, $imm", (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn, logical_imm32_not:$imm), 0>; - def : InstAlias<Alias # "\t$Rd, $Rn, $imm", + def : InstSubst<Alias # "\t$Rd, $Rn, $imm", (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn, logical_imm64_not:$imm), 0>; } @@ -2136,10 +2139,10 @@ multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode, } } // end Defs = [NZCV] - def : InstAlias<Alias # "\t$Rd, $Rn, $imm", + def : InstSubst<Alias # "\t$Rd, $Rn, $imm", (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn, logical_imm32_not:$imm), 0>; - def : InstAlias<Alias # "\t$Rd, $Rn, $imm", + def : InstSubst<Alias # "\t$Rd, $Rn, $imm", (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn, logical_imm64_not:$imm), 0>; } diff --git a/lib/Target/AArch64/AArch64InstrInfo.td b/lib/Target/AArch64/AArch64InstrInfo.td index 6a6dba34606..4449412532f 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.td +++ b/lib/Target/AArch64/AArch64InstrInfo.td @@ -43,6 +43,11 @@ def IsBE : Predicate<"!Subtarget->isLittleEndian()">; def UseAlternateSExtLoadCVTF32 : Predicate<"Subtarget->useAlternateSExtLoadCVTF32Pattern()">; +def UseNegativeImmediates + : Predicate<"false">, AssemblerPredicate<"!FeatureNoNegativeImmediates", + "NegativeImmediates">; + + //===----------------------------------------------------------------------===// // AArch64-specific DAG Nodes. // diff --git a/lib/Target/AArch64/AArch64Subtarget.h b/lib/Target/AArch64/AArch64Subtarget.h index 0a42ba5060f..10377cbbb16 100644 --- a/lib/Target/AArch64/AArch64Subtarget.h +++ b/lib/Target/AArch64/AArch64Subtarget.h @@ -78,6 +78,10 @@ protected: // StrictAlign - Disallow unaligned memory accesses. bool StrictAlign = false; + + // NegativeImmediates - transform instructions with negative immediates + bool NegativeImmediates = true; + bool UseAA = false; bool PredictableSelectIsExpensive = false; bool BalanceFPOps = false; diff --git a/test/MC/AArch64/alias-addsubimm.s b/test/MC/AArch64/alias-addsubimm.s index 75e0a185572..5c1c4799828 100644 --- a/test/MC/AArch64/alias-addsubimm.s +++ b/test/MC/AArch64/alias-addsubimm.s @@ -1,19 +1,24 @@ // RUN: llvm-mc -triple=aarch64-none-linux-gnu < %s | FileCheck %s +// RUN: not llvm-mc -mattr=+no-neg-immediates -triple=aarch64-none-linux-gnu < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-NEG-IMM // CHECK: sub w0, w2, #2, lsl #12 // CHECK: sub w0, w2, #2, lsl #12 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates sub w0, w2, #2, lsl 12 add w0, w2, #-2, lsl 12 // CHECK: sub x1, x3, #2, lsl #12 // CHECK: sub x1, x3, #2, lsl #12 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates sub x1, x3, #2, lsl 12 add x1, x3, #-2, lsl 12 // CHECK: sub x1, x3, #4 // CHECK: sub x1, x3, #4 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates sub x1, x3, #4 add x1, x3, #-4 // CHECK: sub x1, x3, #4095 // CHECK: sub x1, x3, #4095 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates sub x1, x3, #4095, lsl 0 add x1, x3, #-4095, lsl 0 // CHECK: sub x3, x4, #0 @@ -21,18 +26,22 @@ // CHECK: add w0, w2, #2, lsl #12 // CHECK: add w0, w2, #2, lsl #12 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates add w0, w2, #2, lsl 12 sub w0, w2, #-2, lsl 12 // CHECK: add x1, x3, #2, lsl #12 // CHECK: add x1, x3, #2, lsl #12 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates add x1, x3, #2, lsl 12 sub x1, x3, #-2, lsl 12 // CHECK: add x1, x3, #4 // CHECK: add x1, x3, #4 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates add x1, x3, #4 sub x1, x3, #-4 // CHECK: add x1, x3, #4095 // CHECK: add x1, x3, #4095 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates add x1, x3, #4095, lsl 0 sub x1, x3, #-4095, lsl 0 // CHECK: add x2, x5, #0 @@ -40,18 +49,22 @@ // CHECK: subs w0, w2, #2, lsl #12 // CHECK: subs w0, w2, #2, lsl #12 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates subs w0, w2, #2, lsl 12 adds w0, w2, #-2, lsl 12 // CHECK: subs x1, x3, #2, lsl #12 // CHECK: subs x1, x3, #2, lsl #12 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates subs x1, x3, #2, lsl 12 adds x1, x3, #-2, lsl 12 // CHECK: subs x1, x3, #4 // CHECK: subs x1, x3, #4 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates subs x1, x3, #4 adds x1, x3, #-4 // CHECK: subs x1, x3, #4095 // CHECK: subs x1, x3, #4095 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates subs x1, x3, #4095, lsl 0 adds x1, x3, #-4095, lsl 0 // CHECK: subs x3, x4, #0 @@ -59,18 +72,22 @@ // CHECK: adds w0, w2, #2, lsl #12 // CHECK: adds w0, w2, #2, lsl #12 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates adds w0, w2, #2, lsl 12 subs w0, w2, #-2, lsl 12 // CHECK: adds x1, x3, #2, lsl #12 // CHECK: adds x1, x3, #2, lsl #12 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates adds x1, x3, #2, lsl 12 subs x1, x3, #-2, lsl 12 // CHECK: adds x1, x3, #4 // CHECK: adds x1, x3, #4 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates adds x1, x3, #4 subs x1, x3, #-4 // CHECK: adds x1, x3, #4095 // CHECK: adds x1, x3, #4095 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates adds x1, x3, #4095, lsl 0 subs x1, x3, #-4095, lsl 0 // CHECK: adds x2, x5, #0 @@ -78,17 +95,21 @@ // CHECK: {{adds xzr,|cmn}} x5, #5 // CHECK: {{adds xzr,|cmn}} x5, #5 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates cmn x5, #5 cmp x5, #-5 // CHECK: {{subs xzr,|cmp}} x6, #4095 // CHECK: {{subs xzr,|cmp}} x6, #4095 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates cmp x6, #4095 cmn x6, #-4095 // CHECK: {{adds wzr,|cmn}} w7, #5 // CHECK: {{adds wzr,|cmn}} w7, #5 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates cmn w7, #5 cmp w7, #-5 // CHECK: {{subs wzr,|cmp}} w8, #4095 // CHECK: {{subs wzr,|cmp}} w8, #4095 +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates cmp w8, #4095 cmn w8, #-4095 diff --git a/test/MC/AArch64/alias-logicalimm.s b/test/MC/AArch64/alias-logicalimm.s index 28ec40beac4..427a06d6514 100644 --- a/test/MC/AArch64/alias-logicalimm.s +++ b/test/MC/AArch64/alias-logicalimm.s @@ -1,41 +1,50 @@ // RUN: llvm-mc -triple=aarch64-none-linux-gnu < %s | FileCheck %s +// RUN: not llvm-mc -mattr=+no-neg-immediates -triple=aarch64-none-linux-gnu < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-NEG-IMM // CHECK: and x0, x1, #0xfffffffffffffffd // CHECK: and x0, x1, #0xfffffffffffffffd +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates and x0, x1, #~2 bic x0, x1, #2 // CHECK: and w0, w1, #0xfffffffd // CHECK: and w0, w1, #0xfffffffd +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates and w0, w1, #~2 bic w0, w1, #2 // CHECK: ands x0, x1, #0xfffffffffffffffd // CHECK: ands x0, x1, #0xfffffffffffffffd +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates ands x0, x1, #~2 bics x0, x1, #2 // CHECK: ands w0, w1, #0xfffffffd // CHECK: ands w0, w1, #0xfffffffd +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates ands w0, w1, #~2 bics w0, w1, #2 // CHECK: orr x0, x1, #0xfffffffffffffffd // CHECK: orr x0, x1, #0xfffffffffffffffd +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates orr x0, x1, #~2 orn x0, x1, #2 // CHECK: orr w2, w1, #0xfffffffc // CHECK: orr w2, w1, #0xfffffffc +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates orr w2, w1, #~3 orn w2, w1, #3 // CHECK: eor x0, x1, #0xfffffffffffffffd // CHECK: eor x0, x1, #0xfffffffffffffffd +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates eor x0, x1, #~2 eon x0, x1, #2 // CHECK: eor w2, w1, #0xfffffffc // CHECK: eor w2, w1, #0xfffffffc +// CHECK-NO-NEG-IMM: instruction requires: NegativeImmediates eor w2, w1, #~3 eon w2, w1, #3 -- 2.40.0