summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorCraig Topper <craig.topper@intel.com>2019-03-28 18:05:37 +0000
committerCraig Topper <craig.topper@intel.com>2019-03-28 18:05:37 +0000
commitc25c9b4d162695c3537fdd0996c92290bcd30a9e (patch)
tree9bc2b41c22dbc87699575da78f10b17605bf388b /llvm/lib
parentfc5ddeeab30fd89fe012719019cd83658d6c11e4 (diff)
downloadbcm5719-llvm-c25c9b4d162695c3537fdd0996c92290bcd30a9e.tar.gz
bcm5719-llvm-c25c9b4d162695c3537fdd0996c92290bcd30a9e.zip
[X86] Teach the isel optimization for (x << C1) op C2 to (x op (C2>>C1)) << C1 to consider cases where C2>>C1 can fit an unsigned 32-bit immediate
For 64-bit operations we should consider if the immediate can be made to fit in an unsigned 32-bits immedate. For OR/XOR this allows us to load the immediate with MOV32ri instead of movabsq. For AND this allows us to fold the immediate. Differential Revision: https://reviews.llvm.org/D59867 llvm-svn: 357196
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/X86ISelDAGToDAG.cpp52
1 files changed, 29 insertions, 23 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 89585d74cb8..1832cd222dd 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -3501,39 +3501,45 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
break;
int64_t Val = Cst->getSExtValue();
- uint64_t ShlVal = ShlCst->getZExtValue();
+ uint64_t ShAmt = ShlCst->getZExtValue();
// Make sure that we don't change the operation by removing bits.
// This only matters for OR and XOR, AND is unaffected.
- uint64_t RemovedBitsMask = (1ULL << ShlVal) - 1;
+ uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
if (Opcode != ISD::AND && (Val & RemovedBitsMask) != 0)
break;
- MVT CstVT = NVT;
-
// Check the minimum bitwidth for the new constant.
- // TODO: AND32ri is the same as AND64ri32 with zext imm.
- // TODO: MOV32ri+OR64r is cheaper than MOV64ri64+OR64rr
// TODO: Using 16 and 8 bit operations is also possible for or32 & xor32.
- if (!isInt<8>(Val) && isInt<8>(Val >> ShlVal))
- CstVT = MVT::i8;
- else if (!isInt<32>(Val) && isInt<32>(Val >> ShlVal))
- CstVT = MVT::i32;
+ auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
+ ShiftedVal = Val >> ShAmt;
+ if ((!isInt<8>(Val) && isInt<8>(ShiftedVal)) ||
+ (!isInt<32>(Val) && isInt<32>(ShiftedVal)))
+ return true;
+ // For 64-bit we can also try unsigned 32 bit immediates.
+ // AND32ri is the same as AND64ri32 with zext imm.
+ // MOV32ri+OR64r is cheaper than MOV64ri64+OR64rr
+ ShiftedVal = (uint64_t)Val >> ShAmt;
+ if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
+ return true;
+ return false;
+ };
- // Bail if there is no smaller encoding.
- if (NVT == CstVT)
- break;
+ int64_t ShiftedVal;
+ if (CanShrinkImmediate(ShiftedVal)) {
+ SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
+ insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
+ SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, N0->getOperand(0),
+ NewCst);
+ insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
+ SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
+ N0->getOperand(1));
+ ReplaceNode(Node, NewSHL.getNode());
+ SelectCode(NewSHL.getNode());
+ return;
+ }
- SDValue NewCst = CurDAG->getConstant(Val >> ShlVal, dl, NVT);
- insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
- SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, N0->getOperand(0),
- NewCst);
- insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
- SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
- N0->getOperand(1));
- ReplaceNode(Node, NewSHL.getNode());
- SelectCode(NewSHL.getNode());
- return;
+ break;
}
case X86ISD::SMUL:
// i16/i32/i64 are handled with isel patterns.
OpenPOWER on IntegriCloud