Skip to content

Commit

Permalink
[X86] Use "and $0" and "orl $-1" to store 0 and -1 when optimizing fo…
Browse files Browse the repository at this point in the history
…r minsize

64-bit, 32-bit and 16-bit move-immediate instructions are 7, 6, and 5 bytes,
respectively, whereas and/or with 8-bit immediate is only three bytes.

Since these instructions imply an additional memory read (which the CPU could
elide, but we don't think it does), restrict these patterns to minsize functions.

Differential Revision: http://reviews.llvm.org/D18374

llvm-svn: 264440
  • Loading branch information
zmodem committed Mar 25, 2016
1 parent 9cd77ce commit 5f916d3
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 1 deletion.
12 changes: 12 additions & 0 deletions llvm/lib/Target/X86/X86InstrCompiler.td
Expand Up @@ -1001,6 +1001,18 @@ def ACQUIRE_MOV64rm : I<0, Pseudo, (outs GR64:$dst), (ins i64mem:$src),
// DAG Pattern Matching Rules
//===----------------------------------------------------------------------===//

// Use AND/OR to store 0/-1 in memory when optimizing for minsize. This saves
// binary size compared to a regular MOV, but it introduces an unnecessary
// load, so is not suitable for regular or optsize functions.
let Predicates = [OptForMinSize] in {
def : Pat<(store (i16 0), addr:$dst), (AND16mi8 addr:$dst, 0)>;
def : Pat<(store (i32 0), addr:$dst), (AND32mi8 addr:$dst, 0)>;
def : Pat<(store (i64 0), addr:$dst), (AND64mi8 addr:$dst, 0)>;
def : Pat<(store (i16 -1), addr:$dst), (OR16mi8 addr:$dst, -1)>;
def : Pat<(store (i32 -1), addr:$dst), (OR32mi8 addr:$dst, -1)>;
def : Pat<(store (i64 -1), addr:$dst), (OR64mi8 addr:$dst, -1)>;
}

// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable
def : Pat<(i32 (X86Wrapper tconstpool :$dst)), (MOV32ri tconstpool :$dst)>;
def : Pat<(i32 (X86Wrapper tjumptable :$dst)), (MOV32ri tjumptable :$dst)>;
Expand Down
88 changes: 88 additions & 0 deletions llvm/test/CodeGen/X86/store-zero-and-minus-one.ll
@@ -0,0 +1,88 @@
; RUN: llc -mtriple=i686-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=CHECK32 --check-prefix=CHECK
; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=CHECK64 --check-prefix=CHECK

define void @zero_optsize(i32* %p) optsize {
entry:
store i32 0, i32* %p
ret void

; CHECK-LABEL: zero_optsize:
; CHECK: movl $0
; CHECK: ret
}

define void @minus_one_optsize(i32* %p) optsize {
entry:
store i32 -1, i32* %p
ret void

; CHECK-LABEL: minus_one_optsize:
; CHECK: movl $-1
; CHECK: ret
}


define void @zero_64(i64* %p) minsize {
entry:
store i64 0, i64* %p
ret void

; CHECK-LABEL: zero_64:
; CHECK32: andl $0
; CHECK32: andl $0
; CHECK64: andq $0
; CHECK: ret
}

define void @zero_32(i32* %p) minsize {
entry:
store i32 0, i32* %p
ret void

; CHECK-LABEL: zero_32:
; CHECK: andl $0
; CHECK: ret
}

define void @zero_16(i16* %p) minsize {
entry:
store i16 0, i16* %p
ret void

; CHECK-LABEL: zero_16:
; CHECK: andw $0
; CHECK: ret
}


define void @minus_one_64(i64* %p) minsize {
entry:
store i64 -1, i64* %p
ret void

; CHECK-LABEL: minus_one_64:
; CHECK32: orl $-1
; CHECK32: orl $-1
; CHECK64: orq $-1
; CHECK: ret
}

define void @minus_one_32(i32* %p) minsize {
entry:
store i32 -1, i32* %p
ret void

; CHECK-LABEL: minus_one_32:
; CHECK: orl $-1
; CHECK: ret
}

define void @minus_one_16(i16* %p) minsize {
entry:
store i16 -1, i16* %p
ret void

; CHECK-LABEL: minus_one_16:
; CHECK: orw $-1
; CHECK: ret
}
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/X86/tail-opts.ll
Expand Up @@ -376,7 +376,7 @@ return:
; CHECK-LABEL: two_minsize:
; CHECK-NOT: XYZ
; CHECK: ret
; CHECK: movl $0, XYZ(%rip)
; CHECK: andl $0, XYZ(%rip)
; CHECK: movl $1, XYZ(%rip)
; CHECK-NOT: XYZ

Expand Down

0 comments on commit 5f916d3

Please sign in to comment.