242 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; RUN: opt -simplifycfg -instcombine < %s -simplifycfg-merge-cond-stores=true -simplifycfg-merge-cond-stores-aggressively=false -phi-node-folding-threshold=2 -S | FileCheck %s
 | 
						|
 | 
						|
; CHECK-LABEL: @test_simple
 | 
						|
; This test should succeed and end up if-converted.
 | 
						|
; CHECK: icmp eq i32 %b, 0
 | 
						|
; CHECK-NEXT: icmp ne i32 %a, 0
 | 
						|
; CHECK-NEXT: xor i1 %x2, true
 | 
						|
; CHECK-NEXT: %[[x:.*]] = or i1 %{{.*}}, %{{.*}}
 | 
						|
; CHECK-NEXT: br i1 %[[x]]
 | 
						|
; CHECK: store
 | 
						|
; CHECK-NOT: store
 | 
						|
; CHECK: ret
 | 
						|
define void @test_simple(i32* %p, i32 %a, i32 %b) {
 | 
						|
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
 | 
						|
}
 | 
						|
 | 
						|
; CHECK-LABEL: @test_recursive
 | 
						|
; This test should entirely fold away, leaving one large basic block.
 | 
						|
; CHECK: store
 | 
						|
; CHECK-NOT: store
 | 
						|
; CHECK: ret
 | 
						|
define void @test_recursive(i32* %p, i32 %a, i32 %b, i32 %c, i32 %d) {
 | 
						|
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
 | 
						|
}
 | 
						|
 | 
						|
; CHECK-LABEL: @test_not_ifconverted
 | 
						|
; The code in each diamond is too large - it won't be if-converted so our
 | 
						|
; heuristics should say no.
 | 
						|
; CHECK: store
 | 
						|
; CHECK: store
 | 
						|
; CHECK: ret
 | 
						|
define void @test_not_ifconverted(i32* %p, i32 %a, i32 %b) {
 | 
						|
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
 | 
						|
}
 | 
						|
 | 
						|
; CHECK-LABEL: @test_aliasing1
 | 
						|
; The store to %p clobbers the previous store, so if-converting this would
 | 
						|
; be illegal.
 | 
						|
; CHECK: store
 | 
						|
; CHECK: store
 | 
						|
; CHECK: ret
 | 
						|
define void @test_aliasing1(i32* %p, i32 %a, i32 %b) {
 | 
						|
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
 | 
						|
}
 | 
						|
 | 
						|
; CHECK-LABEL: @test_aliasing2
 | 
						|
; The load from %q aliases with %p, so if-converting this would be illegal.
 | 
						|
; CHECK: store
 | 
						|
; CHECK: store
 | 
						|
; CHECK: ret
 | 
						|
define void @test_aliasing2(i32* %p, i32* %q, i32 %a, i32 %b) {
 | 
						|
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()
 | 
						|
 | 
						|
; CHECK-LABEL: @test_diamond_simple
 | 
						|
; This should get if-converted.
 | 
						|
; CHECK: store
 | 
						|
; CHECK-NOT: store
 | 
						|
; CHECK: ret
 | 
						|
define i32 @test_diamond_simple(i32* %p, i32* %q, i32 %a, i32 %b) {
 | 
						|
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
 | 
						|
}
 | 
						|
 | 
						|
; CHECK-LABEL: @test_diamond_alias3
 | 
						|
; 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.
 | 
						|
; CHECK: store
 | 
						|
; CHECK: store
 | 
						|
; CHECK: ret
 | 
						|
define i32 @test_diamond_alias3(i32* %p, i32* %q, i32 %a, i32 %b) {
 | 
						|
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
 | 
						|
}
 |