1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -aggressive-instcombine -S | FileCheck %s
3 ; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
4 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
6 ; Aggressive Instcombine should be able to reduce width of these constant
7 ; expressions, without crashing.
9 declare i32 @use32(i32)
10 declare <2 x i32> @use32_vec(<2 x i32>)
11 declare <vscale x 2 x i32> @use32_scale_vec(<vscale x 2 x i32>)
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14 ;; These tests check cases where expression dag post-dominated by TruncInst
15 ;; contains instruction, which has more than one usage.
16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18 define void @const_expression_mul() {
19 ; CHECK-LABEL: @const_expression_mul(
20 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use32(i32 242)
21 ; CHECK-NEXT: ret void
24 %T = trunc i64 %A to i32
25 call i32 @use32(i32 %T)
29 define void @const_expression_zext() {
30 ; CHECK-LABEL: @const_expression_zext(
31 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use32(i32 33)
32 ; CHECK-NEXT: ret void
34 %A = zext i32 33 to i64
35 %T = trunc i64 %A to i32
36 call i32 @use32(i32 %T)
40 define void @const_expression_trunc() {
41 ; CHECK-LABEL: @const_expression_trunc(
42 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use32(i32 44)
43 ; CHECK-NEXT: ret void
45 %T = trunc i64 44 to i32
46 call i32 @use32(i32 %T)
50 ; Check that we handle constant expression trunc instruction, when it is a leaf
51 ; of other trunc expression pattern:
52 ; 1. %T1 is the constant expression trunc instruction.
53 ; 2. %T2->%T1 is the trunc expression pattern we want to reduce.
54 define void @const_expression_trunc_leaf() {
55 ; CHECK-LABEL: @const_expression_trunc_leaf(
56 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use32(i32 44)
57 ; CHECK-NEXT: ret void
59 %T1 = trunc i64 44 to i48
60 %T2 = trunc i48 %T1 to i32
61 call i32 @use32(i32 %T2)
65 ; Check that we handle zext instruction, which turns into trunc instruction.
66 ; Notice that there are two expression patterns below:
68 ; 2. %T1`->%A (where %T1` is the reduced node of %T1 into trunc instruction)
69 define void @const_expression_zext_to_trunc() {
70 ; CHECK-LABEL: @const_expression_zext_to_trunc(
71 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use32(i32 44)
72 ; CHECK-NEXT: ret void
75 %T1 = zext i64 %A to i128
76 %T2 = trunc i128 %T1 to i32
77 call i32 @use32(i32 %T2)
81 define void @const_expression_mul_vec() {
82 ; CHECK-LABEL: @const_expression_mul_vec(
83 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @use32_vec(<2 x i32> <i32 24531, i32 24864>)
84 ; CHECK-NEXT: ret void
86 %A = mul <2 x i64> <i64 111, i64 112>, <i64 221, i64 222>
87 %T = trunc <2 x i64> %A to <2 x i32>
88 call <2 x i32> @use32_vec(<2 x i32> %T)
92 define void @const_expression_zext_vec() {
93 ; CHECK-LABEL: @const_expression_zext_vec(
94 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @use32_vec(<2 x i32> <i32 331, i32 332>)
95 ; CHECK-NEXT: ret void
97 %A = zext <2 x i32> <i32 331, i32 332> to <2 x i64>
98 %T = trunc <2 x i64> %A to <2 x i32>
99 call <2 x i32> @use32_vec(<2 x i32> %T)
103 define void @const_expression_trunc_vec() {
104 ; CHECK-LABEL: @const_expression_trunc_vec(
105 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @use32_vec(<2 x i32> <i32 551, i32 552>)
106 ; CHECK-NEXT: ret void
108 %T = trunc <2 x i64> <i64 551, i64 552> to <2 x i32>
109 call <2 x i32> @use32_vec(<2 x i32> %T)
113 define void @const_expression_mul_scale_vec() {
114 ; CHECK-LABEL: @const_expression_mul_scale_vec(
115 ; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i32> @use32_scale_vec(<vscale x 2 x i32> zeroinitializer)
116 ; CHECK-NEXT: ret void
118 %A = mul <vscale x 2 x i64> zeroinitializer, zeroinitializer
119 %T = trunc <vscale x 2 x i64> %A to <vscale x 2 x i32>
120 call <vscale x 2 x i32> @use32_scale_vec(<vscale x 2 x i32> %T)
124 define void @const_expression_zext_scale_vec() {
125 ; CHECK-LABEL: @const_expression_zext_scale_vec(
126 ; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i32> @use32_scale_vec(<vscale x 2 x i32> zeroinitializer)
127 ; CHECK-NEXT: ret void
129 %A = zext <vscale x 2 x i32> zeroinitializer to <vscale x 2 x i64>
130 %T = trunc <vscale x 2 x i64> %A to <vscale x 2 x i32>
131 call <vscale x 2 x i32> @use32_scale_vec(<vscale x 2 x i32> %T)
135 define void @const_expression_trunc_scale_vec() {
136 ; CHECK-LABEL: @const_expression_trunc_scale_vec(
137 ; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i32> @use32_scale_vec(<vscale x 2 x i32> zeroinitializer)
138 ; CHECK-NEXT: ret void
140 %T = trunc <vscale x 2 x i64> zeroinitializer to <vscale x 2 x i32>
141 call <vscale x 2 x i32> @use32_scale_vec(<vscale x 2 x i32> %T)