Index: llvm/trunk/lib/Target/AArch64/AArch64.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64.td +++ llvm/trunk/lib/Target/AArch64/AArch64.td @@ -118,6 +118,14 @@ 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. // Index: llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td +++ llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td @@ -39,6 +39,9 @@ let Constraints = cstr; } +class InstSubst + : InstAlias, Requires<[UseNegativeImmediates]>; + // Pseudo instructions (don't have encoding information) class Pseudo pattern, string cstr = ""> : AArch64Inst { @@ -1798,10 +1801,10 @@ } // add Rd, Rb, -imm -> sub Rd, Rn, imm - def : InstAlias(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn, addsub_shifted_imm32_neg:$imm), 0>; - def : InstAlias(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn, addsub_shifted_imm64_neg:$imm), 0>; @@ -1873,10 +1876,10 @@ } // Defs = [NZCV] // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm - def : InstAlias(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn, addsub_shifted_imm32_neg:$imm), 0>; - def : InstAlias(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn, addsub_shifted_imm64_neg:$imm), 0>; @@ -1897,9 +1900,9 @@ XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>; // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm - def : InstAlias(NAME#"Wri") + def : InstSubst(NAME#"Wri") WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>; - def : InstAlias(NAME#"Xri") + def : InstSubst(NAME#"Xri") XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>; // Compare shorthands @@ -2114,10 +2117,10 @@ let Inst{31} = 1; } - def : InstAlias(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn, logical_imm32_not:$imm), 0>; - def : InstAlias(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn, logical_imm64_not:$imm), 0>; } @@ -2136,10 +2139,10 @@ } } // end Defs = [NZCV] - def : InstAlias(NAME # "Wri") GPR32:$Rd, GPR32:$Rn, logical_imm32_not:$imm), 0>; - def : InstAlias(NAME # "Xri") GPR64:$Rd, GPR64:$Rn, logical_imm64_not:$imm), 0>; } Index: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td @@ -43,6 +43,11 @@ def UseAlternateSExtLoadCVTF32 : Predicate<"Subtarget->useAlternateSExtLoadCVTF32Pattern()">; +def UseNegativeImmediates + : Predicate<"false">, AssemblerPredicate<"!FeatureNoNegativeImmediates", + "NegativeImmediates">; + + //===----------------------------------------------------------------------===// // AArch64-specific DAG Nodes. // Index: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h +++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h @@ -78,6 +78,10 @@ // 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; Index: llvm/trunk/test/MC/AArch64/alias-addsubimm.s =================================================================== --- llvm/trunk/test/MC/AArch64/alias-addsubimm.s +++ llvm/trunk/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 Index: llvm/trunk/test/MC/AArch64/alias-logicalimm.s =================================================================== --- llvm/trunk/test/MC/AArch64/alias-logicalimm.s +++ llvm/trunk/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