summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2019-04-03 15:09:19 +0000
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2019-04-03 15:09:19 +0000
commit35dfd1b7dfe9ca5ac7b61a2bee94e227fefc066a (patch)
tree1c3787ebf0cb9057f9535adf65f8e312d3de9013 /llvm/lib
parentff3397247fc08f0b8af9905323a760db1a0902a9 (diff)
downloadbcm5719-llvm-35dfd1b7dfe9ca5ac7b61a2bee94e227fefc066a.tar.gz
bcm5719-llvm-35dfd1b7dfe9ca5ac7b61a2bee94e227fefc066a.zip
[SystemZ] Improve codegen for certain SADDO-immediate cases
When performing an add-with-overflow with an immediate in the range -2G ... -4G, code currently loads the immediate into a register, which generally takes two instructions. In this particular case, it is preferable to load the negated immediate into a register instead, which always only requires one instruction, and then perform a subtract. llvm-svn: 357597
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.td8
-rw-r--r--llvm/lib/Target/SystemZ/SystemZOperands.td20
2 files changed, 28 insertions, 0 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
index 10081262389..edef54eef01 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -1029,6 +1029,14 @@ let AddedComplexity = 1 in {
(AGFI GR64:$src1, imm64sx32n:$src2)>;
}
+// And vice versa in one special case, where we need to load a
+// constant into a register in any case, but the negated constant
+// requires fewer instructions to load.
+def : Pat<(z_saddo GR64:$src1, imm64lh16n:$src2),
+ (SGR GR64:$src1, (LLILH imm64lh16n:$src2))>;
+def : Pat<(z_saddo GR64:$src1, imm64lf32n:$src2),
+ (SGR GR64:$src1, (LLILF imm64lf32n:$src2))>;
+
// Subtraction producing a carry.
let Defs = [CC] in {
// Subtraction of a register.
diff --git a/llvm/lib/Target/SystemZ/SystemZOperands.td b/llvm/lib/Target/SystemZ/SystemZOperands.td
index 4d0c5d02ffa..56632e1529a 100644
--- a/llvm/lib/Target/SystemZ/SystemZOperands.td
+++ b/llvm/lib/Target/SystemZ/SystemZOperands.td
@@ -188,6 +188,17 @@ def HF32 : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(Value, SDLoc(N), MVT::i64);
}]>;
+// Negated variants.
+def NEGLH16 : SDNodeXForm<imm, [{
+ uint64_t Value = (-N->getZExtValue() & 0x00000000FFFF0000ULL) >> 16;
+ return CurDAG->getTargetConstant(Value, SDLoc(N), MVT::i64);
+}]>;
+
+def NEGLF32 : SDNodeXForm<imm, [{
+ uint64_t Value = -N->getZExtValue() & 0x00000000FFFFFFFFULL;
+ return CurDAG->getTargetConstant(Value, SDLoc(N), MVT::i64);
+}]>;
+
// Truncate an immediate to a 8-bit signed quantity.
def SIMM8 : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(int8_t(N->getZExtValue()), SDLoc(N),
@@ -430,6 +441,15 @@ def imm64hf32c : Immediate<i64, [{
return SystemZ::isImmHF(uint64_t(~N->getZExtValue()));
}], HF32, "U32Imm">;
+// Negated immediates that fit LF32 or LH16.
+def imm64lh16n : Immediate<i64, [{
+ return SystemZ::isImmLH(uint64_t(-N->getZExtValue()));
+}], NEGLH16, "U16Imm">;
+
+def imm64lf32n : Immediate<i64, [{
+ return SystemZ::isImmLF(uint64_t(-N->getZExtValue()));
+}], NEGLF32, "U32Imm">;
+
// Short immediates.
def imm64sx8 : Immediate<i64, [{
return isInt<8>(N->getSExtValue());
OpenPOWER on IntegriCloud