Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=ENABLED
      2 ; RUN: llc --disable-x86-lea-opt < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=DISABLED
      3 
      4 %struct.anon1 = type { i32, i32, i32 }
      5 %struct.anon2 = type { i32, [32 x i32], i32 }
      6 
      7 @arr1 = external global [65 x %struct.anon1], align 16
      8 @arr2 = external global [65 x %struct.anon2], align 16
      9 
     10 define void @test1(i64 %x) nounwind {
     11 entry:
     12   %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
     13   %tmp = load i32, i32* %a, align 4
     14   %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
     15   %tmp1 = load i32, i32* %b, align 4
     16   %sub = sub i32 %tmp, %tmp1
     17   %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
     18   %tmp2 = load i32, i32* %c, align 4
     19   %add = add nsw i32 %sub, %tmp2
     20   switch i32 %add, label %sw.epilog [
     21     i32 1, label %sw.bb.1
     22     i32 2, label %sw.bb.2
     23   ]
     24 
     25 sw.bb.1:                                          ; preds = %entry
     26   store i32 111, i32* %b, align 4
     27   store i32 222, i32* %c, align 4
     28   br label %sw.epilog
     29 
     30 sw.bb.2:                                          ; preds = %entry
     31   store i32 333, i32* %b, align 4
     32   store i32 444, i32* %c, align 4
     33   br label %sw.epilog
     34 
     35 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
     36   ret void
     37 ; CHECK-LABEL: test1:
     38 ; CHECK:	shlq $2, [[REG1:%[a-z]+]]
     39 ; CHECK:	movl arr1([[REG1]],[[REG1]],2), {{.*}}
     40 ; CHECK:	leaq arr1+4([[REG1]],[[REG1]],2), [[REG2:%[a-z]+]]
     41 ; CHECK:	subl arr1+4([[REG1]],[[REG1]],2), {{.*}}
     42 ; DISABLED:	leaq arr1+8([[REG1]],[[REG1]],2), [[REG3:%[a-z]+]]
     43 ; CHECK:	addl arr1+8([[REG1]],[[REG1]],2), {{.*}}
     44 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
     45 ; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
     46 ; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
     47 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
     48 ; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
     49 ; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
     50 }
     51 
     52 define void @test2(i64 %x) nounwind optsize {
     53 entry:
     54   %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
     55   %tmp = load i32, i32* %a, align 4
     56   %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
     57   %tmp1 = load i32, i32* %b, align 4
     58   %sub = sub i32 %tmp, %tmp1
     59   %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
     60   %tmp2 = load i32, i32* %c, align 4
     61   %add = add nsw i32 %sub, %tmp2
     62   switch i32 %add, label %sw.epilog [
     63     i32 1, label %sw.bb.1
     64     i32 2, label %sw.bb.2
     65   ]
     66 
     67 sw.bb.1:                                          ; preds = %entry
     68   store i32 111, i32* %b, align 4
     69   store i32 222, i32* %c, align 4
     70   br label %sw.epilog
     71 
     72 sw.bb.2:                                          ; preds = %entry
     73   store i32 333, i32* %b, align 4
     74   store i32 444, i32* %c, align 4
     75   br label %sw.epilog
     76 
     77 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
     78   ret void
     79 ; CHECK-LABEL: test2:
     80 ; CHECK:	shlq $2, [[REG1:%[a-z]+]]
     81 ; DISABLED:	movl arr1([[REG1]],[[REG1]],2), {{.*}}
     82 ; CHECK:	leaq arr1+4([[REG1]],[[REG1]],2), [[REG2:%[a-z]+]]
     83 ; ENABLED:	movl -4([[REG2]]), {{.*}}
     84 ; ENABLED:	subl ([[REG2]]), {{.*}}
     85 ; ENABLED:	addl 4([[REG2]]), {{.*}}
     86 ; DISABLED:	subl arr1+4([[REG1]],[[REG1]],2), {{.*}}
     87 ; DISABLED:	leaq arr1+8([[REG1]],[[REG1]],2), [[REG3:%[a-z]+]]
     88 ; DISABLED:	addl arr1+8([[REG1]],[[REG1]],2), {{.*}}
     89 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
     90 ; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
     91 ; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
     92 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
     93 ; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
     94 ; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
     95 }
     96 
     97 ; Check that LEA optimization pass takes into account a resultant address
     98 ; displacement when choosing a LEA instruction for replacing a redundant
     99 ; address recalculation.
    100 
    101 define void @test3(i64 %x) nounwind optsize {
    102 entry:
    103   %a = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 2
    104   %tmp = load i32, i32* %a, align 4
    105   %b = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 0
    106   %tmp1 = load i32, i32* %b, align 4
    107   %add = add nsw i32 %tmp, %tmp1
    108   switch i32 %add, label %sw.epilog [
    109     i32 1, label %sw.bb.1
    110     i32 2, label %sw.bb.2
    111   ]
    112 
    113 sw.bb.1:                                          ; preds = %entry
    114   store i32 111, i32* %a, align 4
    115   store i32 222, i32* %b, align 4
    116   br label %sw.epilog
    117 
    118 sw.bb.2:                                          ; preds = %entry
    119   store i32 333, i32* %a, align 4
    120   ; Make sure the REG3's definition LEA won't be removed as redundant.
    121   %cvt = ptrtoint i32* %b to i32
    122   store i32 %cvt, i32* %b, align 4
    123   br label %sw.epilog
    124 
    125 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
    126   ret void
    127 ; CHECK-LABEL: test3:
    128 ; CHECK:	imulq {{.*}}, [[REG1:%[a-z]+]]
    129 ; CHECK:	leaq arr2+132([[REG1]]), [[REG2:%[a-z]+]]
    130 ; CHECK:	leaq arr2([[REG1]]), [[REG3:%[a-z]+]]
    131 
    132 ; REG3's definition is closer to movl than REG2's, but the pass still chooses
    133 ; REG2 because it provides the resultant address displacement fitting 1 byte.
    134 
    135 ; ENABLED:	movl ([[REG2]]), {{.*}}
    136 ; ENABLED:	addl ([[REG3]]), {{.*}}
    137 ; DISABLED:	movl arr2+132([[REG1]]), {{.*}}
    138 ; DISABLED:	addl arr2([[REG1]]), {{.*}}
    139 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
    140 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
    141 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
    142 ; CHECK:	movl {{.*}}, ([[REG3]])
    143 }
    144 
    145 define void @test4(i64 %x) nounwind minsize {
    146 entry:
    147   %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
    148   %tmp = load i32, i32* %a, align 4
    149   %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
    150   %tmp1 = load i32, i32* %b, align 4
    151   %sub = sub i32 %tmp, %tmp1
    152   %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
    153   %tmp2 = load i32, i32* %c, align 4
    154   %add = add nsw i32 %sub, %tmp2
    155   switch i32 %add, label %sw.epilog [
    156     i32 1, label %sw.bb.1
    157     i32 2, label %sw.bb.2
    158   ]
    159 
    160 sw.bb.1:                                          ; preds = %entry
    161   store i32 111, i32* %b, align 4
    162   store i32 222, i32* %c, align 4
    163   br label %sw.epilog
    164 
    165 sw.bb.2:                                          ; preds = %entry
    166   store i32 333, i32* %b, align 4
    167   store i32 444, i32* %c, align 4
    168   br label %sw.epilog
    169 
    170 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
    171   ret void
    172 ; CHECK-LABEL: test4:
    173 ; CHECK:	imulq {{.*}}, [[REG1:%[a-z]+]]
    174 ; DISABLED:	movl arr1([[REG1]]), {{.*}}
    175 ; CHECK:	leaq arr1+4([[REG1]]), [[REG2:%[a-z]+]]
    176 ; ENABLED:	movl -4([[REG2]]), {{.*}}
    177 ; ENABLED:	subl ([[REG2]]), {{.*}}
    178 ; ENABLED:	addl 4([[REG2]]), {{.*}}
    179 ; DISABLED:	subl arr1+4([[REG1]]), {{.*}}
    180 ; DISABLED:	leaq arr1+8([[REG1]]), [[REG3:%[a-z]+]]
    181 ; DISABLED:	addl arr1+8([[REG1]]), {{.*}}
    182 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
    183 ; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
    184 ; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
    185 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
    186 ; ENABLED:	movl ${{[1-4]+}}, 4([[REG2]])
    187 ; DISABLED:	movl ${{[1-4]+}}, ([[REG3]])
    188 }
    189