Index: lib/Target/X86/X86InstrCompiler.td =================================================================== --- lib/Target/X86/X86InstrCompiler.td +++ lib/Target/X86/X86InstrCompiler.td @@ -262,6 +262,25 @@ let AddedComplexity = 20; } +let Predicates = [OptForSize, NotSlowIncDec], AddedComplexity = 10 in { + // These encode to 3 bytes (32-bit mode) or 4 bytes (64-bit), which is shorter + // than the 5-byte "movl %reg, imm32". + def : Pat<(i32 1), (INC32r (MOV32r0))>; + def : Pat<(i32 -1), (DEC32r (MOV32r0))>; + def : Pat<(i64 1), (SUBREG_TO_REG (i64 0), (INC32r (MOV32r0)), sub_32bit)>; + + // For 64-bit -1, we need a 64-bit decrement, so this totals 5 bytes, which + // is smaller than "movq %reg, imm64" (7 bytes). + def : Pat<(i64 -1), (DEC64r (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit))>; + + let Predicates = [Not64BitMode] in { + // "mov %r, imm16" encodes to 4 bytes, so the alternative lowering is only + // profitable in non-64-bit mode. + def : Pat<(i16 1), (EXTRACT_SUBREG (INC32r (MOV32r0)), sub_16bit)>; + def : Pat<(i16 -1), (EXTRACT_SUBREG (DEC32r (MOV32r0)), sub_16bit)>; + } +} + // Materialize i64 constant where top 32-bits are zero. This could theoretically // use MOV32ri with a SUBREG_TO_REG to represent the zero-extension, however // that would make it more difficult to rematerialize. Index: test/CodeGen/X86/materialize-one.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/materialize-one.ll @@ -0,0 +1,70 @@ +; RUN: llc -mtriple=i686-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK32 +; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK64 + +define i32 @one32() optsize { +entry: + ret i32 1 + +; CHECK-LABEL: one32 +; CHECK: xorl %eax, %eax +; CHECK-NEXT: incl %eax +; CHECK-NEXT: ret +} + +define i32 @minus_one32() optsize { +entry: + ret i32 -1 + +; CHECK-LABEL: minus_one32 +; CHECK: xorl %eax, %eax +; CHECK-NEXT: decl %eax +; CHECK-NEXT: ret +} + +define i64 @one64() optsize { +entry: + ret i64 1 + +; CHECK64-LABEL: one64 +; CHECK64: xorl %eax, %eax +; CHECK64-NEXT: incl %eax +; CHECK64-NEXT: retq +} + +define i64 @minus_one64() optsize { +entry: + ret i64 -1 + +; CHECK64-LABEL: minus_one64 +; CHECK64: xorl %eax, %eax +; CHECK64-NEXT: decq %rax +; CHECK64-NEXT: retq +} + +define i16 @one16() optsize { +entry: + ret i16 1 + +; CHECK32-LABEL: one16 +; CHECK32: xorl %eax, %eax +; CHECK32-NEXT: incl %eax +; CHECK32-NEXT: retl + +; CHECK64-LABEL: one16 +; CHECK64: movw $1, %ax +; CHECK64-NEXT: retq +} + +define i16 @minus_one16() optsize { +entry: + ret i16 -1 + +; CHECK32-LABEL: minus_one16 +; CHECK32: xorl %eax, %eax +; CHECK32-NEXT: decl %eax +; CHECK32-NEXT: retl + +; CHECK64-LABEL: minus_one16 +; CHECK64: movw $-1, %ax +; CHECK64-NEXT: retq +}