[DAGCombiner] Fix SDLoc in a (zext (zextload x)) combine (4/N)

The logic for this combine is almost identical to the logic for a
(sext (sextload x)) combine.

This commit factors out the logic so it can be shared by both combines,
and corrects the SDLoc assigned in the zext version of the combine.

Prior to this patch, for the given test case, we would apply the
location associated with the udiv instruction to instructions which
perform the load.

Part of: llvm.org/PR37262

llvm-svn: 331303
This commit is contained in:
Vedant Kumar 2018-05-01 19:51:15 +00:00
parent d7117ed0f9
commit e23173b677
3 changed files with 81 additions and 41 deletions

View File

@ -7706,6 +7706,33 @@ SDValue DAGCombiner::matchVSelectOpSizesWithSetCC(SDNode *Cast) {
return DAG.getNode(ISD::VSELECT, DL, VT, SetCC, CastA, CastB); return DAG.getNode(ISD::VSELECT, DL, VT, SetCC, CastA, CastB);
} }
// fold ([s|z]ext ([s|z]extload x)) -> ([s|z]ext (truncate ([s|z]extload x)))
// fold ([s|z]ext ( extload x)) -> ([s|z]ext (truncate ([s|z]extload x)))
static SDValue tryToFoldExtOfExtload(SelectionDAG &DAG, DAGCombiner &Combiner,
const TargetLowering &TLI, EVT VT,
bool LegalOperations, SDNode *N,
SDValue N0, ISD::LoadExtType ExtLoadType) {
SDNode *N0Node = N0.getNode();
bool isAExtLoad = (ExtLoadType == ISD::SEXTLOAD) ? ISD::isSEXTLoad(N0Node)
: ISD::isZEXTLoad(N0Node);
if ((!isAExtLoad && !ISD::isEXTLoad(N0Node)) ||
!ISD::isUNINDEXEDLoad(N0Node) || !N0.hasOneUse())
return {};
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
EVT MemVT = LN0->getMemoryVT();
if ((LegalOperations || LN0->isVolatile()) &&
!TLI.isLoadExtLegal(ExtLoadType, VT, MemVT))
return {};
SDValue ExtLoad =
DAG.getExtLoad(ExtLoadType, SDLoc(LN0), VT, LN0->getChain(),
LN0->getBasePtr(), MemVT, LN0->getMemOperand());
Combiner.CombineTo(N, ExtLoad);
DAG.ReplaceAllUsesOfValueWith(SDValue(LN0, 1), ExtLoad.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
SDValue N0 = N->getOperand(0); SDValue N0 = N->getOperand(0);
EVT VT = N->getValueType(0); EVT VT = N->getValueType(0);
@ -7809,22 +7836,10 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
if (SDValue ExtLoad = CombineExtLoad(N)) if (SDValue ExtLoad = CombineExtLoad(N))
return ExtLoad; return ExtLoad;
// fold (sext (sextload x)) -> (sext (truncate (sextload x))) // Try to simplify (sext (sextload x)).
// fold (sext ( extload x)) -> (sext (truncate (sextload x))) if (SDValue foldedExt = tryToFoldExtOfExtload(
if ((ISD::isSEXTLoad(N0.getNode()) || ISD::isEXTLoad(N0.getNode())) && DAG, *this, TLI, VT, LegalOperations, N, N0, ISD::SEXTLOAD))
ISD::isUNINDEXEDLoad(N0.getNode()) && N0.hasOneUse()) { return foldedExt;
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
EVT MemVT = LN0->getMemoryVT();
if ((!LegalOperations && !LN0->isVolatile()) ||
TLI.isLoadExtLegal(ISD::SEXTLOAD, VT, MemVT)) {
SDValue ExtLoad =
DAG.getExtLoad(ISD::SEXTLOAD, SDLoc(LN0), VT, LN0->getChain(),
LN0->getBasePtr(), MemVT, LN0->getMemOperand());
CombineTo(N, ExtLoad);
DAG.ReplaceAllUsesOfValueWith(SDValue(LN0, 1), ExtLoad.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
}
// fold (sext (and/or/xor (load x), cst)) -> // fold (sext (and/or/xor (load x), cst)) ->
// (and/or/xor (sextload x), (sext cst)) // (and/or/xor (sextload x), (sext cst))
@ -8184,23 +8199,10 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
if (SDValue ZExtLoad = CombineZExtLogicopShiftLoad(N)) if (SDValue ZExtLoad = CombineZExtLogicopShiftLoad(N))
return ZExtLoad; return ZExtLoad;
// fold (zext (zextload x)) -> (zext (truncate (zextload x))) // Try to simplify (zext (zextload x)).
// fold (zext ( extload x)) -> (zext (truncate (zextload x))) if (SDValue foldedExt = tryToFoldExtOfExtload(
if ((ISD::isZEXTLoad(N0.getNode()) || ISD::isEXTLoad(N0.getNode())) && DAG, *this, TLI, VT, LegalOperations, N, N0, ISD::ZEXTLOAD))
ISD::isUNINDEXEDLoad(N0.getNode()) && N0.hasOneUse()) { return foldedExt;
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
EVT MemVT = LN0->getMemoryVT();
if ((!LegalOperations && !LN0->isVolatile()) ||
TLI.isLoadExtLegal(ISD::ZEXTLOAD, VT, MemVT)) {
SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, SDLoc(N), VT,
LN0->getChain(),
LN0->getBasePtr(), MemVT,
LN0->getMemOperand());
CombineTo(N, ExtLoad);
DAG.ReplaceAllUsesOfValueWith(SDValue(LN0, 1), ExtLoad.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
}
if (N0.getOpcode() == ISD::SETCC) { if (N0.getOpcode() == ISD::SETCC) {
// Only do this before legalize for now. // Only do this before legalize for now.

View File

@ -0,0 +1,38 @@
; RUN: llc -mtriple armv7 %s -stop-before=livedebugvalues -o - | FileCheck %s
define <4 x i8> @i(<4 x i8>*) !dbg !8 {
%2 = load <4 x i8>, <4 x i8>* %0, align 4, !dbg !14
; CHECK: $[[reg:.*]] = VLD1LNd32 {{.*}} debug-location !14 :: (load 4 from %ir.0)
; CHECK-NEXT: VMOVLuv8i16 {{.*}} $[[reg]], {{.*}} debug-location !14
; CHECK-NEXT: VMOVLuv4i32 {{.*}} $[[reg]], {{.*}} debug-location !14
%3 = udiv <4 x i8> zeroinitializer, %2, !dbg !15
call void @llvm.dbg.value(metadata <4 x i8> %2, metadata !11, metadata !DIExpression()), !dbg !14
call void @llvm.dbg.value(metadata <4 x i8> %3, metadata !13, metadata !DIExpression()), !dbg !15
ret <4 x i8> %3, !dbg !16
}
declare void @llvm.dbg.value(metadata, metadata, metadata)
!llvm.debugify = !{!0, !1, !2, !3}
!llvm.module.flags = !{!4}
!llvm.dbg.cu = !{!5}
!0 = !{i32 24}
!1 = !{i32 19}
!2 = !{i32 3}
!3 = !{i32 2}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = distinct !DICompileUnit(language: DW_LANG_C, file: !6, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !7)
!6 = !DIFile(filename: "/Users/vsk/Desktop/test.ll", directory: "/")
!7 = !{}
!8 = distinct !DISubprogram(name: "i", linkageName: "i", scope: null, file: !6, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !5, variables: !10)
!9 = !DISubroutineType(types: !7)
!10 = !{!11, !13}
!11 = !DILocalVariable(name: "1", scope: !8, file: !6, line: 1, type: !12)
!12 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
!13 = !DILocalVariable(name: "2", scope: !8, file: !6, line: 2, type: !12)
!14 = !DILocation(line: 1, column: 1, scope: !8)
!15 = !DILocation(line: 2, column: 1, scope: !8)
!16 = !DILocation(line: 3, column: 1, scope: !8)
!17 = !{i32 2, !"Debug Info Version", i32 3}

View File

@ -26,14 +26,14 @@ define i64 @foo(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g, i64 %h)
; CHECK-NEXT: movq %r8, %rax ; CHECK-NEXT: movq %r8, %rax
; CHECK-NEXT: movzbl %ah, %ecx ; CHECK-NEXT: movzbl %ah, %ecx
; CHECK-NEXT: movq %r9, %rax ; CHECK-NEXT: movq %r9, %rax
; CHECK-NEXT: movzbl %ah, %ebx ; CHECK-NEXT: movzbl %ah, %edi
; CHECK-NEXT: movzbl {{[0-9]+}}(%rsp), %eax ; CHECK-NEXT: movzbl {{[0-9]+}}(%rsp), %eax
; CHECK-NEXT: movzbl {{[0-9]+}}(%rsp), %edi ; CHECK-NEXT: movzbl {{[0-9]+}}(%rsp), %ebx
; CHECK-NEXT: addq %r10, %rsi ; CHECK-NEXT: addq %r10, %rsi
; CHECK-NEXT: addq %rbp, %rdx ; CHECK-NEXT: addq %rbp, %rdx
; CHECK-NEXT: addq %rsi, %rdx ; CHECK-NEXT: addq %rsi, %rdx
; CHECK-NEXT: addq %rbx, %rcx ; CHECK-NEXT: addq %rdi, %rcx
; CHECK-NEXT: addq %rdi, %rax ; CHECK-NEXT: addq %rbx, %rax
; CHECK-NEXT: addq %rcx, %rax ; CHECK-NEXT: addq %rcx, %rax
; CHECK-NEXT: addq %rdx, %rax ; CHECK-NEXT: addq %rdx, %rax
; CHECK-NEXT: popq %rbx ; CHECK-NEXT: popq %rbx
@ -60,14 +60,14 @@ define i64 @foo(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g, i64 %h)
; GNUX32-NEXT: movq %r8, %rax ; GNUX32-NEXT: movq %r8, %rax
; GNUX32-NEXT: movzbl %ah, %ecx ; GNUX32-NEXT: movzbl %ah, %ecx
; GNUX32-NEXT: movq %r9, %rax ; GNUX32-NEXT: movq %r9, %rax
; GNUX32-NEXT: movzbl %ah, %ebx ; GNUX32-NEXT: movzbl %ah, %edi
; GNUX32-NEXT: movzbl {{[0-9]+}}(%esp), %eax ; GNUX32-NEXT: movzbl {{[0-9]+}}(%esp), %eax
; GNUX32-NEXT: movzbl {{[0-9]+}}(%esp), %edi ; GNUX32-NEXT: movzbl {{[0-9]+}}(%esp), %ebx
; GNUX32-NEXT: addq %r10, %rsi ; GNUX32-NEXT: addq %r10, %rsi
; GNUX32-NEXT: addq %rbp, %rdx ; GNUX32-NEXT: addq %rbp, %rdx
; GNUX32-NEXT: addq %rsi, %rdx ; GNUX32-NEXT: addq %rsi, %rdx
; GNUX32-NEXT: addq %rbx, %rcx ; GNUX32-NEXT: addq %rdi, %rcx
; GNUX32-NEXT: addq %rdi, %rax ; GNUX32-NEXT: addq %rbx, %rax
; GNUX32-NEXT: addq %rcx, %rax ; GNUX32-NEXT: addq %rcx, %rax
; GNUX32-NEXT: addq %rdx, %rax ; GNUX32-NEXT: addq %rdx, %rax
; GNUX32-NEXT: popq %rbx ; GNUX32-NEXT: popq %rbx