Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 80a3301

Browse files
author
Richard Sandiford
committed
[SystemZ] Optimize (sext (ashr (shl ...), ...))
...into (ashr (shl (anyext X), ...), ...), which requires one fewer instruction. The (anyext X) can sometimes be simplified too. I didn't do this in DAGCombiner because widening shifts isn't a win on all targets. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199114 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 1023a94 commit 80a3301

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

lib/Target/SystemZ/SystemZISelLowering.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm)
209209
// Give LowerOperation the chance to replace 64-bit ORs with subregs.
210210
setOperationAction(ISD::OR, MVT::i64, Custom);
211211

212+
// Give LowerOperation the chance to optimize SIGN_EXTEND sequences.
213+
setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
214+
212215
// FIXME: Can we support these natively?
213216
setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand);
214217
setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
@@ -2174,6 +2177,36 @@ SDValue SystemZTargetLowering::lowerOR(SDValue Op, SelectionDAG &DAG) const {
21742177
MVT::i64, HighOp, Low32);
21752178
}
21762179

2180+
SDValue SystemZTargetLowering::lowerSIGN_EXTEND(SDValue Op,
2181+
SelectionDAG &DAG) const {
2182+
// Convert (sext (ashr (shl X, C1), C2)) to
2183+
// (ashr (shl (anyext X), C1'), C2')), since wider shifts are as
2184+
// cheap as narrower ones.
2185+
SDValue N0 = Op.getOperand(0);
2186+
EVT VT = Op.getValueType();
2187+
if (N0.hasOneUse() && N0.getOpcode() == ISD::SRA) {
2188+
ConstantSDNode *SraAmt = dyn_cast<ConstantSDNode>(N0.getOperand(1));
2189+
SDValue Inner = N0.getOperand(0);
2190+
if (SraAmt && Inner.hasOneUse() && Inner.getOpcode() == ISD::SHL) {
2191+
ConstantSDNode *ShlAmt = dyn_cast<ConstantSDNode>(Inner.getOperand(1));
2192+
if (ShlAmt) {
2193+
unsigned Extra = (VT.getSizeInBits() -
2194+
N0.getValueType().getSizeInBits());
2195+
unsigned NewShlAmt = ShlAmt->getZExtValue() + Extra;
2196+
unsigned NewSraAmt = SraAmt->getZExtValue() + Extra;
2197+
EVT ShiftVT = N0.getOperand(1).getValueType();
2198+
SDValue Ext = DAG.getNode(ISD::ANY_EXTEND, SDLoc(Inner), VT,
2199+
Inner.getOperand(0));
2200+
SDValue Shl = DAG.getNode(ISD::SHL, SDLoc(Inner), VT, Ext,
2201+
DAG.getConstant(NewShlAmt, ShiftVT));
2202+
return DAG.getNode(ISD::SRA, SDLoc(N0), VT, Shl,
2203+
DAG.getConstant(NewSraAmt, ShiftVT));
2204+
}
2205+
}
2206+
}
2207+
return SDValue();
2208+
}
2209+
21772210
// Op is an atomic load. Lower it into a normal volatile load.
21782211
SDValue SystemZTargetLowering::lowerATOMIC_LOAD(SDValue Op,
21792212
SelectionDAG &DAG) const {
@@ -2426,6 +2459,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
24262459
return lowerUDIVREM(Op, DAG);
24272460
case ISD::OR:
24282461
return lowerOR(Op, DAG);
2462+
case ISD::SIGN_EXTEND:
2463+
return lowerSIGN_EXTEND(Op, DAG);
24292464
case ISD::ATOMIC_SWAP:
24302465
return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_SWAPW);
24312466
case ISD::ATOMIC_STORE:

lib/Target/SystemZ/SystemZISelLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ class SystemZTargetLowering : public TargetLowering {
279279
SDValue lowerUDIVREM(SDValue Op, SelectionDAG &DAG) const;
280280
SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
281281
SDValue lowerOR(SDValue Op, SelectionDAG &DAG) const;
282+
SDValue lowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG) const;
282283
SDValue lowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const;
283284
SDValue lowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const;
284285
SDValue lowerATOMIC_LOAD_OP(SDValue Op, SelectionDAG &DAG,

test/CodeGen/SystemZ/shift-10.ll

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ define i64 @f1(i32 %a) {
1414
ret i64 %ext
1515
}
1616

17-
; ...and again with the highest shift count.
17+
; ...and again with the highest shift count that doesn't reduce to an
18+
; ashr/sext pair.
1819
define i64 @f2(i32 %a) {
1920
; CHECK-LABEL: f2:
20-
; CHECK: sllg [[REG:%r[0-5]]], %r2, 32
21+
; CHECK: sllg [[REG:%r[0-5]]], %r2, 33
2122
; CHECK: srag %r2, [[REG]], 63
2223
; CHECK: br %r14
23-
%shr = lshr i32 %a, 31
24+
%shr = lshr i32 %a, 30
2425
%trunc = trunc i32 %shr to i1
2526
%ext = sext i1 %trunc to i64
2627
ret i64 %ext
@@ -76,3 +77,15 @@ define i64 @f6(i64 %a) {
7677
%and = and i64 %shr, 256
7778
ret i64 %and
7879
}
80+
81+
; Test another form of f1.
82+
define i64 @f7(i32 %a) {
83+
; CHECK-LABEL: f7:
84+
; CHECK: sllg [[REG:%r[0-5]]], %r2, 62
85+
; CHECK: srag %r2, [[REG]], 63
86+
; CHECK: br %r14
87+
%1 = shl i32 %a, 30
88+
%sext = ashr i32 %1, 31
89+
%ext = sext i32 %sext to i64
90+
ret i64 %ext
91+
}

0 commit comments

Comments
 (0)