[SCCP] Remove forcedconstant, go to overdefined instead
This patch removes forcedconstant to simplify things for the
move to ValueLattice, which includes constant ranges, but no
forced constants.
This patch removes forcedconstant and changes ResolvedUndefsIn
to mark instructions with unknown operands as overdefined. This
means we do not do simplifications based on undef directly in SCCP
any longer, but this seems to hardly come up in practice (see stats
below), presumably because InstCombine & others take care
of most of the relevant folds already.
It is still beneficial to keep ResolvedUndefIn, as it allows us delaying
going to overdefined until we propagated all known information.
I also built MultiSource, SPEC2000 and SPEC2006 and compared
sccp.IPNumInstRemoved and sccp.NumInstRemoved. It looks like the impact
is quite low:
Tests: 244
Same hash: 238 (filtered out)
Remaining: 6
Metric: sccp.IPNumInstRemoved
Program base patch diff
test-suite...arks/VersaBench/dbms/dbms.test 4.00 3.00 -25.0%
test-suite...TimberWolfMC/timberwolfmc.test 38.00 34.00 -10.5%
test-suite...006/453.povray/453.povray.test 158.00 155.00 -1.9%
test-suite.../CINT2000/176.gcc/176.gcc.test 668.00 668.00 0.0%
test-suite.../CINT2006/403.gcc/403.gcc.test 1209.00 1209.00 0.0%
test-suite...arks/mafft/pairlocalalign.test 76.00 76.00 0.0%
Tests: 244
Same hash: 238 (filtered out)
Remaining: 6
Metric: sccp.NumInstRemoved
Program base patch diff
test-suite...arks/mafft/pairlocalalign.test 185.00 175.00 -5.4%
test-suite.../CINT2006/403.gcc/403.gcc.test 2059.00 2056.00 -0.1%
test-suite.../CINT2000/176.gcc/176.gcc.test 2358.00 2357.00 -0.0%
test-suite...006/453.povray/453.povray.test 317.00 317.00 0.0%
test-suite...TimberWolfMC/timberwolfmc.test 12.00 12.00 0.0%
Reviewers: davide, efriedma, mssimpso
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D61314
diff --git a/llvm/test/Transforms/IPConstantProp/PR16052.ll b/llvm/test/Transforms/IPConstantProp/PR16052.ll
index 451693f..a16067f 100644
--- a/llvm/test/Transforms/IPConstantProp/PR16052.ll
+++ b/llvm/test/Transforms/IPConstantProp/PR16052.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -S -ipsccp | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@@ -7,7 +7,9 @@
define i64 @fn2() {
; CHECK-LABEL: define {{[^@]+}}@fn2()
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef)
+; CHECK-NEXT: [[CONV:%.*]] = sext i32 undef to i64
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]]
+; CHECK-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]])
; CHECK-NEXT: ret i64 [[CALL2]]
;
entry:
@@ -21,7 +23,8 @@
; CHECK-LABEL: define {{[^@]+}}@fn1
; CHECK-SAME: (i64 [[P1:%.*]])
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[COND:%.*]] = select i1 undef, i64 undef, i64 undef
+; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i64 [[P1]], 0
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[P1]], i64 [[P1]]
; CHECK-NEXT: ret i64 [[COND]]
;
entry:
diff --git a/llvm/test/Transforms/IPConstantProp/PR26044.ll b/llvm/test/Transforms/IPConstantProp/PR26044.ll
index eeb5b87..8b4f259 100644
--- a/llvm/test/Transforms/IPConstantProp/PR26044.ll
+++ b/llvm/test/Transforms/IPConstantProp/PR26044.ll
@@ -11,7 +11,8 @@
; CHECK: for.cond1:
; CHECK-NEXT: br i1 false, label [[IF_END]], label [[IF_END]]
; CHECK: if.end:
-; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 undef)
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4
+; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]])
; CHECK-NEXT: store i32 [[CALL]], i32* [[P]]
; CHECK-NEXT: br label [[FOR_COND1:%.*]]
;
@@ -33,7 +34,8 @@
; CHECK-LABEL: define {{[^@]+}}@fn1
; CHECK-SAME: (i32 [[P1:%.*]])
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[COND:%.*]] = select i1 undef, i32 undef, i32 undef
+; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]]
; CHECK-NEXT: ret i32 [[COND]]
;
entry:
diff --git a/llvm/test/Transforms/SCCP/2006-12-19-UndefBug.ll b/llvm/test/Transforms/SCCP/2006-12-19-UndefBug.ll
index ede1a32..4bd096e 100644
--- a/llvm/test/Transforms/SCCP/2006-12-19-UndefBug.ll
+++ b/llvm/test/Transforms/SCCP/2006-12-19-UndefBug.ll
@@ -1,8 +1,12 @@
-; RUN: opt < %s -sccp -S | \
-; RUN: grep "ret i1 false"
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -sccp -S | FileCheck %s
define i1 @foo() {
- %X = and i1 false, undef ; <i1> [#uses=1]
- ret i1 %X
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: [[X:%.*]] = and i1 false, undef
+; CHECK-NEXT: ret i1 [[X]]
+;
+ %X = and i1 false, undef ; <i1> [#uses=1]
+ ret i1 %X
}
diff --git a/llvm/test/Transforms/SCCP/apint-bigint2.ll b/llvm/test/Transforms/SCCP/apint-bigint2.ll
index 5277d9f..7d75240 100644
--- a/llvm/test/Transforms/SCCP/apint-bigint2.ll
+++ b/llvm/test/Transforms/SCCP/apint-bigint2.ll
@@ -18,7 +18,13 @@
}
; CHECK-LABEL: @large_aggregate
-; CHECK-NEXT: ret i101 undef
+; CHECK-NEXT: %B = load i101, i101* undef
+; CHECK-NEXT: %D = and i101 %B, 1
+; CHECK-NEXT: %DD = or i101 %D, 1
+; CHECK-NEXT: %G = getelementptr i101, i101* getelementptr inbounds ([6 x i101], [6 x i101]* @Y, i32 0, i32 5), i101 %DD
+; CHECK-NEXT: %L3 = load i101, i101* %G
+; CHECK-NEXT: ret i101 %L3
+;
define i101 @large_aggregate() {
%B = load i101, i101* undef
%D = and i101 %B, 1
@@ -29,6 +35,22 @@
ret i101 %L3
}
+; CHECK-LABEL: define i101 @large_aggregate_2() {
+; CHECK-NEXT: %D = and i101 undef, 1
+; CHECK-NEXT: %DD = or i101 %D, 1
+; CHECK-NEXT: %G = getelementptr i101, i101* getelementptr inbounds ([6 x i101], [6 x i101]* @Y, i32 0, i32 5), i101 %DD
+; CHECK-NEXT: %L3 = load i101, i101* %G
+; CHECK-NEXT: ret i101 %L3
+;
+define i101 @large_aggregate_2() {
+ %D = and i101 undef, 1
+ %DD = or i101 %D, 1
+ %F = getelementptr [6 x i101], [6 x i101]* @Y, i32 0, i32 5
+ %G = getelementptr i101, i101* %F, i101 %DD
+ %L3 = load i101, i101* %G
+ ret i101 %L3
+}
+
; CHECK-LABEL: @index_too_large
; CHECK-NEXT: store i101* getelementptr (i101, i101* getelementptr ([6 x i101], [6 x i101]* @Y, i32 0, i32 -1), i101 9224497936761618431), i101** undef
; CHECK-NEXT: ret void
diff --git a/llvm/test/Transforms/SCCP/apint-ipsccp3.ll b/llvm/test/Transforms/SCCP/apint-ipsccp3.ll
index c99ae58..4ba1f8d 100644
--- a/llvm/test/Transforms/SCCP/apint-ipsccp3.ll
+++ b/llvm/test/Transforms/SCCP/apint-ipsccp3.ll
@@ -1,23 +1,39 @@
-; RUN: opt < %s -ipsccp -S | not grep global
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -ipsccp -S | FileCheck %s
@G = internal global i66 undef
-
define void @foo() {
- %X = load i66, i66* @G
- store i66 %X, i66* @G
- ret void
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: [[X:%.*]] = load i66, i66* @G
+; CHECK-NEXT: store i66 [[X]], i66* @G
+; CHECK-NEXT: ret void
+;
+ %X = load i66, i66* @G
+ store i66 %X, i66* @G
+ ret void
}
define i66 @bar() {
- %V = load i66, i66* @G
- %C = icmp eq i66 %V, 17
- br i1 %C, label %T, label %F
+; CHECK-LABEL: @bar(
+; CHECK-NEXT: [[V:%.*]] = load i66, i66* @G
+; CHECK-NEXT: [[C:%.*]] = icmp eq i66 [[V]], 17
+; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
+; CHECK: T:
+; CHECK-NEXT: store i66 17, i66* @G
+; CHECK-NEXT: ret i66 17
+; CHECK: F:
+; CHECK-NEXT: store i66 123, i66* @G
+; CHECK-NEXT: ret i66 0
+;
+ %V = load i66, i66* @G
+ %C = icmp eq i66 %V, 17
+ br i1 %C, label %T, label %F
T:
- store i66 17, i66* @G
- ret i66 %V
+ store i66 17, i66* @G
+ ret i66 %V
F:
- store i66 123, i66* @G
- ret i66 0
+ store i66 123, i66* @G
+ ret i66 0
}
diff --git a/llvm/test/Transforms/SCCP/apint-select.ll b/llvm/test/Transforms/SCCP/apint-select.ll
index 893331e..d797c7a 100644
--- a/llvm/test/Transforms/SCCP/apint-select.ll
+++ b/llvm/test/Transforms/SCCP/apint-select.ll
@@ -1,21 +1,29 @@
-; RUN: opt < %s -sccp -S | not grep select
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -sccp -S | FileCheck %s
@A = constant i32 10
define i712 @test1() {
- %P = getelementptr i32, i32* @A, i32 0
- %B = ptrtoint i32* %P to i64
- %BB = and i64 %B, undef
- %C = icmp sge i64 %BB, 0
- %X = select i1 %C, i712 0, i712 1
- ret i712 %X
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: [[BB:%.*]] = and i64 ptrtoint (i32* @A to i64), undef
+; CHECK-NEXT: [[C:%.*]] = icmp sge i64 [[BB]], 0
+; CHECK-NEXT: [[X:%.*]] = select i1 [[C]], i712 0, i712 1
+; CHECK-NEXT: ret i712 [[X]]
+;
+ %P = getelementptr i32, i32* @A, i32 0
+ %B = ptrtoint i32* %P to i64
+ %BB = and i64 %B, undef
+ %C = icmp sge i64 %BB, 0
+ %X = select i1 %C, i712 0, i712 1
+ ret i712 %X
}
define i712 @test2(i1 %C) {
- %X = select i1 %C, i712 0, i712 undef
- ret i712 %X
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: ret i712 0
+;
+ %X = select i1 %C, i712 0, i712 undef
+ ret i712 %X
}
-
-
diff --git a/llvm/test/Transforms/SCCP/ip-constant-ranges.ll b/llvm/test/Transforms/SCCP/ip-constant-ranges.ll
index 426e327..08de8db 100644
--- a/llvm/test/Transforms/SCCP/ip-constant-ranges.ll
+++ b/llvm/test/Transforms/SCCP/ip-constant-ranges.ll
@@ -141,10 +141,12 @@
; Constant range for %x is [47, 302)
; CHECK-LABEL: @f5
; CHECK-NEXT: entry:
-; CHECK-NEXT: %cmp = icmp sgt i32 %x, undef
-; CHECK-NEXT: %res1 = select i1 %cmp, i32 1, i32 2
-; CHECK-NEXT: %res = add i32 %res1, 3
-; CHECK-NEXT: ret i32 %res
+; CHECK-NEXT: %cmp = icmp sgt i32 %x, undef
+; CHECK-NEXT: %cmp2 = icmp ne i32 undef, %x
+; CHECK-NEXT: %res1 = select i1 %cmp, i32 1, i32 2
+; CHECK-NEXT: %res2 = select i1 %cmp2, i32 3, i32 4
+; CHECK-NEXT: %res = add i32 %res1, %res2
+; CHECK-NEXT: ret i32 %res
define internal i32 @f5(i32 %x) {
entry:
%cmp = icmp sgt i32 %x, undef
diff --git a/llvm/test/Transforms/SCCP/ipsccp-basic.ll b/llvm/test/Transforms/SCCP/ipsccp-basic.ll
index b1660b5..795a73f 100644
--- a/llvm/test/Transforms/SCCP/ipsccp-basic.ll
+++ b/llvm/test/Transforms/SCCP/ipsccp-basic.ll
@@ -56,7 +56,9 @@
ret void
}
; CHECK-LABEL: define void @test3a(
-; CHECK-NEXT: ret void
+; CHECK-NEXT: %X = load i32, i32* @G
+; CHECK-NEXT: store i32 %X, i32* @G
+; CHECK-NEXT: ret void
define i32 @test3b() {
@@ -71,9 +73,17 @@
ret i32 0
}
; CHECK-LABEL: define i32 @test3b(
-; CHECK-NOT: store
-; CHECK: ret i32 0
+; CHECK-NEXT: %V = load i32, i32* @G
+; CHECK-NEXT: %C = icmp eq i32 %V, 17
+; CHECK-NEXT: br i1 %C, label %T, label %F
+; CHECK-LABEL: T:
+; CHECK-NEXT: store i32 17, i32* @G
+; CHECK-NEXT: ret i32 17
+
+; CHECK-LABEL: F:
+; CHECK-NEXT: store i32 123, i32* @G
+; CHECK-NEXT: ret i32 0
;;======================== test4
@@ -226,8 +236,11 @@
entry:
%call = call i32 @test10b(i32 undef)
ret i32 %call
+
; CHECK-LABEL: define i32 @test10a(
-; CHECK: ret i32 0
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %call = call i32 @test10b(i32 undef)
+; CHECK-NEXT: ret i32 %call
}
define internal i32 @test10b(i32 %x) nounwind {
@@ -235,7 +248,9 @@
%r = and i32 %x, 1
ret i32 %r
; CHECK-LABEL: define internal i32 @test10b(
-; CHECK: ret i32 undef
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %r = and i32 undef, 1
+; CHECK-NEXT: ret i32 %r
}
;;======================== test11
@@ -244,7 +259,8 @@
%xor = xor i64 undef, undef
ret i64 %xor
; CHECK-LABEL: define i64 @test11a
-; CHECK: ret i64 0
+; CHECK-NEXT: %xor = xor i64 undef, undef
+; CHECK-NEXT: ret i64 %xor
}
define i64 @test11b() {
@@ -252,9 +268,9 @@
%call2 = call i64 @llvm.ctpop.i64(i64 %call1)
ret i64 %call2
; CHECK-LABEL: define i64 @test11b
-; CHECK: %[[call1:.*]] = call i64 @test11a()
-; CHECK-NOT: call i64 @llvm.ctpop.i64
-; CHECK-NEXT: ret i64 0
+; CHECK-NEXT: [[call1:%.*]] = call i64 @test11a()
+; CHECK-NEXT: [[call2:%.*]] = call i64 @llvm.ctpop.i64(i64 [[call1]])
+; CHECK-NEXT: ret i64 [[call2]]
}
declare i64 @llvm.ctpop.i64(i64)
diff --git a/llvm/test/Transforms/SCCP/logical-nuke.ll b/llvm/test/Transforms/SCCP/logical-nuke.ll
index 6ca16de4..5152e12 100644
--- a/llvm/test/Transforms/SCCP/logical-nuke.ll
+++ b/llvm/test/Transforms/SCCP/logical-nuke.ll
@@ -1,39 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -sccp -S | FileCheck %s
; Test that SCCP has basic knowledge of when and/or/mul nuke overdefined values.
-; CHECK-LABEL: test
-; CHECK: ret i32 0
define i32 @test(i32 %X) {
+; CHECK-LABEL: @test(
+; CHECK-NEXT: ret i32 0
+;
%Y = and i32 %X, 0
ret i32 %Y
}
-; CHECK-LABEL: test2
-; CHECK: ret i32 -1
define i32 @test2(i32 %X) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: ret i32 -1
+;
%Y = or i32 -1, %X
ret i32 %Y
}
-; CHECK-LABEL: test3
-; CHECK: ret i32 0
define i32 @test3(i32 %X) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT: [[Y:%.*]] = and i32 undef, [[X:%.*]]
+; CHECK-NEXT: ret i32 [[Y]]
+;
%Y = and i32 undef, %X
ret i32 %Y
}
-; CHECK-LABEL: test4
-; CHECK: ret i32 -1
define i32 @test4(i32 %X) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT: [[Y:%.*]] = or i32 [[X:%.*]], undef
+; CHECK-NEXT: ret i32 [[Y]]
+;
%Y = or i32 %X, undef
ret i32 %Y
}
; X * 0 = 0 even if X is overdefined.
-; CHECK-LABEL: test5
-; CHECK: ret i32 0
define i32 @test5(i32 %foo) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT: ret i32 0
+;
%patatino = mul i32 %foo, 0
ret i32 %patatino
}
diff --git a/llvm/test/Transforms/SCCP/switch-multiple-undef.ll b/llvm/test/Transforms/SCCP/switch-multiple-undef.ll
index 027c9c0..df99e4e 100644
--- a/llvm/test/Transforms/SCCP/switch-multiple-undef.ll
+++ b/llvm/test/Transforms/SCCP/switch-multiple-undef.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -ipsccp < %s | FileCheck %s
declare void @foo()
@@ -5,9 +6,25 @@
declare void @patatino()
define void @test1(i32 %t) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: [[CHOICE:%.*]] = icmp eq i32 undef, -1
+; CHECK-NEXT: switch i1 [[CHOICE]], label [[FIRST:%.*]] [
+; CHECK-NEXT: i1 false, label [[SECOND:%.*]]
+; CHECK-NEXT: i1 true, label [[THIRD:%.*]]
+; CHECK-NEXT: ]
+; CHECK: first:
+; CHECK-NEXT: call void @foo()
+; CHECK-NEXT: ret void
+; CHECK: second:
+; CHECK-NEXT: call void @goo()
+; CHECK-NEXT: ret void
+; CHECK: third:
+; CHECK-NEXT: call void @patatino()
+; CHECK-NEXT: ret void
+;
%choice = icmp eq i32 undef, -1
switch i1 %choice, label %first [i1 0, label %second
- i1 1, label %third]
+ i1 1, label %third]
first:
call void @foo()
ret void
@@ -18,10 +35,3 @@
call void @patatino()
ret void
}
-
-; CHECK: define void @test1(i32 %t) {
-; CHECK-NEXT: br label %second
-; CHECK: second:
-; CHECK-NEXT: call void @goo()
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
diff --git a/llvm/test/Transforms/SCCP/ub-shift.ll b/llvm/test/Transforms/SCCP/ub-shift.ll
index 3fb2d97..6e15d6b 100644
--- a/llvm/test/Transforms/SCCP/ub-shift.ll
+++ b/llvm/test/Transforms/SCCP/ub-shift.ll
@@ -1,68 +1,89 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -sccp -S | FileCheck %s
-; CHECK-LABEL: shift_undef_64
define void @shift_undef_64(i64* %p) {
+; CHECK-LABEL: @shift_undef_64(
+; CHECK-NEXT: [[R1:%.*]] = lshr i64 -1, 4294967296
+; CHECK-NEXT: store i64 [[R1]], i64* [[P:%.*]]
+; CHECK-NEXT: [[R2:%.*]] = ashr i64 -1, 4294967297
+; CHECK-NEXT: store i64 [[R2]], i64* [[P]]
+; CHECK-NEXT: [[R3:%.*]] = shl i64 -1, 4294967298
+; CHECK-NEXT: store i64 [[R3]], i64* [[P]]
+; CHECK-NEXT: ret void
+;
%r1 = lshr i64 -1, 4294967296 ; 2^32
- ; CHECK: store i64 undef
store i64 %r1, i64* %p
%r2 = ashr i64 -1, 4294967297 ; 2^32 + 1
- ; CHECK: store i64 undef
store i64 %r2, i64* %p
%r3 = shl i64 -1, 4294967298 ; 2^32 + 2
- ; CHECK: store i64 undef
store i64 %r3, i64* %p
ret void
}
-; CHECK-LABEL: shift_undef_65
define void @shift_undef_65(i65* %p) {
+; CHECK-LABEL: @shift_undef_65(
+; CHECK-NEXT: [[R1:%.*]] = lshr i65 2, -18446744073709551615
+; CHECK-NEXT: store i65 [[R1]], i65* [[P:%.*]]
+; CHECK-NEXT: [[R2:%.*]] = ashr i65 4, -18446744073709551615
+; CHECK-NEXT: store i65 [[R2]], i65* [[P]]
+; CHECK-NEXT: [[R3:%.*]] = shl i65 1, -18446744073709551615
+; CHECK-NEXT: store i65 [[R3]], i65* [[P]]
+; CHECK-NEXT: ret void
+;
%r1 = lshr i65 2, 18446744073709551617
- ; CHECK: store i65 undef
store i65 %r1, i65* %p
%r2 = ashr i65 4, 18446744073709551617
- ; CHECK: store i65 undef
store i65 %r2, i65* %p
%r3 = shl i65 1, 18446744073709551617
- ; CHECK: store i65 undef
store i65 %r3, i65* %p
ret void
}
-; CHECK-LABEL: shift_undef_256
define void @shift_undef_256(i256* %p) {
+; CHECK-LABEL: @shift_undef_256(
+; CHECK-NEXT: [[R1:%.*]] = lshr i256 2, 18446744073709551617
+; CHECK-NEXT: store i256 [[R1]], i256* [[P:%.*]]
+; CHECK-NEXT: [[R2:%.*]] = ashr i256 4, 18446744073709551618
+; CHECK-NEXT: store i256 [[R2]], i256* [[P]]
+; CHECK-NEXT: [[R3:%.*]] = shl i256 1, 18446744073709551619
+; CHECK-NEXT: store i256 [[R3]], i256* [[P]]
+; CHECK-NEXT: ret void
+;
%r1 = lshr i256 2, 18446744073709551617
- ; CHECK: store i256 undef
store i256 %r1, i256* %p
%r2 = ashr i256 4, 18446744073709551618
- ; CHECK: store i256 undef
store i256 %r2, i256* %p
%r3 = shl i256 1, 18446744073709551619
- ; CHECK: store i256 undef
store i256 %r3, i256* %p
ret void
}
-; CHECK-LABEL: shift_undef_511
define void @shift_undef_511(i511* %p) {
+; CHECK-LABEL: @shift_undef_511(
+; CHECK-NEXT: [[R1:%.*]] = lshr i511 -1, 1208925819614629174706276
+; CHECK-NEXT: store i511 [[R1]], i511* [[P:%.*]]
+; CHECK-NEXT: [[R2:%.*]] = ashr i511 -2, 1208925819614629174706200
+; CHECK-NEXT: store i511 [[R2]], i511* [[P]]
+; CHECK-NEXT: [[R3:%.*]] = shl i511 -3, 1208925819614629174706180
+; CHECK-NEXT: store i511 [[R3]], i511* [[P]]
+; CHECK-NEXT: ret void
+;
%r1 = lshr i511 -1, 1208925819614629174706276 ; 2^80 + 100
- ; CHECK: store i511 undef
store i511 %r1, i511* %p
%r2 = ashr i511 -2, 1208925819614629174706200
- ; CHECK: store i511 undef
store i511 %r2, i511* %p
%r3 = shl i511 -3, 1208925819614629174706180
- ; CHECK: store i511 undef
store i511 %r3, i511* %p
ret void
diff --git a/llvm/test/Transforms/SCCP/undef-resolve.ll b/llvm/test/Transforms/SCCP/undef-resolve.ll
index 7fdcd55..e2a4268 100644
--- a/llvm/test/Transforms/SCCP/undef-resolve.ll
+++ b/llvm/test/Transforms/SCCP/undef-resolve.ll
@@ -1,12 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -sccp -S < %s | FileCheck %s
; PR6940
define double @test1() {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: [[T:%.*]] = sitofp i32 undef to double
+; CHECK-NEXT: ret double [[T]]
+;
%t = sitofp i32 undef to double
ret double %t
-; CHECK-LABEL: @test1(
-; CHECK: ret double 0.0
}
@@ -14,6 +17,72 @@
; Check that lots of stuff doesn't get turned into undef.
define i32 @test2() nounwind readnone ssp {
; CHECK-LABEL: @test2(
+; CHECK-NEXT: init:
+; CHECK-NEXT: br label [[CONTROL_OUTER_OUTER:%.*]]
+; CHECK: control.outer.loopexit.us-lcssa:
+; CHECK-NEXT: br label [[CONTROL_OUTER_LOOPEXIT:%.*]]
+; CHECK: control.outer.loopexit:
+; CHECK-NEXT: br label [[CONTROL_OUTER_OUTER_BACKEDGE:%.*]]
+; CHECK: control.outer.outer:
+; CHECK-NEXT: [[SWITCHCOND_0_PH_PH:%.*]] = phi i32 [ 2, [[INIT:%.*]] ], [ 3, [[CONTROL_OUTER_OUTER_BACKEDGE]] ]
+; CHECK-NEXT: [[I_0_PH_PH:%.*]] = phi i32 [ undef, [[INIT]] ], [ [[I_0_PH_PH_BE:%.*]], [[CONTROL_OUTER_OUTER_BACKEDGE]] ]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[I_0_PH_PH]], 0
+; CHECK-NEXT: br i1 [[TMP4]], label [[CONTROL_OUTER_OUTER_SPLIT_US:%.*]], label [[CONTROL_OUTER_OUTER_CONTROL_OUTER_OUTER_SPLIT_CRIT_EDGE:%.*]]
+; CHECK: control.outer.outer.control.outer.outer.split_crit_edge:
+; CHECK-NEXT: br label [[CONTROL_OUTER:%.*]]
+; CHECK: control.outer.outer.split.us:
+; CHECK-NEXT: br label [[CONTROL_OUTER_US:%.*]]
+; CHECK: control.outer.us:
+; CHECK-NEXT: [[A_0_PH_US:%.*]] = phi i32 [ [[SWITCHCOND_0_US:%.*]], [[BB3_US:%.*]] ], [ 4, [[CONTROL_OUTER_OUTER_SPLIT_US]] ]
+; CHECK-NEXT: [[SWITCHCOND_0_PH_US:%.*]] = phi i32 [ [[A_0_PH_US]], [[BB3_US]] ], [ [[SWITCHCOND_0_PH_PH]], [[CONTROL_OUTER_OUTER_SPLIT_US]] ]
+; CHECK-NEXT: br label [[CONTROL_US:%.*]]
+; CHECK: bb3.us:
+; CHECK-NEXT: br label [[CONTROL_OUTER_US]]
+; CHECK: bb0.us:
+; CHECK-NEXT: br label [[CONTROL_US]]
+; CHECK: control.us:
+; CHECK-NEXT: [[SWITCHCOND_0_US]] = phi i32 [ [[A_0_PH_US]], [[BB0_US:%.*]] ], [ [[SWITCHCOND_0_PH_US]], [[CONTROL_OUTER_US]] ]
+; CHECK-NEXT: switch i32 [[SWITCHCOND_0_US]], label [[CONTROL_OUTER_LOOPEXIT_US_LCSSA_US:%.*]] [
+; CHECK-NEXT: i32 0, label [[BB0_US]]
+; CHECK-NEXT: i32 1, label [[BB1_US_LCSSA_US:%.*]]
+; CHECK-NEXT: i32 3, label [[BB3_US]]
+; CHECK-NEXT: i32 4, label [[BB4_US_LCSSA_US:%.*]]
+; CHECK-NEXT: ]
+; CHECK: control.outer.loopexit.us-lcssa.us:
+; CHECK-NEXT: br label [[CONTROL_OUTER_LOOPEXIT]]
+; CHECK: bb1.us-lcssa.us:
+; CHECK-NEXT: br label [[BB1:%.*]]
+; CHECK: bb4.us-lcssa.us:
+; CHECK-NEXT: br label [[BB4:%.*]]
+; CHECK: control.outer:
+; CHECK-NEXT: [[A_0_PH:%.*]] = phi i32 [ [[NEXTID17:%.*]], [[BB3:%.*]] ], [ 4, [[CONTROL_OUTER_OUTER_CONTROL_OUTER_OUTER_SPLIT_CRIT_EDGE]] ]
+; CHECK-NEXT: [[SWITCHCOND_0_PH:%.*]] = phi i32 [ 0, [[BB3]] ], [ [[SWITCHCOND_0_PH_PH]], [[CONTROL_OUTER_OUTER_CONTROL_OUTER_OUTER_SPLIT_CRIT_EDGE]] ]
+; CHECK-NEXT: br label [[CONTROL:%.*]]
+; CHECK: control:
+; CHECK-NEXT: [[SWITCHCOND_0:%.*]] = phi i32 [ [[A_0_PH]], [[BB0:%.*]] ], [ [[SWITCHCOND_0_PH]], [[CONTROL_OUTER]] ]
+; CHECK-NEXT: switch i32 [[SWITCHCOND_0]], label [[CONTROL_OUTER_LOOPEXIT_US_LCSSA:%.*]] [
+; CHECK-NEXT: i32 0, label [[BB0]]
+; CHECK-NEXT: i32 1, label [[BB1_US_LCSSA:%.*]]
+; CHECK-NEXT: i32 3, label [[BB3]]
+; CHECK-NEXT: i32 4, label [[BB4_US_LCSSA:%.*]]
+; CHECK-NEXT: ]
+; CHECK: bb4.us-lcssa:
+; CHECK-NEXT: br label [[BB4]]
+; CHECK: bb4:
+; CHECK-NEXT: br label [[CONTROL_OUTER_OUTER_BACKEDGE]]
+; CHECK: control.outer.outer.backedge:
+; CHECK-NEXT: [[I_0_PH_PH_BE]] = phi i32 [ 1, [[BB4]] ], [ 0, [[CONTROL_OUTER_LOOPEXIT]] ]
+; CHECK-NEXT: br label [[CONTROL_OUTER_OUTER]]
+; CHECK: bb3:
+; CHECK-NEXT: [[NEXTID17]] = add i32 [[SWITCHCOND_0]], -2
+; CHECK-NEXT: br label [[CONTROL_OUTER]]
+; CHECK: bb0:
+; CHECK-NEXT: br label [[CONTROL]]
+; CHECK: bb1.us-lcssa:
+; CHECK-NEXT: br label [[BB1]]
+; CHECK: bb1:
+; CHECK-NEXT: ret i32 0
+;
init:
br label %control.outer.outer
@@ -46,16 +115,13 @@
bb0.us: ; preds = %control.us
br label %control.us
-; CHECK: control.us: ; preds = %bb0.us, %control.outer.us
-; CHECK-NEXT: %switchCond.0.us = phi i32
-; CHECK-NEXT: switch i32 %switchCond.0.us
control.us: ; preds = %bb0.us, %control.outer.us
%switchCond.0.us = phi i32 [ %A.0.ph.us, %bb0.us ], [ %switchCond.0.ph.us, %control.outer.us ] ; <i32> [#uses=2]
switch i32 %switchCond.0.us, label %control.outer.loopexit.us-lcssa.us [
- i32 0, label %bb0.us
- i32 1, label %bb1.us-lcssa.us
- i32 3, label %bb3.us
- i32 4, label %bb4.us-lcssa.us
+ i32 0, label %bb0.us
+ i32 1, label %bb1.us-lcssa.us
+ i32 3, label %bb3.us
+ i32 4, label %bb4.us-lcssa.us
]
control.outer.loopexit.us-lcssa.us: ; preds = %control.us
@@ -75,10 +141,10 @@
control: ; preds = %bb0, %control.outer
%switchCond.0 = phi i32 [ %A.0.ph, %bb0 ], [ %switchCond.0.ph, %control.outer ] ; <i32> [#uses=2]
switch i32 %switchCond.0, label %control.outer.loopexit.us-lcssa [
- i32 0, label %bb0
- i32 1, label %bb1.us-lcssa
- i32 3, label %bb3
- i32 4, label %bb4.us-lcssa
+ i32 0, label %bb0
+ i32 1, label %bb1.us-lcssa
+ i32 3, label %bb3
+ i32 4, label %bb4.us-lcssa
]
bb4.us-lcssa: ; preds = %control
@@ -108,83 +174,105 @@
; Make sure SCCP honors the xor "idiom"
; rdar://9956541
define i32 @test3() {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT: [[T:%.*]] = xor i32 undef, undef
+; CHECK-NEXT: ret i32 [[T]]
+;
%t = xor i32 undef, undef
ret i32 %t
-; CHECK-LABEL: @test3(
-; CHECK: ret i32 0
}
; Be conservative with FP ops
define double @test4(double %x) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT: [[T:%.*]] = fadd double [[X:%.*]], undef
+; CHECK-NEXT: ret double [[T]]
+;
%t = fadd double %x, undef
ret double %t
-; CHECK-LABEL: @test4(
-; CHECK: fadd double %x, undef
}
; Make sure casts produce a possible value
define i32 @test5() {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT: [[T:%.*]] = sext i8 undef to i32
+; CHECK-NEXT: ret i32 [[T]]
+;
%t = sext i8 undef to i32
ret i32 %t
-; CHECK-LABEL: @test5(
-; CHECK: ret i32 0
}
; Make sure ashr produces a possible value
define i32 @test6() {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT: [[T:%.*]] = ashr i32 undef, 31
+; CHECK-NEXT: ret i32 [[T]]
+;
%t = ashr i32 undef, 31
ret i32 %t
-; CHECK-LABEL: @test6(
-; CHECK: ret i32 0
}
; Make sure lshr produces a possible value
define i32 @test7() {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT: [[T:%.*]] = lshr i32 undef, 31
+; CHECK-NEXT: ret i32 [[T]]
+;
%t = lshr i32 undef, 31
ret i32 %t
-; CHECK-LABEL: @test7(
-; CHECK: ret i32 0
}
; icmp eq with undef simplifies to undef
define i1 @test8() {
+; CHECK-LABEL: @test8(
+; CHECK-NEXT: [[T:%.*]] = icmp eq i32 undef, -1
+; CHECK-NEXT: ret i1 [[T]]
+;
%t = icmp eq i32 undef, -1
ret i1 %t
-; CHECK-LABEL: @test8(
-; CHECK: ret i1 undef
}
; Make sure we don't conclude that relational comparisons simplify to undef
define i1 @test9() {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT: [[T:%.*]] = icmp ugt i32 undef, -1
+; CHECK-NEXT: ret i1 [[T]]
+;
%t = icmp ugt i32 undef, -1
ret i1 %t
-; CHECK-LABEL: @test9(
-; CHECK: icmp ugt
}
; Make sure we handle extractvalue
-define i64 @test10() {
+define i64 @test10() {
+; CHECK-LABEL: @test10(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[E:%.*]] = extractvalue { i64, i64 } undef, 1
+; CHECK-NEXT: ret i64 [[E]]
+;
entry:
%e = extractvalue { i64, i64 } undef, 1
ret i64 %e
-; CHECK-LABEL: @test10(
-; CHECK: ret i64 undef
}
@GV = external global i32
define i32 @test11(i1 %tobool) {
+; CHECK-LABEL: @test11(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHR4:%.*]] = ashr i32 undef, zext (i1 icmp eq (i32* bitcast (i32 (i1)* @test11 to i32*), i32* @GV) to i32)
+; CHECK-NEXT: ret i32 [[SHR4]]
+;
entry:
%shr4 = ashr i32 undef, zext (i1 icmp eq (i32* bitcast (i32 (i1)* @test11 to i32*), i32* @GV) to i32)
ret i32 %shr4
-; CHECK-LABEL: @test11(
-; CHECK: ret i32 0
}
; Test unary ops
define double @test12(double %x) {
+; CHECK-LABEL: @test12(
+; CHECK-NEXT: [[T:%.*]] = fneg double undef
+; CHECK-NEXT: ret double [[T]]
+;
%t = fneg double undef
ret double %t
-; CHECK-LABEL: @test12(
-; CHECK: double undef
}