Index: lib/Target/SystemZ/SystemZInstrInfo.td =================================================================== --- lib/Target/SystemZ/SystemZInstrInfo.td +++ lib/Target/SystemZ/SystemZInstrInfo.td @@ -1685,6 +1685,14 @@ def : Pat<(and (xor GR64:$x, (i64 -1)), GR64:$y), (XGR GR64:$y, (NGR GR64:$y, GR64:$x))>; +// Generate fewer instructions for (sub , x) if the constant can fit +// in immediate field. +def : Pat<(sub imm64sx16:$imm, GR64:$x), + (SGRK (LGHI imm64sx16:$imm), GR64:$x)>; + +def : Pat<(sub imm64sx32:$imm, GR64:$x), + (SGRK (LGFI imm64sx32:$imm), GR64:$x)>; + // Shift/rotate instructions only use the last 6 bits of the second operand // register, so we can safely use NILL (16 fewer bits than NILF) to only AND the // last 16 bits. Index: test/CodeGen/SystemZ/int-sub-10.ll =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/int-sub-10.ll @@ -0,0 +1,22 @@ +; Test of subtraction that involves a constant as the first operand +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check highest 16-bit signed int immediate value. +define i64 @f1(i64 %a) { +; CHECK-LABEL: f1: +; CHECK: lghi %r0, 32767 +; CHECK: sgrk %r2, %r0, %r2 +; CHECK: br %r14 + %sub = sub i64 32767, %a + ret i64 %sub +} +; Check highest 32-bit signed int immediate value. +define i64 @f2(i64 %a) { +; CHECK-LABEL: f2: +; CHECK: lgfi %r0, 2147483647 +; CHECK: sgrk %r2, %r0, %r2 +; CHECK: br %r14 + %sub = sub i64 2147483647, %a + ret i64 %sub +}