mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-13 01:15:32 +00:00
In special cases select instructions can be eliminated by replacing them with a cheaper bitwise operation even when the select result is used outside its home block. The instances implemented are patterns like %x=icmp.eq %y=select %x,%r, null %z=icmp.eq|neq %y, null br %z,true, false ==> %x=icmp.ne %y=icmp.eq %r,null %z=or %x,%y br %z,true,false The optimization is integrated into the instruction combiner and performed only when all uses of the select result can be replaced by the select operand proper. For this dominator information is used and dominance is now a required analysis pass in the combiner. The optimization itself is iterative. The critical step is to replace the select result with the non-constant select operand. So the select becomes local and the combiner iteratively works out simpler code pattern and eventually eliminates the select. rdar://17853760 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218721 91177308-0d34-0410-b5e6-96231b3b80d8
128 lines
3.6 KiB
LLVM
128 lines
3.6 KiB
LLVM
; Replace a 'select' with 'or' in 'select - cmp [eq|ne] - br' sequence
|
|
; RUN: opt -instcombine -S < %s | FileCheck %s
|
|
|
|
%C = type <{ %struct.S }>
|
|
%struct.S = type { i64*, i32, i32 }
|
|
|
|
declare void @bar(%struct.S *) #1
|
|
|
|
define void @test1(%C*) {
|
|
entry:
|
|
%1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0
|
|
%m = load i64** %1, align 8
|
|
%2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0
|
|
%n = load i64** %2, align 8
|
|
%3 = getelementptr inbounds i64* %m, i64 9
|
|
%4 = bitcast i64* %3 to i64 (%C*)**
|
|
%5 = load i64 (%C*)** %4, align 8
|
|
%6 = icmp eq i64* %m, %n
|
|
%7 = select i1 %6, %C* %0, %C* null
|
|
%8 = icmp eq %C* %7, null
|
|
br i1 %8, label %12, label %10
|
|
|
|
; <label>:9 ; preds = %10, %12
|
|
ret void
|
|
|
|
; <label>:10 ; preds = %entry
|
|
%11 = getelementptr inbounds %C* %7, i64 0, i32 0
|
|
tail call void @bar(%struct.S* %11)
|
|
br label %9
|
|
|
|
; <label>:12 ; preds = %entry
|
|
%13 = tail call i64 %5(%C* %0)
|
|
br label %9
|
|
; CHECK-LABEL: @test1(
|
|
; CHECK-NOT: select
|
|
; CHECK: or
|
|
}
|
|
|
|
define void @test2(%C*) {
|
|
entry:
|
|
%1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0
|
|
%m = load i64** %1, align 8
|
|
%2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0
|
|
%n = load i64** %2, align 8
|
|
%3 = getelementptr inbounds i64* %m, i64 9
|
|
%4 = bitcast i64* %3 to i64 (%C*)**
|
|
%5 = load i64 (%C*)** %4, align 8
|
|
%6 = icmp eq i64* %m, %n
|
|
%7 = select i1 %6, %C* null, %C* %0
|
|
%8 = icmp eq %C* %7, null
|
|
br i1 %8, label %12, label %10
|
|
|
|
; <label>:9 ; preds = %10, %12
|
|
ret void
|
|
|
|
; <label>:10 ; preds = %entry
|
|
%11 = getelementptr inbounds %C* %7, i64 0, i32 0
|
|
tail call void @bar(%struct.S* %11)
|
|
br label %9
|
|
|
|
; <label>:12 ; preds = %entry
|
|
%13 = tail call i64 %5(%C* %0)
|
|
br label %9
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NOT: select
|
|
; CHECK: or
|
|
}
|
|
|
|
define void @test3(%C*) {
|
|
entry:
|
|
%1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0
|
|
%m = load i64** %1, align 8
|
|
%2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0
|
|
%n = load i64** %2, align 8
|
|
%3 = getelementptr inbounds i64* %m, i64 9
|
|
%4 = bitcast i64* %3 to i64 (%C*)**
|
|
%5 = load i64 (%C*)** %4, align 8
|
|
%6 = icmp eq i64* %m, %n
|
|
%7 = select i1 %6, %C* %0, %C* null
|
|
%8 = icmp ne %C* %7, null
|
|
br i1 %8, label %10, label %12
|
|
|
|
; <label>:9 ; preds = %10, %12
|
|
ret void
|
|
|
|
; <label>:10 ; preds = %entry
|
|
%11 = getelementptr inbounds %C* %7, i64 0, i32 0
|
|
tail call void @bar(%struct.S* %11)
|
|
br label %9
|
|
|
|
; <label>:12 ; preds = %entry
|
|
%13 = tail call i64 %5(%C* %0)
|
|
br label %9
|
|
; CHECK-LABEL: @test3(
|
|
; CHECK-NOT: select
|
|
; CHECK: or
|
|
}
|
|
|
|
define void @test4(%C*) {
|
|
entry:
|
|
%1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0
|
|
%m = load i64** %1, align 8
|
|
%2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0
|
|
%n = load i64** %2, align 8
|
|
%3 = getelementptr inbounds i64* %m, i64 9
|
|
%4 = bitcast i64* %3 to i64 (%C*)**
|
|
%5 = load i64 (%C*)** %4, align 8
|
|
%6 = icmp eq i64* %m, %n
|
|
%7 = select i1 %6, %C* null, %C* %0
|
|
%8 = icmp ne %C* %7, null
|
|
br i1 %8, label %10, label %12
|
|
|
|
; <label>:9 ; preds = %10, %12
|
|
ret void
|
|
|
|
; <label>:10 ; preds = %entry
|
|
%11 = getelementptr inbounds %C* %7, i64 0, i32 0
|
|
tail call void @bar(%struct.S* %11)
|
|
br label %9
|
|
|
|
; <label>:12 ; preds = %entry
|
|
%13 = tail call i64 %5(%C* %0)
|
|
br label %9
|
|
; CHECK-LABEL: @test4(
|
|
; CHECK-NOT: select
|
|
; CHECK: or
|
|
}
|