Skip to content

Commit f9a9e9a

Browse files
committedJan 31, 2018
[X86] Generate testl instruction through truncates.
Summary: This was introduced in D42646 but ended up being reverted because the original implementation was buggy. Depends on D42646 Reviewers: craig.topper, niravd, spatel, hfinkel Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D42741 llvm-svn: 323899
1 parent 60d1e79 commit f9a9e9a

File tree

3 files changed

+48
-67
lines changed

3 files changed

+48
-67
lines changed
 

‎llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 44 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3052,70 +3052,55 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
30523052
if (!C) break;
30533053
uint64_t Mask = C->getZExtValue();
30543054

3055-
// For example, convert "testl %eax, $8" to "testb %al, $8"
3055+
MVT VT;
3056+
int SubRegOp;
3057+
unsigned Op;
3058+
30563059
if (isUInt<8>(Mask) &&
30573060
(!(Mask & 0x80) || hasNoSignedComparisonUses(Node))) {
3058-
SDValue Imm = CurDAG->getTargetConstant(Mask, dl, MVT::i8);
3059-
SDValue Reg = N0.getOperand(0);
3060-
3061-
// Extract the l-register.
3062-
SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::sub_8bit, dl,
3063-
MVT::i8, Reg);
3064-
3065-
// Emit a testb.
3066-
SDNode *NewNode = CurDAG->getMachineNode(X86::TEST8ri, dl, MVT::i32,
3067-
Subreg, Imm);
3068-
// Replace SUB|CMP with TEST, since SUB has two outputs while TEST has
3069-
// one, do not call ReplaceAllUsesWith.
3070-
ReplaceUses(SDValue(Node, (Opcode == X86ISD::SUB ? 1 : 0)),
3071-
SDValue(NewNode, 0));
3072-
CurDAG->RemoveDeadNode(Node);
3073-
return;
3061+
// For example, convert "testl %eax, $8" to "testb %al, $8"
3062+
VT = MVT::i8;
3063+
SubRegOp = X86::sub_8bit;
3064+
Op = X86::TEST8ri;
3065+
} else if (OptForMinSize && isUInt<16>(Mask) &&
3066+
(!(Mask & 0x8000) || hasNoSignedComparisonUses(Node))) {
3067+
// For example, "testl %eax, $32776" to "testw %ax, $32776".
3068+
// NOTE: We only want to form TESTW instructions if optimizing for
3069+
// min size. Otherwise we only save one byte and possibly get a length
3070+
// changing prefix penalty in the decoders.
3071+
VT = MVT::i16;
3072+
SubRegOp = X86::sub_16bit;
3073+
Op = X86::TEST16ri;
3074+
} else if (isUInt<32>(Mask) && N0.getValueType() != MVT::i16 &&
3075+
(!(Mask & 0x80000000) || hasNoSignedComparisonUses(Node))) {
3076+
// For example, "testq %rax, $268468232" to "testl %eax, $268468232".
3077+
// NOTE: We only want to run that transform if N0 is 32 or 64 bits.
3078+
// Otherwize, we find ourselves in a position where we have to do
3079+
// promotion. If previous passes did not promote the and, we assume
3080+
// they had a good reason not to and do not promote here.
3081+
VT = MVT::i32;
3082+
SubRegOp = X86::sub_32bit;
3083+
Op = X86::TEST32ri;
3084+
} else {
3085+
// No eligible transformation was found.
3086+
break;
30743087
}
30753088

3076-
// For example, "testl %eax, $32776" to "testw %ax, $32776".
3077-
// NOTE: We only want to form TESTW instructions if optimizing for
3078-
// min size. Otherwise we only save one byte and possibly get a length
3079-
// changing prefix penalty in the decoders.
3080-
if (OptForMinSize && isUInt<16>(Mask) && N0.getValueType() != MVT::i16 &&
3081-
(!(Mask & 0x8000) || hasNoSignedComparisonUses(Node))) {
3082-
SDValue Imm = CurDAG->getTargetConstant(Mask, dl, MVT::i16);
3083-
SDValue Reg = N0.getOperand(0);
3084-
3085-
// Extract the 16-bit subregister.
3086-
SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::sub_16bit, dl,
3087-
MVT::i16, Reg);
3088-
3089-
// Emit a testw.
3090-
SDNode *NewNode = CurDAG->getMachineNode(X86::TEST16ri, dl, MVT::i32,
3091-
Subreg, Imm);
3092-
// Replace SUB|CMP with TEST, since SUB has two outputs while TEST has
3093-
// one, do not call ReplaceAllUsesWith.
3094-
ReplaceUses(SDValue(Node, (Opcode == X86ISD::SUB ? 1 : 0)),
3095-
SDValue(NewNode, 0));
3096-
CurDAG->RemoveDeadNode(Node);
3097-
return;
3098-
}
3089+
SDValue Imm = CurDAG->getTargetConstant(Mask, dl, VT);
3090+
SDValue Reg = N0.getOperand(0);
30993091

3100-
// For example, "testq %rax, $268468232" to "testl %eax, $268468232".
3101-
if (isUInt<32>(Mask) && N0.getValueType() == MVT::i64 &&
3102-
(!(Mask & 0x80000000) || hasNoSignedComparisonUses(Node))) {
3103-
SDValue Imm = CurDAG->getTargetConstant(Mask, dl, MVT::i32);
3104-
SDValue Reg = N0.getOperand(0);
3105-
3106-
// Extract the 32-bit subregister.
3107-
SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::sub_32bit, dl,
3108-
MVT::i32, Reg);
3109-
// Emit a testl.
3110-
SDNode *NewNode = CurDAG->getMachineNode(X86::TEST32ri, dl, MVT::i32,
3111-
Subreg, Imm);
3112-
// Replace SUB|CMP with TEST, since SUB has two outputs while TEST has
3113-
// one, do not call ReplaceAllUsesWith.
3114-
ReplaceUses(SDValue(Node, (Opcode == X86ISD::SUB ? 1 : 0)),
3115-
SDValue(NewNode, 0));
3116-
CurDAG->RemoveDeadNode(Node);
3117-
return;
3118-
}
3092+
// Extract the subregister if necessary.
3093+
if (N0.getValueType() != VT)
3094+
Reg = CurDAG->getTargetExtractSubreg(SubRegOp, dl, VT, Reg);
3095+
3096+
// Emit a testl or testw.
3097+
SDNode *NewNode = CurDAG->getMachineNode(Op, dl, MVT::i32, Reg, Imm);
3098+
// Replace SUB|CMP with TEST, since SUB has two outputs while TEST has
3099+
// one, do not call ReplaceAllUsesWith.
3100+
ReplaceUses(SDValue(Node, (Opcode == X86ISD::SUB ? 1 : 0)),
3101+
SDValue(NewNode, 0));
3102+
CurDAG->RemoveDeadNode(Node);
3103+
return;
31193104
}
31203105
break;
31213106
}

‎llvm/test/CodeGen/X86/test-shrink-bug.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ define void @fail(i16 %a, <2 x i8> %b) {
5151
; CHECK-X86-NEXT: movzwl {{[0-9]+}}(%esp), %ecx
5252
; CHECK-X86-NEXT: cmpb $123, {{[0-9]+}}(%esp)
5353
; CHECK-X86-NEXT: sete %al
54-
; CHECK-X86-NEXT: andl $263, %ecx ## imm = 0x107
55-
; CHECK-X86-NEXT: testw %cx, %cx
54+
; CHECK-X86-NEXT: testl $263, %ecx ## imm = 0x107
5655
; CHECK-X86-NEXT: je LBB1_2
5756
; CHECK-X86-NEXT: ## %bb.1:
5857
; CHECK-X86-NEXT: testb %al, %al

‎llvm/test/CodeGen/X86/test-shrink.ll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,7 @@ no:
484484
define void @truncand32(i16 inreg %x) nounwind {
485485
; CHECK-LINUX64-LABEL: truncand32:
486486
; CHECK-LINUX64: # %bb.0:
487-
; CHECK-LINUX64-NEXT: andl $2049, %edi # imm = 0x801
488-
; CHECK-LINUX64-NEXT: testw %di, %di
487+
; CHECK-LINUX64-NEXT: testl $2049, %edi # imm = 0x801
489488
; CHECK-LINUX64-NEXT: je .LBB11_1
490489
; CHECK-LINUX64-NEXT: # %bb.2: # %no
491490
; CHECK-LINUX64-NEXT: retq
@@ -498,8 +497,7 @@ define void @truncand32(i16 inreg %x) nounwind {
498497
; CHECK-WIN32-64-LABEL: truncand32:
499498
; CHECK-WIN32-64: # %bb.0:
500499
; CHECK-WIN32-64-NEXT: subq $40, %rsp
501-
; CHECK-WIN32-64-NEXT: andl $2049, %ecx # imm = 0x801
502-
; CHECK-WIN32-64-NEXT: testw %cx, %cx
500+
; CHECK-WIN32-64-NEXT: testl $2049, %ecx # imm = 0x801
503501
; CHECK-WIN32-64-NEXT: je .LBB11_1
504502
; CHECK-WIN32-64-NEXT: # %bb.2: # %no
505503
; CHECK-WIN32-64-NEXT: addq $40, %rsp
@@ -511,8 +509,7 @@ define void @truncand32(i16 inreg %x) nounwind {
511509
;
512510
; CHECK-X86-LABEL: truncand32:
513511
; CHECK-X86: # %bb.0:
514-
; CHECK-X86-NEXT: andl $2049, %eax # imm = 0x801
515-
; CHECK-X86-NEXT: testw %ax, %ax
512+
; CHECK-X86-NEXT: testl $2049, %eax # imm = 0x801
516513
; CHECK-X86-NEXT: je .LBB11_1
517514
; CHECK-X86-NEXT: # %bb.2: # %no
518515
; CHECK-X86-NEXT: retl

0 commit comments

Comments
 (0)
Please sign in to comment.