Index: lib/Target/SystemZ/SystemZInstrInfo.td =================================================================== --- lib/Target/SystemZ/SystemZInstrInfo.td +++ lib/Target/SystemZ/SystemZInstrInfo.td @@ -1685,6 +1685,17 @@ 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), + (AGHI (LCGR GR64:$x), imm64sx16:$imm)>; + +def : Pat<(sub imm64sx32:$imm, GR64:$x), + (AGFI (LCGR GR64:$x), imm64sx32:$imm)>; + +def : Pat<(sub imm64zx32:$imm, GR64:$x), + (ALGFI (LCGR GR64:$x), imm64zx32:$imm)>; + // 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,53 @@ +; Test of subtraction that involves a constant as the first operand +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s + +; Check AGHI highest immediate value. +define i64 @f1(i64 %a) { +; CHECK-LABEL: f1: +; CHECK: lcgr %r2, %r2 +; CHECK: aghi %r2, 32767 +; CHECK: br %r14 + %sub = sub i64 32767, %a + ret i64 %sub +} + +; Check AGFI immediate value that cannot fit in AGHI. +define i64 @f2(i64 %a) { +; CHECK-LABEL: f2: +; CHECK: lcgr %r2, %r2 +; CHECK: agfi %r2, 32768 +; CHECK: br %r14 + %sub = sub i64 32768, %a + ret i64 %sub +} + +; Check AGFI highest immediate value. +define i64 @f3(i64 %a) { +; CHECK-LABEL: f3: +; CHECK: lcgr %r2, %r2 +; CHECK: agfi %r2, 2147483647 +; CHECK: br %r14 + %sub = sub i64 2147483647, %a + ret i64 %sub +} + +; Check ALGFI immediate value that cannot fit in AGFI. +define i64 @f4(i64 %a) { +; CHECK-LABEL: f4: +; CHECK: lcgr %r2, %r2 +; CHECK: algfi %r2, 2147483648 +; CHECK: br %r14 + %sub = sub i64 2147483648, %a + ret i64 %sub +} + +; Check ALGFI highest immediate value. +define i64 @f5(i64 %a) { +; CHECK-LABEL: f5: +; CHECK: lcgr %r2, %r2 +; CHECK: algfi %r2, 4294967295 +; CHECK: br %r14 + %sub = sub i64 4294967295, %a + ret i64 %sub +}