Skip to content

Commit 8b82648

Browse files
committed
[X86] Turn (and (anyextend (shl X, C1), C2)) into (shl (and (anyextend X), (C1 >> C2), C2) if the AND could match a movzx.
There's one slight regression in here because we don't check that the immediate already allowed movzx before the shift. I'll fix that next. llvm-svn: 358804
1 parent 8f28f7a commit 8b82648

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3976,22 +3976,36 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
39763976

39773977
// For operations of the form (x << C1) op C2, check if we can use a smaller
39783978
// encoding for C2 by transforming it into (x op (C2>>C1)) << C1.
3979-
SDValue N0 = Node->getOperand(0);
3979+
SDValue Shift = Node->getOperand(0);
39803980
SDValue N1 = Node->getOperand(1);
39813981

3982-
if (N0->getOpcode() != ISD::SHL || !N0->hasOneUse())
3982+
ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N1);
3983+
if (!Cst)
3984+
break;
3985+
3986+
// If we have an any_extend feeding the AND, look through it to see if there
3987+
// is a shift behind it. But only if the AND doesn't use the extended bits.
3988+
// FIXME: Generalize this to other ANY_EXTEND than i32 to i64?
3989+
int64_t Val = Cst->getSExtValue();
3990+
bool FoundAnyExtend = false;
3991+
if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() &&
3992+
Shift.getOperand(0).getSimpleValueType() == MVT::i32 &&
3993+
isUInt<32>(Val)) {
3994+
FoundAnyExtend = true;
3995+
Shift = Shift.getOperand(0);
3996+
}
3997+
3998+
if (Shift.getOpcode() != ISD::SHL || !Shift.hasOneUse())
39833999
break;
39844000

39854001
// i8 is unshrinkable, i16 should be promoted to i32.
39864002
if (NVT != MVT::i32 && NVT != MVT::i64)
39874003
break;
39884004

3989-
ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N1);
3990-
ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(N0->getOperand(1));
3991-
if (!Cst || !ShlCst)
4005+
ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(Shift.getOperand(1));
4006+
if (!ShlCst)
39924007
break;
39934008

3994-
int64_t Val = Cst->getSExtValue();
39954009
uint64_t ShAmt = ShlCst->getZExtValue();
39964010

39974011
// Make sure that we don't change the operation by removing bits.
@@ -4028,13 +4042,19 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
40284042

40294043
int64_t ShiftedVal;
40304044
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+
}
4051+
40314052
SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
40324053
insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
4033-
SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, N0->getOperand(0),
4034-
NewCst);
4054+
SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
40354055
insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
40364056
SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
4037-
N0->getOperand(1));
4057+
Shift.getOperand(1));
40384058
ReplaceNode(Node, NewSHL.getNode());
40394059
SelectCode(NewSHL.getNode());
40404060
return;

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,9 @@ define i32 @test12(i32 %x, i32* %y) nounwind {
152152
define i64 @test13(i64 %x, i64* %y) nounwind {
153153
; CHECK-LABEL: test13:
154154
; CHECK: # %bb.0:
155-
; CHECK-NEXT: addl %edi, %edi
156-
; CHECK-NEXT: movzbl %dil, %eax
155+
; CHECK-NEXT: movq %rdi, %rax
156+
; CHECK-NEXT: andl $127, %eax
157+
; CHECK-NEXT: addq %rax, %rax
157158
; CHECK-NEXT: movq %rax, (%rsi)
158159
; CHECK-NEXT: retq
159160
%and = shl i64 %x, 1
@@ -212,9 +213,8 @@ define i32 @test17(i32 %x) nounwind {
212213
define i64 @test18(i64 %x) nounwind {
213214
; CHECK-LABEL: test18:
214215
; CHECK: # %bb.0:
215-
; CHECK-NEXT: movq %rdi, %rax
216-
; CHECK-NEXT: shll $10, %eax
217-
; CHECK-NEXT: andl $261120, %eax # imm = 0x3FC00
216+
; CHECK-NEXT: movzbl %dil, %eax
217+
; CHECK-NEXT: shlq $10, %rax
218218
; CHECK-NEXT: retq
219219
%and = shl i64 %x, 10
220220
%shl = and i64 %and, 261120
@@ -235,9 +235,8 @@ define i32 @test19(i32 %x) nounwind {
235235
define i64 @test20(i64 %x) nounwind {
236236
; CHECK-LABEL: test20:
237237
; CHECK: # %bb.0:
238-
; CHECK-NEXT: movq %rdi, %rax
239-
; CHECK-NEXT: shll $10, %eax
240-
; CHECK-NEXT: andl $67107840, %eax # imm = 0x3FFFC00
238+
; CHECK-NEXT: movzwl %di, %eax
239+
; CHECK-NEXT: shlq $10, %rax
241240
; CHECK-NEXT: retq
242241
%and = shl i64 %x, 10
243242
%shl = and i64 %and, 67107840

0 commit comments

Comments
 (0)