diff options
author | Craig Topper <craig.topper@intel.com> | 2019-03-28 18:05:37 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2019-03-28 18:05:37 +0000 |
commit | c25c9b4d162695c3537fdd0996c92290bcd30a9e (patch) | |
tree | 9bc2b41c22dbc87699575da78f10b17605bf388b /llvm/lib | |
parent | fc5ddeeab30fd89fe012719019cd83658d6c11e4 (diff) | |
download | bcm5719-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.cpp | 52 |
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. |