Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s -mtriple=x86_64-linux -enable-x86-lea-opt | FileCheck %s
      2 
      3 %struct.anon1 = type { i32, i32, i32 }
      4 %struct.anon2 = type { i32, [32 x i32], i32 }
      5 
      6 @arr1 = external global [65 x %struct.anon1], align 16
      7 @arr2 = external global [65 x %struct.anon2], align 16
      8 
      9 define void @test1(i64 %x) nounwind {
     10 entry:
     11   %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
     12   %tmp = load i32, i32* %a, align 4
     13   %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
     14   %tmp1 = load i32, i32* %b, align 4
     15   %sub = sub i32 %tmp, %tmp1
     16   %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
     17   %tmp2 = load i32, i32* %c, align 4
     18   %add = add nsw i32 %sub, %tmp2
     19   switch i32 %add, label %sw.epilog [
     20     i32 1, label %sw.bb.1
     21     i32 2, label %sw.bb.2
     22   ]
     23 
     24 sw.bb.1:                                          ; preds = %entry
     25   store i32 111, i32* %b, align 4
     26   store i32 222, i32* %c, align 4
     27   br label %sw.epilog
     28 
     29 sw.bb.2:                                          ; preds = %entry
     30   store i32 333, i32* %b, align 4
     31   store i32 444, i32* %c, align 4
     32   br label %sw.epilog
     33 
     34 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
     35   ret void
     36 ; CHECK-LABEL: test1:
     37 ; CHECK:	leaq (%rdi,%rdi,2), [[REG1:%[a-z]+]]
     38 ; CHECK:	movl arr1(,[[REG1]],4), {{.*}}
     39 ; CHECK:	leaq arr1+4(,[[REG1]],4), [[REG2:%[a-z]+]]
     40 ; CHECK:	subl arr1+4(,[[REG1]],4), {{.*}}
     41 ; CHECK:	leaq arr1+8(,[[REG1]],4), [[REG3:%[a-z]+]]
     42 ; CHECK:	addl arr1+8(,[[REG1]],4), {{.*}}
     43 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
     44 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
     45 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
     46 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
     47 }
     48 
     49 define void @test2(i64 %x) nounwind optsize {
     50 entry:
     51   %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0
     52   %tmp = load i32, i32* %a, align 4
     53   %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1
     54   %tmp1 = load i32, i32* %b, align 4
     55   %sub = sub i32 %tmp, %tmp1
     56   %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2
     57   %tmp2 = load i32, i32* %c, align 4
     58   %add = add nsw i32 %sub, %tmp2
     59   switch i32 %add, label %sw.epilog [
     60     i32 1, label %sw.bb.1
     61     i32 2, label %sw.bb.2
     62   ]
     63 
     64 sw.bb.1:                                          ; preds = %entry
     65   store i32 111, i32* %b, align 4
     66   store i32 222, i32* %c, align 4
     67   br label %sw.epilog
     68 
     69 sw.bb.2:                                          ; preds = %entry
     70   store i32 333, i32* %b, align 4
     71   store i32 444, i32* %c, align 4
     72   br label %sw.epilog
     73 
     74 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
     75   ret void
     76 ; CHECK-LABEL: test2:
     77 ; CHECK:	leaq (%rdi,%rdi,2), [[REG1:%[a-z]+]]
     78 ; CHECK:	leaq arr1+4(,[[REG1]],4), [[REG2:%[a-z]+]]
     79 ; CHECK:	movl -4([[REG2]]), {{.*}}
     80 ; CHECK:	subl ([[REG2]]), {{.*}}
     81 ; CHECK:	leaq arr1+8(,[[REG1]],4), [[REG3:%[a-z]+]]
     82 ; CHECK:	addl ([[REG3]]), {{.*}}
     83 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
     84 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
     85 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
     86 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
     87 }
     88 
     89 ; Check that LEA optimization pass takes into account a resultant address
     90 ; displacement when choosing a LEA instruction for replacing a redundant
     91 ; address recalculation.
     92 
     93 define void @test3(i64 %x) nounwind optsize {
     94 entry:
     95   %a = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 2
     96   %tmp = load i32, i32* %a, align 4
     97   %b = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 0
     98   %tmp1 = load i32, i32* %b, align 4
     99   %add = add nsw i32 %tmp, %tmp1
    100   switch i32 %add, label %sw.epilog [
    101     i32 1, label %sw.bb.1
    102     i32 2, label %sw.bb.2
    103   ]
    104 
    105 sw.bb.1:                                          ; preds = %entry
    106   store i32 111, i32* %a, align 4
    107   store i32 222, i32* %b, align 4
    108   br label %sw.epilog
    109 
    110 sw.bb.2:                                          ; preds = %entry
    111   store i32 333, i32* %a, align 4
    112   store i32 444, i32* %b, align 4
    113   br label %sw.epilog
    114 
    115 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
    116   ret void
    117 ; CHECK-LABEL: test3:
    118 ; CHECK:	imulq {{.*}}, [[REG1:%[a-z]+]]
    119 ; CHECK:	leaq arr2+132([[REG1]]), [[REG2:%[a-z]+]]
    120 ; CHECK:	leaq arr2([[REG1]]), [[REG3:%[a-z]+]]
    121 
    122 ; REG3's definition is closer to movl than REG2's, but the pass still chooses
    123 ; REG2 because it provides the resultant address displacement fitting 1 byte.
    124 
    125 ; CHECK:	movl ([[REG2]]), {{.*}}
    126 ; CHECK:	addl ([[REG3]]), {{.*}}
    127 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
    128 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
    129 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
    130 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
    131 }
    132