[Hexagon] Implement MI-level constant propagation

llvm-svn: 277028
diff --git a/llvm/test/CodeGen/Hexagon/constp-clb.ll b/llvm/test/CodeGen/Hexagon/constp-clb.ll
new file mode 100644
index 0000000..1a872b1
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/constp-clb.ll
@@ -0,0 +1,23 @@
+; RUN: llc -mcpu=hexagonv5 < %s
+; REQUIRES: asserts
+
+target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-v32:32-n16:32"
+target triple = "hexagon-unknown--elf"
+
+; Function Attrs: nounwind readnone
+define i64 @foo() #0 {
+entry:
+  %0 = tail call i32 @llvm.hexagon.S2.clbp(i64 291)
+  %1 = tail call i64 @llvm.hexagon.A4.combineir(i32 0, i32 %0)
+  ret i64 %1
+}
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.hexagon.S2.clbp(i64) #1
+
+; Function Attrs: nounwind readnone
+declare i64 @llvm.hexagon.A4.combineir(i32, i32) #1
+
+attributes #0 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
diff --git a/llvm/test/CodeGen/Hexagon/constp-combine-neg.ll b/llvm/test/CodeGen/Hexagon/constp-combine-neg.ll
new file mode 100644
index 0000000..18f0e81
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/constp-combine-neg.ll
@@ -0,0 +1,27 @@
+; RUN: llc -O2 -march=hexagon < %s | FileCheck %s --check-prefix=CHECK-TEST1
+; RUN: llc -O2 -march=hexagon < %s | FileCheck %s --check-prefix=CHECK-TEST2
+; RUN: llc -O2 -march=hexagon < %s | FileCheck %s --check-prefix=CHECK-TEST3
+define i32 @main() #0 {
+entry:
+  %l = alloca [7 x i32], align 8
+  %p_arrayidx45 = bitcast [7 x i32]* %l to i32*
+  %vector_ptr = bitcast [7 x i32]* %l to <2 x i32>*
+  store <2 x i32> <i32 3, i32 -2>, <2 x i32>* %vector_ptr, align 8
+  %p_arrayidx.1 = getelementptr [7 x i32], [7 x i32]* %l, i32 0, i32 2
+  %vector_ptr.1 = bitcast i32* %p_arrayidx.1 to <2 x i32>*
+  store <2 x i32> <i32 -4, i32 6>, <2 x i32>* %vector_ptr.1, align 8
+  %p_arrayidx.2 = getelementptr [7 x i32], [7 x i32]* %l, i32 0, i32 4
+  %vector_ptr.2 = bitcast i32* %p_arrayidx.2 to <2 x i32>*
+  store <2 x i32> <i32 -8, i32 -10>, <2 x i32>* %vector_ptr.2, align 8
+  ret i32 0
+}
+
+; The instructions seem to be in a different order in the .s file than
+; the corresponding values in the .ll file, so just run the test three
+; times and each time test for a different instruction.
+; CHECK-TEST1: combine(#-2, #3)
+; CHECK-TEST2: combine(#6, #-4)
+; CHECK-TEST3: combine(#-10, #-8)
+
+attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
diff --git a/llvm/test/CodeGen/Hexagon/constp-ctb.ll b/llvm/test/CodeGen/Hexagon/constp-ctb.ll
new file mode 100644
index 0000000..76a9820
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/constp-ctb.ll
@@ -0,0 +1,26 @@
+; RUN: llc < %s
+; REQUIRES: asserts
+
+target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-v32:32-n16:32"
+target triple = "hexagon-unknown--elf"
+
+; Function Attrs: nounwind readnone
+define i64 @foo() #0 {
+entry:
+  %0 = tail call i32 @llvm.hexagon.S2.ct0p(i64 18)
+  %1 = tail call i32 @llvm.hexagon.S2.ct1p(i64 27)
+  %2 = tail call i64 @llvm.hexagon.A2.combinew(i32 %0, i32 %1)
+  ret i64 %2
+}
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.hexagon.S2.ct0p(i64) #0
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.hexagon.S2.ct1p(i64) #0
+
+; Function Attrs: nounwind readnone
+declare i64 @llvm.hexagon.A2.combinew(i32, i32) #0
+
+attributes #0 = { nounwind readnone }
+
diff --git a/llvm/test/CodeGen/Hexagon/constp-extract.ll b/llvm/test/CodeGen/Hexagon/constp-extract.ll
new file mode 100644
index 0000000..00f1763
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/constp-extract.ll
@@ -0,0 +1,31 @@
+; Expect the constant propagation to evaluate signed and unsigned bit extract.
+; RUN: llc -march=hexagon -O2 < %s | FileCheck %s
+
+target triple = "hexagon"
+
+@x = common global i32 0, align 4
+@y = common global i32 0, align 4
+
+define void @foo() #0 {
+entry:
+  ; extractu(0x000ABCD0, 16, 4)
+  ; should evaluate to 0xABCD (dec 43981)
+  %0 = call i32 @llvm.hexagon.S2.extractu(i32 703696, i32 16, i32 4)
+; CHECK: 43981
+; CHECK-NOT: extractu
+  store i32 %0, i32* @x, align 4
+  ; extract(0x000ABCD0, 16, 4)
+  ; should evaluate to 0xFFFFABCD (dec 4294945741 or -21555)
+  %1 = call i32 @llvm.hexagon.S4.extract(i32 703696, i32 16, i32 4)
+; CHECK: -21555
+; CHECK-NOT: extract
+  store i32 %1, i32* @y, align 4
+  ret void
+}
+
+declare i32 @llvm.hexagon.S2.extractu(i32, i32, i32) #1
+
+declare i32 @llvm.hexagon.S4.extract(i32, i32, i32) #1
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
diff --git a/llvm/test/CodeGen/Hexagon/constp-physreg.ll b/llvm/test/CodeGen/Hexagon/constp-physreg.ll
new file mode 100644
index 0000000..0473b96
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/constp-physreg.ll
@@ -0,0 +1,21 @@
+; RUN: llc -O2 -march hexagon < %s
+target datalayout = "e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-f64:64:64-f32:32:32-v64:64:64-v32:32:32-a0:0-n16:32"
+target triple = "hexagon"
+
+define signext i16 @foo(i16 signext %var1, i16 signext %var2) #0 {
+entry:
+  %0 = or i16 %var2, %var1
+  %1 = icmp slt i16 %0, 0
+  %cmp8 = icmp sgt i16 %var1, %var2
+  %or.cond19 = or i1 %1, %cmp8
+  br i1 %or.cond19, label %return, label %if.end
+
+if.end:                                           ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %if.end, %if.end15, %entry
+  %retval.0.reg2mem.0 = phi i16 [ 0, %entry ], [ 32767, %if.end ]
+  ret i16 %retval.0.reg2mem.0
+}
+
+attributes #0 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/llvm/test/CodeGen/Hexagon/constp-rewrite-branches.ll b/llvm/test/CodeGen/Hexagon/constp-rewrite-branches.ll
new file mode 100644
index 0000000..dfac49c
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/constp-rewrite-branches.ll
@@ -0,0 +1,17 @@
+; RUN: llc -O2 -march hexagon < %s | FileCheck %s
+
+define i32 @foo(i32 %x) {
+  %p = icmp eq i32 %x, 0
+  br i1 %p, label %zero, label %nonzero
+nonzero:
+  %v1 = add i32 %x, 1
+  %c = icmp eq i32 %x, %v1
+; This branch will be rewritten by HCP.  A bug would cause both branches to
+; go away, leaving no path to "ret -1".
+  br i1 %c, label %zero, label %other
+zero:
+  ret i32 0
+other:
+; CHECK: -1
+  ret i32 -1
+}
diff --git a/llvm/test/CodeGen/Hexagon/constp-rseq.ll b/llvm/test/CodeGen/Hexagon/constp-rseq.ll
new file mode 100644
index 0000000..c89407e
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/constp-rseq.ll
@@ -0,0 +1,19 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+; CHECK: cmp
+; Make sure that the result is not a compile-time constant.
+
+define i64 @foo(i32 %x) {
+entry:
+  %c = icmp slt i32 %x, 17
+  br i1 %c, label %b1, label %b2
+b1:
+  br label %b2
+b2:
+  %p = phi i32 [ 1, %entry ], [ 0, %b1 ]
+  %q = sub i32 %x, %x
+  %y = zext i32 %q to i64
+  %u = shl i64 %y, 32
+  %v = zext i32 %p to i64
+  %w = or i64 %u, %v
+  ret i64 %w
+}
diff --git a/llvm/test/CodeGen/Hexagon/constp-vsplat.ll b/llvm/test/CodeGen/Hexagon/constp-vsplat.ll
new file mode 100644
index 0000000..6063383
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/constp-vsplat.ll
@@ -0,0 +1,18 @@
+; RUN: llc < %s
+; REQUIRES: asserts
+target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-v32:32-n16:32"
+target triple = "hexagon"
+
+; Function Attrs: nounwind readnone
+define i64 @foo() #0 {
+entry:
+  %0 = tail call i32 @llvm.hexagon.S2.vsplatrb(i32 255)
+  %conv = zext i32 %0 to i64
+  %shl = shl nuw i64 %conv, 32
+  %or = or i64 %shl, %conv
+  ret i64 %or
+}
+
+declare i32 @llvm.hexagon.S2.vsplatrb(i32) #0
+
+attributes #0 = { nounwind readnone }
diff --git a/llvm/test/CodeGen/Hexagon/vect/vect-vsplatb.ll b/llvm/test/CodeGen/Hexagon/vect/vect-vsplatb.ll
index 6996dd1..097e2cc 100644
--- a/llvm/test/CodeGen/Hexagon/vect/vect-vsplatb.ll
+++ b/llvm/test/CodeGen/Hexagon/vect/vect-vsplatb.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=hexagon < %s | FileCheck %s
+; RUN: llc -march=hexagon -disable-hcp < %s | FileCheck %s
 ; Make sure we build the constant vector <7, 7, 7, 7> with a vsplatb.
 ; CHECK: vsplatb
 @B = common global [400 x i8] zeroinitializer, align 8
diff --git a/llvm/test/CodeGen/Hexagon/vect/vect-vsplath.ll b/llvm/test/CodeGen/Hexagon/vect/vect-vsplath.ll
index f520710..db90bf4 100644
--- a/llvm/test/CodeGen/Hexagon/vect/vect-vsplath.ll
+++ b/llvm/test/CodeGen/Hexagon/vect/vect-vsplath.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=hexagon < %s | FileCheck %s
+; RUN: llc -march=hexagon -disable-hcp < %s | FileCheck %s
 ; Make sure we build the constant vector <7, 7, 7, 7> with a vsplath.
 ; CHECK: vsplath
 @B = common global [400 x i16] zeroinitializer, align 8