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