diff options
-rw-r--r-- | lib/Target/X86/X86InstrCompiler.td | 21 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 5 | ||||
-rw-r--r-- | test/CodeGen/X86/andimm8.ll | 10 |
3 files changed, 33 insertions, 3 deletions
diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td index 6bfd605f61..5f13885946 100644 --- a/lib/Target/X86/X86InstrCompiler.td +++ b/lib/Target/X86/X86InstrCompiler.td @@ -20,6 +20,11 @@ def GetLo32XForm : SDNodeXForm<imm, [{ return getI32Imm((unsigned)N->getZExtValue()); }]>; +def GetLo8XForm : SDNodeXForm<imm, [{ + // Transformation function: get the low 8 bits. + return getI8Imm((uint8_t)N->getZExtValue()); +}]>; + //===----------------------------------------------------------------------===// // Random Pseudo Instructions. @@ -1106,9 +1111,19 @@ def : Pat<(add GR64:$src1, 0x0000000080000000), def : Pat<(store (add (loadi64 addr:$dst), 0x00000000800000000), addr:$dst), (SUB64mi32 addr:$dst, 0xffffffff80000000)>; -// Use a 32-bit and with implicit zero-extension instead of a 64-bit and if it -// has an immediate with at least 32 bits of leading zeros, to avoid needing to -// materialize that immediate in a register first. +// To avoid needing to materialize an immediate in a register, use a 32-bit and +// with implicit zero-extension instead of a 64-bit and if the immediate has at +// least 32 bits of leading zeros. If in addition the last 32 bits can be +// represented with a sign extension of a 8 bit constant, use that. + +def : Pat<(and GR64:$src, i64immZExt32SExt8:$imm), + (SUBREG_TO_REG + (i64 0), + (AND32ri8 + (EXTRACT_SUBREG GR64:$src, sub_32bit), + (i32 (GetLo8XForm imm:$imm))), + sub_32bit)>; + def : Pat<(and GR64:$src, i64immZExt32:$imm), (SUBREG_TO_REG (i64 0), diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index ed5e407dcc..14d673a36a 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -473,6 +473,11 @@ def i64immZExt32 : PatLeaf<(i64 imm), [{ return (uint64_t)N->getZExtValue() == (uint32_t)N->getZExtValue(); }]>; +def i64immZExt32SExt8 : PatLeaf<(i64 imm), [{ + uint64_t v = N->getZExtValue(); + return v == (uint32_t)v && (int32_t)v == (int8_t)v; +}]>; + // Helper fragments for loads. // It's always safe to treat a anyext i16 load as a i32 load if the i16 is // known to be 32-bit aligned or better. Ditto for i8 to i16. diff --git a/test/CodeGen/X86/andimm8.ll b/test/CodeGen/X86/andimm8.ll new file mode 100644 index 0000000000..059919c8ef --- /dev/null +++ b/test/CodeGen/X86/andimm8.ll @@ -0,0 +1,10 @@ +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-linux-gnu -show-mc-encoding | FileCheck %s + +; PR8365 +; CHECK: andl $-64, %edi # encoding: [0x83,0xe7,0xc0] + +define i64 @bra(i32 %zed) nounwind { + %t1 = zext i32 %zed to i64 + %t2 = and i64 %t1, 4294967232 + ret i64 %t2 +} |