[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / AggressiveInstCombine / trunc_const_expr.ll
blob32f323602498dfcc40e6875acb7e4d746acbb778
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
23   %A = mul i64 11, 22
24   %T = trunc i64 %A to i32
25   call i32 @use32(i32 %T)
26   ret void
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)
37   ret void
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)
47   ret void
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)
62   ret void
65 ; Check that we handle zext instruction, which turns into trunc instruction.
66 ; Notice that there are two expression patterns below:
67 ; 1. %T2->%T1
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
74   %A = add i64 11, 33
75   %T1 = zext i64 %A to i128
76   %T2 = trunc i128 %T1 to i32
77   call i32 @use32(i32 %T2)
78   ret void
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)
89   ret void
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)
100   ret void
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)
110   ret void
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)
121   ret void
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)
132   ret void
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)
142   ret void