Files
clang-p2996/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll
Roman Lebedev d1a6f92fd5 [InstCombine] Fold (~x) | y --> ~(x & (~y)) iff it is free to do so
Iff we know we can get rid of the inversions in the new pattern,
we can thus get rid of the inversion in the old pattern,
this decreasing instruction count.

Note that we could position this transformation as just hoisting
of the `not` (still, iff y is freely negatible), but the test changes
show a number of regressions, so let's not do that.
2021-01-22 17:23:54 +03:00

412 lines
12 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -instcombine < %s -simplifycfg-merge-cond-stores=true -simplifycfg-merge-cond-stores-aggressively=false -phi-node-folding-threshold=2 -S | FileCheck %s
; This test should succeed and end up if-converted.
define void @test_simple(i32* %p, i32 %a, i32 %b) {
; CHECK-LABEL: @test_simple(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP3:%.*]], label [[TMP2:%.*]]
; CHECK: 2:
; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
; CHECK-NEXT: store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[TMP3]]
; CHECK: 3:
; CHECK-NEXT: ret void
;
entry:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %fallthrough, label %yes1
yes1:
store i32 0, i32* %p
br label %fallthrough
fallthrough:
%x2 = icmp eq i32 %b, 0
br i1 %x2, label %end, label %yes2
yes2:
store i32 1, i32* %p
br label %end
end:
ret void
}
; This is the same as test_simple, but the branch target order has been swapped
define void @test_simple_commuted(i32* %p, i32 %a, i32 %b) {
; CHECK-LABEL: @test_simple_commuted(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X1_NOT:%.*]] = icmp eq i32 [[A:%.*]], 0
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[X1_NOT]], [[X2]]
; CHECK-NEXT: br i1 [[TMP0]], label [[TMP1:%.*]], label [[TMP2:%.*]]
; CHECK: 1:
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
; CHECK-NEXT: store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[TMP2]]
; CHECK: 2:
; CHECK-NEXT: ret void
;
entry:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %yes1, label %fallthrough
yes1:
store i32 0, i32* %p
br label %fallthrough
fallthrough:
%x2 = icmp eq i32 %b, 0
br i1 %x2, label %yes2, label %end
yes2:
store i32 1, i32* %p
br label %end
end:
ret void
}
; This test should entirely fold away, leaving one large basic block.
define void @test_recursive(i32* %p, i32 %a, i32 %b, i32 %c, i32 %d) {
; CHECK-LABEL: @test_recursive(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP0]], [[C:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[D:%.*]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
; CHECK-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
; CHECK: 4:
; CHECK-NEXT: [[X4:%.*]] = icmp eq i32 [[D]], 0
; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C]], 0
; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
; CHECK-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[X3]], i32 [[SPEC_SELECT]], i32 2
; CHECK-NEXT: [[SPEC_SELECT2:%.*]] = select i1 [[X4]], i32 [[SPEC_SELECT1]], i32 3
; CHECK-NEXT: store i32 [[SPEC_SELECT2]], i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[TMP5]]
; CHECK: 5:
; CHECK-NEXT: ret void
;
entry:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %fallthrough, label %yes1
yes1:
store i32 0, i32* %p
br label %fallthrough
fallthrough:
%x2 = icmp eq i32 %b, 0
br i1 %x2, label %next, label %yes2
yes2:
store i32 1, i32* %p
br label %next
next:
%x3 = icmp eq i32 %c, 0
br i1 %x3, label %fallthrough2, label %yes3
yes3:
store i32 2, i32* %p
br label %fallthrough2
fallthrough2:
%x4 = icmp eq i32 %d, 0
br i1 %x4, label %end, label %yes4
yes4:
store i32 3, i32* %p
br label %end
end:
ret void
}
; The code in each diamond is too large - it won't be if-converted so our
; heuristics should say no.
define void @test_not_ifconverted(i32* %p, i32 %a, i32 %b) {
; CHECK-LABEL: @test_not_ifconverted(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
; CHECK: yes1:
; CHECK-NEXT: [[Y1:%.*]] = or i32 [[B:%.*]], 55
; CHECK-NEXT: [[Y2:%.*]] = add i32 [[Y1]], 24
; CHECK-NEXT: [[Y3:%.*]] = and i32 [[Y2]], 67
; CHECK-NEXT: store i32 [[Y3]], i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[FALLTHROUGH]]
; CHECK: fallthrough:
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B]], 0
; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
; CHECK: yes2:
; CHECK-NEXT: [[Z1:%.*]] = or i32 [[A]], 55
; CHECK-NEXT: [[Z2:%.*]] = add i32 [[Z1]], 24
; CHECK-NEXT: [[Z3:%.*]] = and i32 [[Z2]], 67
; CHECK-NEXT: store i32 [[Z3]], i32* [[P]], align 4
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %fallthrough, label %yes1
yes1:
%y1 = or i32 %b, 55
%y2 = add i32 %y1, 24
%y3 = and i32 %y2, 67
store i32 %y3, i32* %p
br label %fallthrough
fallthrough:
%x2 = icmp eq i32 %b, 0
br i1 %x2, label %end, label %yes2
yes2:
%z1 = or i32 %a, 55
%z2 = add i32 %z1, 24
%z3 = and i32 %z2, 67
store i32 %z3, i32* %p
br label %end
end:
ret void
}
; The store to %p clobbers the previous store, so if-converting this would
; be illegal.
define void @test_aliasing1(i32* %p, i32 %a, i32 %b) {
; CHECK-LABEL: @test_aliasing1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
; CHECK: yes1:
; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[FALLTHROUGH]]
; CHECK: fallthrough:
; CHECK-NEXT: [[Y1:%.*]] = load i32, i32* [[P]], align 4
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[Y1]], 0
; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
; CHECK: yes2:
; CHECK-NEXT: store i32 1, i32* [[P]], align 4
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %fallthrough, label %yes1
yes1:
store i32 0, i32* %p
br label %fallthrough
fallthrough:
%y1 = load i32, i32* %p
%x2 = icmp eq i32 %y1, 0
br i1 %x2, label %end, label %yes2
yes2:
store i32 1, i32* %p
br label %end
end:
ret void
}
; The load from %q aliases with %p, so if-converting this would be illegal.
define void @test_aliasing2(i32* %p, i32* %q, i32 %a, i32 %b) {
; CHECK-LABEL: @test_aliasing2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
; CHECK: yes1:
; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[FALLTHROUGH]]
; CHECK: fallthrough:
; CHECK-NEXT: [[Y1:%.*]] = load i32, i32* [[Q:%.*]], align 4
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[Y1]], 0
; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
; CHECK: yes2:
; CHECK-NEXT: store i32 1, i32* [[P]], align 4
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %fallthrough, label %yes1
yes1:
store i32 0, i32* %p
br label %fallthrough
fallthrough:
%y1 = load i32, i32* %q
%x2 = icmp eq i32 %y1, 0
br i1 %x2, label %end, label %yes2
yes2:
store i32 1, i32* %p
br label %end
end:
ret void
}
declare void @f()
; This should get if-converted.
define i32 @test_diamond_simple(i32* %p, i32* %q, i32 %a, i32 %b) {
; CHECK-LABEL: @test_diamond_simple(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
; CHECK-NEXT: [[Z2:%.*]] = select i1 [[X1]], i32 [[B:%.*]], i32 0
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B]], 0
; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A]], [[B]]
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP0]], 0
; CHECK-NEXT: br i1 [[DOTNOT]], label [[TMP2:%.*]], label [[TMP1:%.*]]
; CHECK: 1:
; CHECK-NEXT: [[SIMPLIFYCFG_MERGE:%.*]] = select i1 [[X2]], i32 [[Z2]], i32 1
; CHECK-NEXT: store i32 [[SIMPLIFYCFG_MERGE]], i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[TMP2]]
; CHECK: 2:
; CHECK-NEXT: [[Z4:%.*]] = select i1 [[X2]], i32 [[Z2]], i32 3
; CHECK-NEXT: ret i32 [[Z4]]
;
entry:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %no1, label %yes1
yes1:
store i32 0, i32* %p
br label %fallthrough
no1:
%z1 = add i32 %a, %b
br label %fallthrough
fallthrough:
%z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
%x2 = icmp eq i32 %b, 0
br i1 %x2, label %no2, label %yes2
yes2:
store i32 1, i32* %p
br label %end
no2:
%z3 = sub i32 %z2, %b
br label %end
end:
%z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
ret i32 %z4
}
; Now there is a call to f() in the bottom branch. The store in the first
; branch would now be reordered with respect to the call if we if-converted,
; so we must not.
define i32 @test_diamond_alias3(i32* %p, i32* %q, i32 %a, i32 %b) {
; CHECK-LABEL: @test_diamond_alias3(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
; CHECK-NEXT: br i1 [[X1]], label [[NO1:%.*]], label [[YES1:%.*]]
; CHECK: yes1:
; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[FALLTHROUGH:%.*]]
; CHECK: no1:
; CHECK-NEXT: call void @f()
; CHECK-NEXT: [[Z1:%.*]] = add i32 [[A]], [[B:%.*]]
; CHECK-NEXT: br label [[FALLTHROUGH]]
; CHECK: fallthrough:
; CHECK-NEXT: [[Z2:%.*]] = phi i32 [ [[Z1]], [[NO1]] ], [ 0, [[YES1]] ]
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B]], 0
; CHECK-NEXT: br i1 [[X2]], label [[NO2:%.*]], label [[YES2:%.*]]
; CHECK: yes2:
; CHECK-NEXT: store i32 1, i32* [[P]], align 4
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: no2:
; CHECK-NEXT: call void @f()
; CHECK-NEXT: [[Z3:%.*]] = sub i32 [[Z2]], [[B]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[Z4:%.*]] = phi i32 [ [[Z3]], [[NO2]] ], [ 3, [[YES2]] ]
; CHECK-NEXT: ret i32 [[Z4]]
;
entry:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %no1, label %yes1
yes1:
store i32 0, i32* %p
br label %fallthrough
no1:
call void @f()
%z1 = add i32 %a, %b
br label %fallthrough
fallthrough:
%z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
%x2 = icmp eq i32 %b, 0
br i1 %x2, label %no2, label %yes2
yes2:
store i32 1, i32* %p
br label %end
no2:
call void @f()
%z3 = sub i32 %z2, %b
br label %end
end:
%z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
ret i32 %z4
}
; This test has an outer if over the two triangles. This requires creating a new BB to hold the store.
define void @test_outer_if(i32* %p, i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @test_outer_if(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: br i1 [[X3]], label [[END:%.*]], label [[CONTINUE:%.*]]
; CHECK: continue:
; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0
; CHECK-NEXT: br i1 [[TMP1]], label [[END]], label [[TMP2:%.*]]
; CHECK: 2:
; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
; CHECK-NEXT: store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
%x3 = icmp eq i32 %c, 0
br i1 %x3, label %end, label %continue
continue:
%x1 = icmp eq i32 %a, 0
br i1 %x1, label %fallthrough, label %yes1
yes1:
store i32 0, i32* %p
br label %fallthrough
fallthrough:
%x2 = icmp eq i32 %b, 0
br i1 %x2, label %end, label %yes2
yes2:
store i32 1, i32* %p
br label %end
end:
ret void
}