mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-23 21:13:02 +02:00
6d132686e0
Summary: Currently, when 't1: i1 = setcc t2, t3, cc' followed by 't4: i1 = xor t1, Constant:i1<-1>' is folded into 't5: i1 = setcc t2, t3 !cc', SDLoc of newly created SDValue 't5' follows SDLoc of 't4', not 't1'. However, as the opcode of newly created SDValue is 'setcc', it make more sense to take DebugLoc from 't1' than 't4'. For the code below ``` extern int bar(); extern int baz(); int foo(int x, int y) { if (x != y) return bar(); else return baz(); } ``` , following is the bitcode representation of 'foo' at the end of llvm-ir level optimization: ``` define i32 @foo(i32 %x, i32 %y) !dbg !4 { entry: tail call void @llvm.dbg.value(metadata i32 %x, i64 0, metadata !9, metadata !11), !dbg !12 tail call void @llvm.dbg.value(metadata i32 %y, i64 0, metadata !10, metadata !11), !dbg !13 %cmp = icmp ne i32 %x, %y, !dbg !14 br i1 %cmp, label %if.then, label %if.else, !dbg !16 if.then: ; preds = %entry %call = tail call i32 (...) @bar() #3, !dbg !17 br label %return, !dbg !18 if.else: ; preds = %entry %call1 = tail call i32 (...) @baz() #3, !dbg !19 br label %return, !dbg !20 return: ; preds = %if.else, %if.then %retval.0 = phi i32 [ %call, %if.then ], [ %call1, %if.else ] ret i32 %retval.0, !dbg !21 } !14 = !DILocation(line: 5, column: 9, scope: !15) !16 = !DILocation(line: 5, column: 7, scope: !4) ``` As you can see, in 'entry' block, 'icmp' instruction and 'br' instruction have different debug locations. However, with current implementation, there's no distinction between debug locations of these two when they are lowered to asm instructions. This is because 'icmp' and 'br' become 'setcc' 'xor' and 'brcond' in SelectionDAG, where SDLoc of 'setcc' follows the debug location of 'icmp' but SDLOC of 'xor' and 'brcond' follows the debug location of 'br' instruction, and SDLoc of 'xor' overwrites SDLoc of 'setcc' when they are folded. This patch addresses this issue. Reviewers: atrick, bogner, andreadb, craig.topper, aprantl Reviewed By: andreadb Subscribers: jlebar, mkuper, jholewinski, andreadb, llvm-commits Differential Revision: https://reviews.llvm.org/D29813 llvm-svn: 296825
182 lines
4.0 KiB
LLVM
182 lines
4.0 KiB
LLVM
; RUN: llc -mtriple=i686-unknown -verify-machineinstrs < %s | FileCheck %s
|
|
; RUN: opt < %s -codegenprepare -S -mtriple=x86_64-unknown-unknown | FileCheck --check-prefix=CHECK-CGP %s
|
|
|
|
@A = global i32 zeroinitializer
|
|
@B = global i32 zeroinitializer
|
|
@C = global i32 zeroinitializer
|
|
|
|
; Test that 'and' is sunk into bb0.
|
|
define i32 @and_sink1(i32 %a, i1 %c) {
|
|
; CHECK-LABEL: and_sink1:
|
|
; CHECK: testb $1,
|
|
; CHECK: je
|
|
; CHECK-NOT: andl $4,
|
|
; CHECK: movl $0, A
|
|
; CHECK: testb $4,
|
|
; CHECK: jne
|
|
|
|
; CHECK-CGP-LABEL: @and_sink1(
|
|
; CHECK-CGP-NOT: and i32
|
|
%and = and i32 %a, 4
|
|
br i1 %c, label %bb0, label %bb2
|
|
bb0:
|
|
; CHECK-CGP-LABEL: bb0:
|
|
; CHECK-CGP: and i32
|
|
; CHECK-CGP-NEXT: icmp eq i32
|
|
; CHECK-CGP-NEXT: store
|
|
; CHECK-CGP-NEXT: br
|
|
%cmp = icmp eq i32 %and, 0
|
|
store i32 0, i32* @A
|
|
br i1 %cmp, label %bb1, label %bb2
|
|
bb1:
|
|
ret i32 1
|
|
bb2:
|
|
ret i32 0
|
|
}
|
|
|
|
; Test that both 'and' and cmp get sunk to bb1.
|
|
define i32 @and_sink2(i32 %a, i1 %c, i1 %c2) {
|
|
; CHECK-LABEL: and_sink2:
|
|
; CHECK: movl $0, A
|
|
; CHECK: testb $1,
|
|
; CHECK: je
|
|
; CHECK-NOT: andl $4,
|
|
; CHECK: movl $0, B
|
|
; CHECK: testb $1,
|
|
; CHECK: je
|
|
; CHECK: movl $0, C
|
|
; CHECK: testb $4,
|
|
; CHECK: jne
|
|
|
|
; CHECK-CGP-LABEL: @and_sink2(
|
|
; CHECK-CGP-NOT: and i32
|
|
%and = and i32 %a, 4
|
|
store i32 0, i32* @A
|
|
br i1 %c, label %bb0, label %bb3
|
|
bb0:
|
|
; CHECK-CGP-LABEL: bb0:
|
|
; CHECK-CGP-NOT: and i32
|
|
; CHECK-CGP-NOT: icmp
|
|
%cmp = icmp eq i32 %and, 0
|
|
store i32 0, i32* @B
|
|
br i1 %c2, label %bb1, label %bb3
|
|
bb1:
|
|
; CHECK-CGP-LABEL: bb1:
|
|
; CHECK-CGP: and i32
|
|
; CHECK-CGP-NEXT: icmp eq i32
|
|
; CHECK-CGP-NEXT: store
|
|
; CHECK-CGP-NEXT: br
|
|
store i32 0, i32* @C
|
|
br i1 %cmp, label %bb2, label %bb0
|
|
bb2:
|
|
ret i32 1
|
|
bb3:
|
|
ret i32 0
|
|
}
|
|
|
|
; Test that CodeGenPrepare doesn't get stuck in a loop sinking and hoisting a masked load.
|
|
define i32 @and_sink3(i1 %c, i32* %p) {
|
|
; CHECK-LABEL: and_sink3:
|
|
; CHECK: testb $1,
|
|
; CHECK: je
|
|
; CHECK: movzbl
|
|
; CHECK-DAG: movl $0, A
|
|
; CHECK-DAG: testl %
|
|
; CHECK: je
|
|
|
|
; CHECK-CGP-LABEL: @and_sink3(
|
|
; CHECK-CGP: load i32
|
|
; CHECK-CGP-NEXT: and i32
|
|
%load = load i32, i32* %p
|
|
%and = and i32 %load, 255
|
|
br i1 %c, label %bb0, label %bb2
|
|
bb0:
|
|
; CHECK-CGP-LABEL: bb0:
|
|
; CHECK-CGP-NOT: and i32
|
|
; CHECK-CGP: icmp eq i32
|
|
%cmp = icmp eq i32 %and, 0
|
|
store i32 0, i32* @A
|
|
br i1 %cmp, label %bb1, label %bb2
|
|
bb1:
|
|
ret i32 1
|
|
bb2:
|
|
ret i32 0
|
|
}
|
|
|
|
; Test that CodeGenPrepare sinks/duplicates non-immediate 'and'.
|
|
define i32 @and_sink4(i32 %a, i32 %b, i1 %c) {
|
|
; CHECK-LABEL: and_sink4:
|
|
; CHECK: testb $1,
|
|
; CHECK: je
|
|
; CHECK-NOT: andl
|
|
; CHECK-DAG: movl $0, A
|
|
; CHECK-DAG: testl [[REG1:%[a-z0-9]+]], [[REG2:%[a-z0-9]+]]
|
|
; CHECK: jne
|
|
; CHECK-DAG: movl {{%[a-z0-9]+}}, B
|
|
; CHECK-DAG: testl [[REG1]], [[REG2]]
|
|
; CHECK: je
|
|
|
|
; CHECK-CGP-LABEL: @and_sink4(
|
|
; CHECK-CGP-NOT: and i32
|
|
; CHECK-CGP-NOT: icmp
|
|
%and = and i32 %a, %b
|
|
%cmp = icmp eq i32 %and, 0
|
|
br i1 %c, label %bb0, label %bb3
|
|
bb0:
|
|
; CHECK-CGP-LABEL: bb0:
|
|
; CHECK-CGP: and i32
|
|
; CHECK-CGP-NEXT: icmp eq i32
|
|
store i32 0, i32* @A
|
|
br i1 %cmp, label %bb1, label %bb3
|
|
bb1:
|
|
; CHECK-CGP-LABEL: bb1:
|
|
; CHECK-CGP: and i32
|
|
; CHECK-CGP-NEXT: icmp eq i32
|
|
%add = add i32 %a, %b
|
|
store i32 %add, i32* @B
|
|
br i1 %cmp, label %bb2, label %bb3
|
|
bb2:
|
|
ret i32 1
|
|
bb3:
|
|
ret i32 0
|
|
}
|
|
|
|
|
|
; Test that CodeGenPrepare doesn't sink/duplicate non-immediate 'and'
|
|
; when it would increase register pressure.
|
|
define i32 @and_sink5(i32 %a, i32 %b, i32 %a2, i32 %b2, i1 %c) {
|
|
; CHECK-LABEL: and_sink5:
|
|
; CHECK: testb $1,
|
|
; CHECK: je
|
|
; CHECK-DAG: andl {{[0-9]+\(%[a-z0-9]+\)}}, [[REG:%[a-z0-9]+]]
|
|
; CHECK-DAG: movl $0, A
|
|
; CHECK: jne
|
|
; CHECK-DAG: movl {{%[a-z0-9]+}}, B
|
|
; CHECK-DAG: testl [[REG]], [[REG]]
|
|
; CHECK: je
|
|
|
|
; CHECK-CGP-LABEL: @and_sink5(
|
|
; CHECK-CGP: and i32
|
|
; CHECK-CGP-NOT: icmp
|
|
%and = and i32 %a, %b
|
|
%cmp = icmp eq i32 %and, 0
|
|
br i1 %c, label %bb0, label %bb3
|
|
bb0:
|
|
; CHECK-CGP-LABEL: bb0:
|
|
; CHECK-CGP-NOT: and i32
|
|
; CHECK-CGP: icmp eq i32
|
|
store i32 0, i32* @A
|
|
br i1 %cmp, label %bb1, label %bb3
|
|
bb1:
|
|
; CHECK-CGP-LABEL: bb1:
|
|
; CHECK-CGP-NOT: and i32
|
|
; CHECK-CGP: icmp eq i32
|
|
%add = add i32 %a2, %b2
|
|
store i32 %add, i32* @B
|
|
br i1 %cmp, label %bb2, label %bb3
|
|
bb2:
|
|
ret i32 1
|
|
bb3:
|
|
ret i32 0
|
|
}
|