load-combine.ll 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. ; RUN: opt < %s -load-combine -instcombine -S | FileCheck %s
  2. target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
  3. target triple = "x86_64-unknown-linux-gnu"
  4. ; Combine read from char* idiom.
  5. define i64 @LoadU64_x64_0(i64* %pData) {
  6. %1 = bitcast i64* %pData to i8*
  7. %2 = load i8, i8* %1, align 1
  8. %3 = zext i8 %2 to i64
  9. %4 = shl nuw i64 %3, 56
  10. %5 = getelementptr inbounds i8, i8* %1, i64 1
  11. %6 = load i8, i8* %5, align 1
  12. %7 = zext i8 %6 to i64
  13. %8 = shl nuw nsw i64 %7, 48
  14. %9 = or i64 %8, %4
  15. %10 = getelementptr inbounds i8, i8* %1, i64 2
  16. %11 = load i8, i8* %10, align 1
  17. %12 = zext i8 %11 to i64
  18. %13 = shl nuw nsw i64 %12, 40
  19. %14 = or i64 %9, %13
  20. %15 = getelementptr inbounds i8, i8* %1, i64 3
  21. %16 = load i8, i8* %15, align 1
  22. %17 = zext i8 %16 to i64
  23. %18 = shl nuw nsw i64 %17, 32
  24. %19 = or i64 %14, %18
  25. %20 = getelementptr inbounds i8, i8* %1, i64 4
  26. %21 = load i8, i8* %20, align 1
  27. %22 = zext i8 %21 to i64
  28. %23 = shl nuw nsw i64 %22, 24
  29. %24 = or i64 %19, %23
  30. %25 = getelementptr inbounds i8, i8* %1, i64 5
  31. %26 = load i8, i8* %25, align 1
  32. %27 = zext i8 %26 to i64
  33. %28 = shl nuw nsw i64 %27, 16
  34. %29 = or i64 %24, %28
  35. %30 = getelementptr inbounds i8, i8* %1, i64 6
  36. %31 = load i8, i8* %30, align 1
  37. %32 = zext i8 %31 to i64
  38. %33 = shl nuw nsw i64 %32, 8
  39. %34 = or i64 %29, %33
  40. %35 = getelementptr inbounds i8, i8* %1, i64 7
  41. %36 = load i8, i8* %35, align 1
  42. %37 = zext i8 %36 to i64
  43. %38 = or i64 %34, %37
  44. ret i64 %38
  45. ; CHECK-LABEL: @LoadU64_x64_0(
  46. ; CHECK: load i64, i64* %{{.*}}, align 1
  47. ; CHECK-NOT: load
  48. }
  49. ; Combine simple adjacent loads.
  50. define i32 @"2xi16_i32"(i16* %x) {
  51. %1 = load i16, i16* %x, align 2
  52. %2 = getelementptr inbounds i16, i16* %x, i64 1
  53. %3 = load i16, i16* %2, align 2
  54. %4 = zext i16 %3 to i32
  55. %5 = shl nuw i32 %4, 16
  56. %6 = zext i16 %1 to i32
  57. %7 = or i32 %5, %6
  58. ret i32 %7
  59. ; CHECK-LABEL: @"2xi16_i32"(
  60. ; CHECK: load i32, i32* %{{.*}}, align 2
  61. ; CHECK-NOT: load
  62. }
  63. ; Don't combine loads across stores.
  64. define i32 @"2xi16_i32_store"(i16* %x, i16* %y) {
  65. %1 = load i16, i16* %x, align 2
  66. store i16 0, i16* %y, align 2
  67. %2 = getelementptr inbounds i16, i16* %x, i64 1
  68. %3 = load i16, i16* %2, align 2
  69. %4 = zext i16 %3 to i32
  70. %5 = shl nuw i32 %4, 16
  71. %6 = zext i16 %1 to i32
  72. %7 = or i32 %5, %6
  73. ret i32 %7
  74. ; CHECK-LABEL: @"2xi16_i32_store"(
  75. ; CHECK: load i16, i16* %{{.*}}, align 2
  76. ; CHECK: store
  77. ; CHECK: load i16, i16* %{{.*}}, align 2
  78. }
  79. ; Don't combine loads with a gap.
  80. define i32 @"2xi16_i32_gap"(i16* %x) {
  81. %1 = load i16, i16* %x, align 2
  82. %2 = getelementptr inbounds i16, i16* %x, i64 2
  83. %3 = load i16, i16* %2, align 2
  84. %4 = zext i16 %3 to i32
  85. %5 = shl nuw i32 %4, 16
  86. %6 = zext i16 %1 to i32
  87. %7 = or i32 %5, %6
  88. ret i32 %7
  89. ; CHECK-LABEL: @"2xi16_i32_gap"(
  90. ; CHECK: load i16, i16* %{{.*}}, align 2
  91. ; CHECK: load i16, i16* %{{.*}}, align 2
  92. }
  93. ; Combine out of order loads.
  94. define i32 @"2xi16_i32_order"(i16* %x) {
  95. %1 = getelementptr inbounds i16, i16* %x, i64 1
  96. %2 = load i16, i16* %1, align 2
  97. %3 = zext i16 %2 to i32
  98. %4 = load i16, i16* %x, align 2
  99. %5 = shl nuw i32 %3, 16
  100. %6 = zext i16 %4 to i32
  101. %7 = or i32 %5, %6
  102. ret i32 %7
  103. ; CHECK-LABEL: @"2xi16_i32_order"(
  104. ; CHECK: load i32, i32* %{{.*}}, align 2
  105. ; CHECK-NOT: load
  106. }
  107. ; Overlapping loads.
  108. define i32 @"2xi16_i32_overlap"(i8* %x) {
  109. %1 = bitcast i8* %x to i16*
  110. %2 = load i16, i16* %1, align 2
  111. %3 = getelementptr inbounds i8, i8* %x, i64 1
  112. %4 = bitcast i8* %3 to i16*
  113. %5 = load i16, i16* %4, align 2
  114. %6 = zext i16 %5 to i32
  115. %7 = shl nuw i32 %6, 16
  116. %8 = zext i16 %2 to i32
  117. %9 = or i32 %7, %8
  118. ret i32 %9
  119. ; CHECK-LABEL: @"2xi16_i32_overlap"(
  120. ; CHECK: load i16, i16* %{{.*}}, align 2
  121. ; CHECK: load i16, i16* %{{.*}}, align 2
  122. }
  123. ; Combine valid alignments.
  124. define i64 @"2xi16_i64_align"(i8* %x) {
  125. %1 = bitcast i8* %x to i32*
  126. %2 = load i32, i32* %1, align 4
  127. %3 = getelementptr inbounds i8, i8* %x, i64 4
  128. %4 = bitcast i8* %3 to i16*
  129. %5 = load i16, i16* %4, align 2
  130. %6 = getelementptr inbounds i8, i8* %x, i64 6
  131. %7 = bitcast i8* %6 to i16*
  132. %8 = load i16, i16* %7, align 2
  133. %9 = zext i16 %8 to i64
  134. %10 = shl nuw i64 %9, 48
  135. %11 = zext i16 %5 to i64
  136. %12 = shl nuw nsw i64 %11, 32
  137. %13 = zext i32 %2 to i64
  138. %14 = or i64 %12, %13
  139. %15 = or i64 %14, %10
  140. ret i64 %15
  141. ; CHECK-LABEL: @"2xi16_i64_align"(
  142. ; CHECK: load i64, i64* %{{.*}}, align 4
  143. }
  144. ; Non power of two.
  145. define i64 @"2xi16_i64_npo2"(i8* %x) {
  146. %1 = load i8, i8* %x, align 1
  147. %2 = zext i8 %1 to i64
  148. %3 = getelementptr inbounds i8, i8* %x, i64 1
  149. %4 = load i8, i8* %3, align 1
  150. %5 = zext i8 %4 to i64
  151. %6 = shl nuw nsw i64 %5, 8
  152. %7 = or i64 %6, %2
  153. %8 = getelementptr inbounds i8, i8* %x, i64 2
  154. %9 = load i8, i8* %8, align 1
  155. %10 = zext i8 %9 to i64
  156. %11 = shl nuw nsw i64 %10, 16
  157. %12 = or i64 %11, %7
  158. %13 = getelementptr inbounds i8, i8* %x, i64 3
  159. %14 = load i8, i8* %13, align 1
  160. %15 = zext i8 %14 to i64
  161. %16 = shl nuw nsw i64 %15, 24
  162. %17 = or i64 %16, %12
  163. %18 = getelementptr inbounds i8, i8* %x, i64 4
  164. %19 = load i8, i8* %18, align 1
  165. %20 = zext i8 %19 to i64
  166. %21 = shl nuw nsw i64 %20, 32
  167. %22 = or i64 %21, %17
  168. %23 = getelementptr inbounds i8, i8* %x, i64 5
  169. %24 = load i8, i8* %23, align 1
  170. %25 = zext i8 %24 to i64
  171. %26 = shl nuw nsw i64 %25, 40
  172. %27 = or i64 %26, %22
  173. %28 = getelementptr inbounds i8, i8* %x, i64 6
  174. %29 = load i8, i8* %28, align 1
  175. %30 = zext i8 %29 to i64
  176. %31 = shl nuw nsw i64 %30, 48
  177. %32 = or i64 %31, %27
  178. ret i64 %32
  179. ; CHECK-LABEL: @"2xi16_i64_npo2"(
  180. ; CHECK: load i32, i32* %{{.*}}, align 1
  181. }