[llvm] 656d66f - [X86] Use custom isel for (X86sbb_flag 0, 0) so we can use 32-bit SBB for i8/i16.
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 9 13:33:41 PST 2020
Author: Craig Topper
Date: 2020-02-09T13:19:35-08:00
New Revision: 656d66f5fc51ce6003b1ef114d6806168fb1f159
URL: https://github.com/llvm/llvm-project/commit/656d66f5fc51ce6003b1ef114d6806168fb1f159
DIFF: https://github.com/llvm/llvm-project/commit/656d66f5fc51ce6003b1ef114d6806168fb1f159.diff
LOG: [X86] Use custom isel for (X86sbb_flag 0, 0) so we can use 32-bit SBB for i8/i16.
We were using MOV32r0 and an extract_subreg as an input. By using
custom isel we can move the extract_subreg to after the SBB instead
of on the input.
Added:
Modified:
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
llvm/lib/Target/X86/X86InstrCompiler.td
llvm/test/CodeGen/X86/shl-crash-on-legalize.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 9789ffcd0dd5..e0228284795f 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -5343,12 +5343,11 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
// We have to do this manually because tblgen will put the eflags copy in
// the wrong place if we use an extract_subreg in the pattern.
MVT VT = Node->getSimpleValueType(0);
- SDValue Chain = CurDAG->getEntryNode();
// Copy flags to the EFLAGS register and glue it to next node.
- SDValue EFLAGS = CurDAG->getCopyToReg(Chain, dl, X86::EFLAGS,
- Node->getOperand(1), SDValue());
- Chain = EFLAGS;
+ SDValue EFLAGS =
+ CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
+ Node->getOperand(1), SDValue());
// Create a 64-bit instruction if the result is 64-bits otherwise use the
// 32-bit version.
@@ -5367,6 +5366,56 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
CurDAG->RemoveDeadNode(Node);
return;
}
+ case X86ISD::SBB: {
+ if (isNullConstant(Node->getOperand(0)) &&
+ isNullConstant(Node->getOperand(1))) {
+ MVT VT = Node->getSimpleValueType(0);
+
+ // Create zero.
+ SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
+ SDValue Zero =
+ SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, None), 0);
+ if (VT == MVT::i64) {
+ Zero = SDValue(
+ CurDAG->getMachineNode(
+ TargetOpcode::SUBREG_TO_REG, dl, MVT::i64,
+ CurDAG->getTargetConstant(0, dl, MVT::i64), Zero,
+ CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
+ 0);
+ }
+
+ // Copy flags to the EFLAGS register and glue it to next node.
+ SDValue EFLAGS =
+ CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
+ Node->getOperand(2), SDValue());
+
+ // Create a 64-bit instruction if the result is 64-bits otherwise use the
+ // 32-bit version.
+ unsigned Opc = VT == MVT::i64 ? X86::SBB64rr : X86::SBB32rr;
+ MVT SBBVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
+ VTs = CurDAG->getVTList(SBBVT, MVT::i32);
+ SDValue Result =
+ SDValue(CurDAG->getMachineNode(Opc, dl, VTs, {Zero, Zero, EFLAGS,
+ EFLAGS.getValue(1)}),
+ 0);
+
+ // Replace the flag use.
+ ReplaceUses(SDValue(Node, 1), Result.getValue(1));
+
+ // Replace the result use.
+ if (!SDValue(Node, 0).use_empty()) {
+ // For less than 32-bits we need to extract from the 32-bit node.
+ if (VT == MVT::i8 || VT == MVT::i16) {
+ int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
+ Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
+ }
+ ReplaceUses(SDValue(Node, 0), Result);
+ }
+
+ CurDAG->RemoveDeadNode(Node);
+ return;
+ }
+ }
}
SelectCode(Node);
diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td
index 96ebb44fecb5..e8f2f584cde0 100644
--- a/llvm/lib/Target/X86/X86InstrCompiler.td
+++ b/llvm/lib/Target/X86/X86InstrCompiler.td
@@ -334,22 +334,6 @@ def SETB_C32r : I<0, Pseudo, (outs GR32:$dst), (ins), "", []>;
def SETB_C64r : I<0, Pseudo, (outs GR64:$dst), (ins), "", []>;
} // isCodeGenOnly
-
-// Patterns to give priority when both inputs are zero so that we don't use
-// an immediate for the RHS.
-// TODO: Should we use a 32-bit sbb for 8/16 to push the extract_subreg out?
-def : Pat<(X86sbb_flag (i8 0), (i8 0), EFLAGS),
- (SBB8rr (EXTRACT_SUBREG (MOV32r0), sub_8bit),
- (EXTRACT_SUBREG (MOV32r0), sub_8bit))>;
-def : Pat<(X86sbb_flag (i16 0), (i16 0), EFLAGS),
- (SBB16rr (EXTRACT_SUBREG (MOV32r0), sub_16bit),
- (EXTRACT_SUBREG (MOV32r0), sub_16bit))>;
-def : Pat<(X86sbb_flag (i32 0), (i32 0), EFLAGS),
- (SBB32rr (MOV32r0), (MOV32r0))>;
-def : Pat<(X86sbb_flag (i64 0), (i64 0), EFLAGS),
- (SBB64rr (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit),
- (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit))>;
-
//===----------------------------------------------------------------------===//
// String Pseudo Instructions
//
diff --git a/llvm/test/CodeGen/X86/shl-crash-on-legalize.ll b/llvm/test/CodeGen/X86/shl-crash-on-legalize.ll
index d9de001c5a86..4c3c999e1cba 100644
--- a/llvm/test/CodeGen/X86/shl-crash-on-legalize.ll
+++ b/llvm/test/CodeGen/X86/shl-crash-on-legalize.ll
@@ -17,7 +17,7 @@ define i32 @PR29058(i8 %x, i32 %y) {
; CHECK-NEXT: cmovnel %esi, %eax
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: cmpb $1, %dil
-; CHECK-NEXT: sbbb %dl, %dl
+; CHECK-NEXT: sbbl %edx, %edx
; CHECK-NEXT: orb %dl, %cl
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: shll %cl, %eax
More information about the llvm-commits
mailing list