instcombine-phi.ll 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. ; RUN: opt -instcombine -S < %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. ; If all the operands to a phi node are of the same operation, instcombine
  5. ; will try to pull them through the phi node, combining them into a single
  6. ; operation. Check that when it does this the combined operation has a merged
  7. ; debug location.
  8. ; Test folding of a binary operation. Generated from source:
  9. ; extern int foo(void);
  10. ; extern int bar(void);
  11. ;
  12. ; int binop(int a, int b) {
  13. ; if(a)
  14. ; b -= foo();
  15. ; else
  16. ; b -= bar();
  17. ; return b;
  18. ; }
  19. ; CHECK: define i32 @binop
  20. ; CHECK-LABEL: if.end:
  21. ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
  22. ; CHECK: sub nsw i32 %b, %[[PHI]], !dbg [[binopMergedLoc:![0-9]+]]
  23. ; CHECK: ret i32
  24. define i32 @binop(i32 %a, i32 %b) !dbg !6 {
  25. entry:
  26. %tobool = icmp ne i32 %a, 0, !dbg !8
  27. br i1 %tobool, label %if.then, label %if.else, !dbg !8
  28. if.then: ; preds = %entry
  29. %call = call i32 @foo(), !dbg !9
  30. %sub = sub nsw i32 %b, %call, !dbg !10
  31. br label %if.end, !dbg !11
  32. if.else: ; preds = %entry
  33. %call1 = call i32 @bar(), !dbg !12
  34. %sub2 = sub nsw i32 %b, %call1, !dbg !13
  35. br label %if.end
  36. if.end: ; preds = %if.else, %if.then
  37. %b.addr.0 = phi i32 [ %sub, %if.then ], [ %sub2, %if.else ]
  38. ret i32 %b.addr.0, !dbg !14
  39. }
  40. ; Test folding of a compare. Generated from source (with editing to
  41. ; common the zext):
  42. ; extern int foo(void);
  43. ; extern int bar(void);
  44. ;
  45. ; int cmp(int a, int b) {
  46. ; int r;
  47. ; if(a)
  48. ; r = foo() < b;
  49. ; else
  50. ; r = bar() < b;
  51. ; return r;
  52. ; }
  53. ; CHECK: define i32 @cmp
  54. ; CHECK-LABEL: if.end:
  55. ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
  56. ; CHECK: icmp slt i32 %[[PHI]], %b, !dbg [[cmpMergedLoc:![0-9]+]]
  57. ; CHECK: ret i32
  58. define i32 @cmp(i32 %a, i32 %b) !dbg !15 {
  59. entry:
  60. %tobool = icmp ne i32 %a, 0, !dbg !16
  61. br i1 %tobool, label %if.then, label %if.else, !dbg !16
  62. if.then: ; preds = %entry
  63. %call = call i32 @foo(), !dbg !17
  64. %cmp = icmp slt i32 %call, %b, !dbg !18
  65. br label %if.end, !dbg !19
  66. if.else: ; preds = %entry
  67. %call1 = call i32 @bar(), !dbg !20
  68. %cmp2 = icmp slt i32 %call1, %b, !dbg !21
  69. br label %if.end
  70. if.end: ; preds = %if.else, %if.then
  71. %r.0 = phi i1 [ %cmp, %if.then ], [ %cmp2, %if.else ]
  72. %conv = zext i1 %r.0 to i32
  73. ret i32 %conv, !dbg !22
  74. }
  75. ; Test folding of getelementptr. Generated from source:
  76. ; extern long long foo2(void);
  77. ; extern long long bar2(void);
  78. ;
  79. ; int *gep(int a, int *b) {
  80. ; int *r;
  81. ; if(a)
  82. ; r = &b[foo2()];
  83. ; else
  84. ; r = &b[bar2()];
  85. ; return p;
  86. ; }
  87. ; CHECK: define i32* @gep
  88. ; CHECK-LABEL: if.end:
  89. ; CHECK: %[[PHI:.*]] = phi i64 [ %call, %if.then ], [ %call1, %if.else ]
  90. ; CHECK: getelementptr inbounds i32, i32* %b, i64 %[[PHI]], !dbg [[gepMergedLoc:![0-9]+]]
  91. ; CHECK: ret i32*
  92. define i32* @gep(i32 %a, i32* %b) !dbg !23 {
  93. entry:
  94. %tobool = icmp ne i32 %a, 0, !dbg !24
  95. br i1 %tobool, label %if.then, label %if.else, !dbg !24
  96. if.then: ; preds = %entry
  97. %call = call i64 @foo2(), !dbg !25
  98. %arrayidx = getelementptr inbounds i32, i32* %b, i64 %call, !dbg !26
  99. br label %if.end, !dbg !27
  100. if.else: ; preds = %entry
  101. %call1 = call i64 @bar2(), !dbg !28
  102. %arrayidx2 = getelementptr inbounds i32, i32* %b, i64 %call1, !dbg !29
  103. br label %if.end
  104. if.end: ; preds = %if.else, %if.then
  105. %r.0 = phi i32* [ %arrayidx, %if.then ], [ %arrayidx2, %if.else ]
  106. ret i32* %r.0, !dbg !30
  107. }
  108. ; Test folding of load. Generated from source:
  109. ; extern int *foo3(void);
  110. ; extern int *bar3(void);
  111. ;
  112. ; int load(int a) {
  113. ; int r;
  114. ; if(a)
  115. ; r = *foo3();
  116. ; else
  117. ; r = *bar3();
  118. ; return r;
  119. ; }
  120. ; CHECK: define i32 @load
  121. ; CHECK-LABEL: if.end:
  122. ; CHECK: %[[PHI:.*]] = phi i32* [ %call, %if.then ], [ %call1, %if.else ]
  123. ; CHECK: load i32, i32* %[[PHI]],{{.*}} !dbg [[loadMergedLoc:![0-9]+]]
  124. ; CHECK: ret i32
  125. define i32 @load(i32 %a) !dbg !31 {
  126. entry:
  127. %tobool = icmp ne i32 %a, 0, !dbg !32
  128. br i1 %tobool, label %if.then, label %if.else, !dbg !32
  129. if.then: ; preds = %entry
  130. %call = call i32* @foo3(), !dbg !33
  131. %0 = load i32, i32* %call, align 4, !dbg !34
  132. br label %if.end, !dbg !35
  133. if.else: ; preds = %entry
  134. %call1 = call i32* @bar3(), !dbg !36
  135. %1 = load i32, i32* %call1, align 4, !dbg !37
  136. br label %if.end
  137. if.end: ; preds = %if.else, %if.then
  138. %r.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ]
  139. ret i32 %r.0, !dbg !38
  140. }
  141. ; Test folding of a cast. Generated from source:
  142. ; extern int foo(void);
  143. ; extern int bar(void);
  144. ;
  145. ; long long cast(int a) {
  146. ; long long r;
  147. ; if(a)
  148. ; r = foo();
  149. ; else
  150. ; r = bar();
  151. ; return r;
  152. ; }
  153. ; CHECK: define i64 @cast
  154. ; CHECK-LABEL: if.end:
  155. ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
  156. ; CHECK: sext i32 %[[PHI]] to i64, !dbg [[castMergedLoc:![0-9]+]]
  157. ; CHECK: ret i64
  158. define i64 @cast(i32 %a) !dbg !39 {
  159. entry:
  160. %tobool = icmp ne i32 %a, 0, !dbg !40
  161. br i1 %tobool, label %if.then, label %if.else, !dbg !40
  162. if.then: ; preds = %entry
  163. %call = call i32 @foo(), !dbg !41
  164. %conv = sext i32 %call to i64, !dbg !41
  165. br label %if.end, !dbg !42
  166. if.else: ; preds = %entry
  167. %call1 = call i32 @bar(), !dbg !43
  168. %conv2 = sext i32 %call1 to i64, !dbg !43
  169. br label %if.end
  170. if.end: ; preds = %if.else, %if.then
  171. %r.0 = phi i64 [ %conv, %if.then ], [ %conv2, %if.else ]
  172. ret i64 %r.0, !dbg !44
  173. }
  174. ; Test folding of a binary op with a RHS constant. Generated from source:
  175. ; extern int foo(void);
  176. ; extern int bar(void);
  177. ;
  178. ; int binop_const(int a) {
  179. ; int r;
  180. ; if(a)
  181. ; r = foo() - 5;
  182. ; else
  183. ; r = bar() - 5;
  184. ; return r;
  185. ; }
  186. ; CHECK: define i32 @binop_const
  187. ; CHECK-LABEL: if.end:
  188. ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
  189. ; CHECK: add nsw i32 %[[PHI]], -5, !dbg [[binopConstMergedLoc:![0-9]+]]
  190. ; CHECK: ret i32
  191. define i32 @binop_const(i32 %a) !dbg !45 {
  192. entry:
  193. %tobool = icmp ne i32 %a, 0, !dbg !46
  194. br i1 %tobool, label %if.then, label %if.else, !dbg !46
  195. if.then: ; preds = %entry
  196. %call = call i32 @foo(), !dbg !47
  197. %sub = sub nsw i32 %call, 5, !dbg !48
  198. br label %if.end, !dbg !49
  199. if.else: ; preds = %entry
  200. %call1 = call i32 @bar(), !dbg !50
  201. %sub2 = sub nsw i32 %call1, 5, !dbg !51
  202. br label %if.end
  203. if.end: ; preds = %if.else, %if.then
  204. %r.0 = phi i32 [ %sub, %if.then ], [ %sub2, %if.else ]
  205. ret i32 %r.0, !dbg !52
  206. }
  207. ; Test folding of a compare with RHS constant. Generated from source (with
  208. ; editing to common the zext):
  209. ; extern int foo(void);
  210. ; extern int bar(void);
  211. ;
  212. ; int cmp_const(int a) {
  213. ; int r;
  214. ; if(a)
  215. ; r = foo() < 10;
  216. ; else
  217. ; r = bar() < 10;
  218. ; return r;
  219. ; }
  220. ; CHECK: define i32 @cmp_const
  221. ; CHECK-LABEL: if.end:
  222. ; CHECK: %[[PHI:.*]] = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
  223. ; CHECK: icmp slt i32 %[[PHI]], 10, !dbg [[cmpConstMergedLoc:![0-9]+]]
  224. ; CHECK: ret i32
  225. define i32 @cmp_const(i32 %a) !dbg !53 {
  226. entry:
  227. %tobool = icmp ne i32 %a, 0, !dbg !54
  228. br i1 %tobool, label %if.then, label %if.else, !dbg !54
  229. if.then: ; preds = %entry
  230. %call = call i32 @foo(), !dbg !55
  231. %cmp = icmp slt i32 %call, 10, !dbg !56
  232. br label %if.end, !dbg !57
  233. if.else: ; preds = %entry
  234. %call1 = call i32 @bar(), !dbg !58
  235. %cmp2 = icmp slt i32 %call1, 10, !dbg !59
  236. br label %if.end
  237. if.end: ; preds = %if.else, %if.then
  238. %r.0 = phi i1 [ %cmp, %if.then ], [ %cmp2, %if.else ]
  239. %conv = zext i1 %r.0 to i32
  240. ret i32 %conv, !dbg !60
  241. }
  242. declare i32 @foo()
  243. declare i32 @bar()
  244. declare i64 @foo2()
  245. declare i64 @bar2()
  246. declare i32* @foo3()
  247. declare i32* @bar3()
  248. ; CHECK: [[binopMergedLoc]] = !DILocation(line: 0
  249. ; CHECK: [[cmpMergedLoc]] = !DILocation(line: 0
  250. ; CHECK: [[gepMergedLoc]] = !DILocation(line: 0
  251. ; CHECK: [[loadMergedLoc]] = !DILocation(line: 0
  252. ; CHECK: [[castMergedLoc]] = !DILocation(line: 0
  253. ; CHECK: [[binopConstMergedLoc]] = !DILocation(line: 0
  254. ; CHECK: [[cmpConstMergedLoc]] = !DILocation(line: 0
  255. !llvm.dbg.cu = !{!0}
  256. !llvm.module.flags = !{!3, !4}
  257. !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
  258. !1 = !DIFile(filename: "test.c", directory: "")
  259. !2 = !{}
  260. !3 = !{i32 2, !"Dwarf Version", i32 4}
  261. !4 = !{i32 2, !"Debug Info Version", i32 3}
  262. !6 = distinct !DISubprogram(name: "binop", scope: !1, file: !1, line: 8, type: !7, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
  263. !7 = !DISubroutineType(types: !2)
  264. !8 = !DILocation(line: 9, column: 6, scope: !6)
  265. !9 = !DILocation(line: 10, column: 10, scope: !6)
  266. !10 = !DILocation(line: 10, column: 7, scope: !6)
  267. !11 = !DILocation(line: 10, column: 5, scope: !6)
  268. !12 = !DILocation(line: 12, column: 10, scope: !6)
  269. !13 = !DILocation(line: 12, column: 7, scope: !6)
  270. !14 = !DILocation(line: 13, column: 3, scope: !6)
  271. !15 = distinct !DISubprogram(name: "cmp", scope: !1, file: !1, line: 16, type: !7, isLocal: false, isDefinition: true, scopeLine: 16, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
  272. !16 = !DILocation(line: 18, column: 6, scope: !15)
  273. !17 = !DILocation(line: 19, column: 9, scope: !15)
  274. !18 = !DILocation(line: 19, column: 15, scope: !15)
  275. !19 = !DILocation(line: 19, column: 5, scope: !15)
  276. !20 = !DILocation(line: 21, column: 9, scope: !15)
  277. !21 = !DILocation(line: 21, column: 15, scope: !15)
  278. !22 = !DILocation(line: 22, column: 3, scope: !15)
  279. !23 = distinct !DISubprogram(name: "gep", scope: !1, file: !1, line: 25, type: !7, isLocal: false, isDefinition: true, scopeLine: 25, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
  280. !24 = !DILocation(line: 27, column: 6, scope: !23)
  281. !25 = !DILocation(line: 28, column: 12, scope: !23)
  282. !26 = !DILocation(line: 28, column: 10, scope: !23)
  283. !27 = !DILocation(line: 28, column: 5, scope: !23)
  284. !28 = !DILocation(line: 30, column: 12, scope: !23)
  285. !29 = !DILocation(line: 30, column: 10, scope: !23)
  286. !30 = !DILocation(line: 31, column: 3, scope: !23)
  287. !31 = distinct !DISubprogram(name: "load", scope: !1, file: !1, line: 34, type: !7, isLocal: false, isDefinition: true, scopeLine: 34, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
  288. !32 = !DILocation(line: 36, column: 6, scope: !31)
  289. !33 = !DILocation(line: 37, column: 10, scope: !31)
  290. !34 = !DILocation(line: 37, column: 9, scope: !31)
  291. !35 = !DILocation(line: 37, column: 5, scope: !31)
  292. !36 = !DILocation(line: 39, column: 10, scope: !31)
  293. !37 = !DILocation(line: 39, column: 9, scope: !31)
  294. !38 = !DILocation(line: 40, column: 3, scope: !31)
  295. !39 = distinct !DISubprogram(name: "cast", scope: !1, file: !1, line: 43, type: !7, isLocal: false, isDefinition: true, scopeLine: 43, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
  296. !40 = !DILocation(line: 45, column: 6, scope: !39)
  297. !41 = !DILocation(line: 46, column: 9, scope: !39)
  298. !42 = !DILocation(line: 46, column: 5, scope: !39)
  299. !43 = !DILocation(line: 48, column: 9, scope: !39)
  300. !44 = !DILocation(line: 49, column: 3, scope: !39)
  301. !45 = distinct !DISubprogram(name: "binop_const", scope: !1, file: !1, line: 52, type: !7, isLocal: false, isDefinition: true, scopeLine: 52, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
  302. !46 = !DILocation(line: 54, column: 6, scope: !45)
  303. !47 = !DILocation(line: 55, column: 9, scope: !45)
  304. !48 = !DILocation(line: 55, column: 15, scope: !45)
  305. !49 = !DILocation(line: 55, column: 5, scope: !45)
  306. !50 = !DILocation(line: 57, column: 9, scope: !45)
  307. !51 = !DILocation(line: 57, column: 15, scope: !45)
  308. !52 = !DILocation(line: 58, column: 3, scope: !45)
  309. !53 = distinct !DISubprogram(name: "cmp_const", scope: !1, file: !1, line: 61, type: !7, isLocal: false, isDefinition: true, scopeLine: 61, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
  310. !54 = !DILocation(line: 63, column: 6, scope: !53)
  311. !55 = !DILocation(line: 64, column: 9, scope: !53)
  312. !56 = !DILocation(line: 64, column: 15, scope: !53)
  313. !57 = !DILocation(line: 64, column: 5, scope: !53)
  314. !58 = !DILocation(line: 66, column: 9, scope: !53)
  315. !59 = !DILocation(line: 66, column: 15, scope: !53)
  316. !60 = !DILocation(line: 67, column: 3, scope: !53)