Skip to content

Commit 4d4b5d9

Browse files
committed
[X86] Don't turn (and (shl X, C1), C2) into (shl (and X, (C1 >> C2), C2) if the original AND can represented by MOVZX.
The MOVZX doesn't require an immediate to be encoded at all. Though it does use a 2 byte opcode so its the same size as a 1 byte immediate. But it has a separate source and dest register so can help avoid copies. llvm-svn: 358805
1 parent 8b82648 commit 4d4b5d9

File tree

2 files changed

+41
-24
lines changed

2 files changed

+41
-24
lines changed

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3983,10 +3983,11 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
39833983
if (!Cst)
39843984
break;
39853985

3986+
int64_t Val = Cst->getSExtValue();
3987+
39863988
// If we have an any_extend feeding the AND, look through it to see if there
39873989
// is a shift behind it. But only if the AND doesn't use the extended bits.
39883990
// FIXME: Generalize this to other ANY_EXTEND than i32 to i64?
3989-
int64_t Val = Cst->getSExtValue();
39903991
bool FoundAnyExtend = false;
39913992
if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() &&
39923993
Shift.getOperand(0).getSimpleValueType() == MVT::i32 &&
@@ -4041,26 +4042,44 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
40414042
};
40424043

40434044
int64_t ShiftedVal;
4044-
if (CanShrinkImmediate(ShiftedVal)) {
4045-
SDValue X = Shift.getOperand(0);
4046-
if (FoundAnyExtend) {
4047-
SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X);
4048-
insertDAGNode(*CurDAG, SDValue(Node, 0), NewX);
4049-
X = NewX;
4050-
}
4045+
if (!CanShrinkImmediate(ShiftedVal))
4046+
break;
40514047

4052-
SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
4053-
insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
4054-
SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
4055-
insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
4056-
SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
4057-
Shift.getOperand(1));
4058-
ReplaceNode(Node, NewSHL.getNode());
4059-
SelectCode(NewSHL.getNode());
4060-
return;
4048+
// Ok, we can reorder to get a smaller immediate.
4049+
4050+
// But, its possible the original immediate allowed an AND to become MOVZX.
4051+
// Doing this late due to avoid the MakedValueIsZero call as late as
4052+
// possible.
4053+
if (Opcode == ISD::AND) {
4054+
// Find the smallest zext this could possibly be.
4055+
unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
4056+
ZExtWidth = PowerOf2Ceil(std::max(ZExtWidth, 8U));
4057+
4058+
// Figure out which bits need to be zero to achieve that mask.
4059+
APInt NeededMask = APInt::getLowBitsSet(NVT.getSizeInBits(),
4060+
ZExtWidth);
4061+
NeededMask &= ~Cst->getAPIntValue();
4062+
4063+
if (CurDAG->MaskedValueIsZero(Node->getOperand(0), NeededMask))
4064+
break;
40614065
}
40624066

4063-
break;
4067+
SDValue X = Shift.getOperand(0);
4068+
if (FoundAnyExtend) {
4069+
SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X);
4070+
insertDAGNode(*CurDAG, SDValue(Node, 0), NewX);
4071+
X = NewX;
4072+
}
4073+
4074+
SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
4075+
insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
4076+
SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
4077+
insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
4078+
SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
4079+
Shift.getOperand(1));
4080+
ReplaceNode(Node, NewSHL.getNode());
4081+
SelectCode(NewSHL.getNode());
4082+
return;
40644083
}
40654084
case X86ISD::SMUL:
40664085
// i16/i32/i64 are handled with isel patterns.

llvm/test/CodeGen/X86/narrow-shl-cst.ll

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,8 @@ define i64 @test11(i64 %x) nounwind {
138138
define i32 @test12(i32 %x, i32* %y) nounwind {
139139
; CHECK-LABEL: test12:
140140
; CHECK: # %bb.0:
141-
; CHECK-NEXT: movl %edi, %eax
142-
; CHECK-NEXT: andl $127, %eax
143-
; CHECK-NEXT: addl %eax, %eax
141+
; CHECK-NEXT: addl %edi, %edi
142+
; CHECK-NEXT: movzbl %dil, %eax
144143
; CHECK-NEXT: movl %eax, (%rsi)
145144
; CHECK-NEXT: retq
146145
%and = shl i32 %x, 1
@@ -152,9 +151,8 @@ define i32 @test12(i32 %x, i32* %y) nounwind {
152151
define i64 @test13(i64 %x, i64* %y) nounwind {
153152
; CHECK-LABEL: test13:
154153
; CHECK: # %bb.0:
155-
; CHECK-NEXT: movq %rdi, %rax
156-
; CHECK-NEXT: andl $127, %eax
157-
; CHECK-NEXT: addq %rax, %rax
154+
; CHECK-NEXT: addl %edi, %edi
155+
; CHECK-NEXT: movzbl %dil, %eax
158156
; CHECK-NEXT: movq %rax, (%rsi)
159157
; CHECK-NEXT: retq
160158
%and = shl i64 %x, 1

0 commit comments

Comments
 (0)