Home | History | Annotate | Download | only in LoopRotate
      1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
      2 ; RUN: opt -S -loop-rotate < %s -verify-loop-info -verify-dom-info | FileCheck %s
      3 
      4 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
      5 target triple = "thumbv8m.base-arm-none-eabi"
      6 
      7 %struct.List = type { %struct.List*, i32 }
      8 
      9 define void @list_add(%struct.List** nocapture %list, %struct.List* %data) {
     10 ; CHECK-LABEL: @list_add(
     11 ; CHECK-NEXT:  entry:
     12 ; CHECK-NEXT:    [[TMP0:%.*]] = load %struct.List*, %struct.List** [[LIST:%.*]], align 4
     13 ; CHECK-NEXT:    [[VAL2:%.*]] = getelementptr inbounds [[STRUCT_LIST:%.*]], %struct.List* [[TMP0]], i32 0, i32 1
     14 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[VAL2]], align 4
     15 ; CHECK-NEXT:    [[VAL1:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[DATA:%.*]], i32 0, i32 1
     16 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[VAL1]], align 4
     17 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]]
     18 ; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN_LR_PH:%.*]], label [[IF_ELSE6:%.*]]
     19 ; CHECK:       if.then.lr.ph:
     20 ; CHECK-NEXT:    br label [[IF_THEN:%.*]]
     21 ; CHECK:       for.cond:
     22 ; CHECK-NEXT:    [[CURR_0:%.*]] = phi %struct.List* [ [[TMP5:%.*]], [[IF_THEN]] ]
     23 ; CHECK-NEXT:    [[PREV_0:%.*]] = phi %struct.List* [ [[CURR_04:%.*]], [[IF_THEN]] ]
     24 ; CHECK-NEXT:    [[VAL:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[CURR_0]], i32 0, i32 1
     25 ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[VAL]], align 4
     26 ; CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* [[VAL1]], align 4
     27 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP3]], [[TMP4]]
     28 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN]], label [[FOR_COND_IF_ELSE6_CRIT_EDGE:%.*]]
     29 ; CHECK:       if.then:
     30 ; CHECK-NEXT:    [[CURR_04]] = phi %struct.List* [ [[TMP0]], [[IF_THEN_LR_PH]] ], [ [[CURR_0]], [[FOR_COND:%.*]] ]
     31 ; CHECK-NEXT:    [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[CURR_04]], i32 0, i32 0
     32 ; CHECK-NEXT:    [[TMP5]] = load %struct.List*, %struct.List** [[NEXT]], align 4
     33 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq %struct.List* [[TMP5]], null
     34 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[FOR_COND]]
     35 ; CHECK:       if.else:
     36 ; CHECK-NEXT:    [[NEXT_LCSSA:%.*]] = phi %struct.List** [ [[NEXT]], [[IF_THEN]] ]
     37 ; CHECK-NEXT:    store %struct.List* [[DATA]], %struct.List** [[NEXT_LCSSA]], align 4
     38 ; CHECK-NEXT:    [[NEXT5:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[DATA]], i32 0, i32 0
     39 ; CHECK-NEXT:    store %struct.List* null, %struct.List** [[NEXT5]], align 4
     40 ; CHECK-NEXT:    br label [[FOR_END:%.*]]
     41 ; CHECK:       for.cond.if.else6_crit_edge:
     42 ; CHECK-NEXT:    [[SPLIT:%.*]] = phi %struct.List* [ [[PREV_0]], [[FOR_COND]] ]
     43 ; CHECK-NEXT:    br label [[IF_ELSE6]]
     44 ; CHECK:       if.else6:
     45 ; CHECK-NEXT:    [[PREV_0_LCSSA:%.*]] = phi %struct.List* [ [[SPLIT]], [[FOR_COND_IF_ELSE6_CRIT_EDGE]] ], [ null, [[ENTRY:%.*]] ]
     46 ; CHECK-NEXT:    [[TOBOOL7:%.*]] = icmp eq %struct.List* [[PREV_0_LCSSA]], null
     47 ; CHECK-NEXT:    br i1 [[TOBOOL7]], label [[IF_ELSE12:%.*]], label [[IF_THEN8:%.*]]
     48 ; CHECK:       if.then8:
     49 ; CHECK-NEXT:    [[NEXT9:%.*]] = getelementptr inbounds [[STRUCT_LIST]], %struct.List* [[PREV_0_LCSSA]], i32 0, i32 0
     50 ; CHECK-NEXT:    [[TMP6:%.*]] = bitcast %struct.List* [[PREV_0_LCSSA]] to i32*
     51 ; CHECK-NEXT:    [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4
     52 ; CHECK-NEXT:    [[TMP8:%.*]] = bitcast %struct.List* [[DATA]] to i32*
     53 ; CHECK-NEXT:    store i32 [[TMP7]], i32* [[TMP8]], align 4
     54 ; CHECK-NEXT:    store %struct.List* [[DATA]], %struct.List** [[NEXT9]], align 4
     55 ; CHECK-NEXT:    br label [[FOR_END]]
     56 ; CHECK:       if.else12:
     57 ; CHECK-NEXT:    [[TMP9:%.*]] = bitcast %struct.List** [[LIST]] to i32*
     58 ; CHECK-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4
     59 ; CHECK-NEXT:    [[TMP11:%.*]] = bitcast %struct.List* [[DATA]] to i32*
     60 ; CHECK-NEXT:    store i32 [[TMP10]], i32* [[TMP11]], align 4
     61 ; CHECK-NEXT:    store %struct.List* [[DATA]], %struct.List** [[LIST]], align 4
     62 ; CHECK-NEXT:    br label [[FOR_END]]
     63 ; CHECK:       for.end:
     64 ; CHECK-NEXT:    ret void
     65 ;
     66 entry:
     67   %0 = load %struct.List*, %struct.List** %list, align 4
     68   br label %for.cond
     69 
     70 for.cond:                                         ; preds = %if.then, %entry
     71   %curr.0 = phi %struct.List* [ %0, %entry ], [ %3, %if.then ]
     72   %prev.0 = phi %struct.List* [ null, %entry ], [ %curr.0, %if.then ]
     73   %val = getelementptr inbounds %struct.List, %struct.List* %curr.0, i32 0, i32 1
     74   %1 = load i32, i32* %val, align 4
     75   %val1 = getelementptr inbounds %struct.List, %struct.List* %data, i32 0, i32 1
     76   %2 = load i32, i32* %val1, align 4
     77   %cmp = icmp slt i32 %1, %2
     78   br i1 %cmp, label %if.then, label %if.else6
     79 
     80 if.then:                                          ; preds = %for.cond
     81   %next = getelementptr inbounds %struct.List, %struct.List* %curr.0, i32 0, i32 0
     82   %3 = load %struct.List*, %struct.List** %next, align 4
     83   %tobool = icmp eq %struct.List* %3, null
     84   br i1 %tobool, label %if.else, label %for.cond
     85 
     86 if.else:                                          ; preds = %if.then
     87   %next.lcssa = phi %struct.List** [ %next, %if.then ]
     88   store %struct.List* %data, %struct.List** %next.lcssa, align 4
     89   %next5 = getelementptr inbounds %struct.List, %struct.List* %data, i32 0, i32 0
     90   store %struct.List* null, %struct.List** %next5, align 4
     91   br label %for.end
     92 
     93 if.else6:                                         ; preds = %for.cond
     94   %prev.0.lcssa = phi %struct.List* [ %prev.0, %for.cond ]
     95   %tobool7 = icmp eq %struct.List* %prev.0.lcssa, null
     96   br i1 %tobool7, label %if.else12, label %if.then8
     97 
     98 if.then8:                                         ; preds = %if.else6
     99   %next9 = getelementptr inbounds %struct.List, %struct.List* %prev.0.lcssa, i32 0, i32 0
    100   %4 = bitcast %struct.List* %prev.0.lcssa to i32*
    101   %5 = load i32, i32* %4, align 4
    102   %6 = bitcast %struct.List* %data to i32*
    103   store i32 %5, i32* %6, align 4
    104   store %struct.List* %data, %struct.List** %next9, align 4
    105   br label %for.end
    106 
    107 if.else12:                                        ; preds = %if.else6
    108   %7 = bitcast %struct.List** %list to i32*
    109   %8 = load i32, i32* %7, align 4
    110   %9 = bitcast %struct.List* %data to i32*
    111   store i32 %8, i32* %9, align 4
    112   store %struct.List* %data, %struct.List** %list, align 4
    113   br label %for.end
    114 
    115 for.end:                                          ; preds = %if.else12, %if.then8, %if.else
    116   ret void
    117 }
    118 
    119 define i32 @test2(i32* %l) {
    120 ; CHECK-LABEL: @test2(
    121 ; CHECK-NEXT:  entry:
    122 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[L:%.*]], align 4
    123 ; CHECK-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[TMP0]], 0
    124 ; CHECK-NEXT:    br i1 [[TOBOOL2]], label [[CLEANUP:%.*]], label [[DO_COND_LR_PH:%.*]]
    125 ; CHECK:       do.cond.lr.ph:
    126 ; CHECK-NEXT:    br label [[DO_COND:%.*]]
    127 ; CHECK:       do.body:
    128 ; CHECK-NEXT:    [[A_0:%.*]] = phi i32 [ [[REM:%.*]], [[DO_COND]] ]
    129 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[L]], align 4
    130 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP1]], 0
    131 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[DO_BODY_CLEANUP_CRIT_EDGE:%.*]], label [[DO_COND]]
    132 ; CHECK:       do.body.cleanup_crit_edge:
    133 ; CHECK-NEXT:    [[SPLIT:%.*]] = phi i32 [ [[A_0]], [[DO_BODY:%.*]] ]
    134 ; CHECK-NEXT:    br label [[CLEANUP]]
    135 ; CHECK:       cleanup:
    136 ; CHECK-NEXT:    [[A_0_LCSSA:%.*]] = phi i32 [ [[SPLIT]], [[DO_BODY_CLEANUP_CRIT_EDGE]] ], [ 100, [[ENTRY:%.*]] ]
    137 ; CHECK-NEXT:    store i32 10, i32* [[L]], align 4
    138 ; CHECK-NEXT:    br label [[CLEANUP2:%.*]]
    139 ; CHECK:       do.cond:
    140 ; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP0]], [[DO_COND_LR_PH]] ], [ [[TMP1]], [[DO_BODY]] ]
    141 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[TMP2]], 13
    142 ; CHECK-NEXT:    [[REM]] = srem i32 [[MUL]], 27
    143 ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[L]], align 4
    144 ; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[TMP3]], 0
    145 ; CHECK-NEXT:    br i1 [[TOBOOL1]], label [[CLEANUP2_LOOPEXIT:%.*]], label [[DO_BODY]]
    146 ; CHECK:       cleanup2.loopexit:
    147 ; CHECK-NEXT:    br label [[CLEANUP2]]
    148 ; CHECK:       cleanup2:
    149 ; CHECK-NEXT:    [[RETVAL_2:%.*]] = phi i32 [ [[A_0_LCSSA]], [[CLEANUP]] ], [ 0, [[CLEANUP2_LOOPEXIT]] ]
    150 ; CHECK-NEXT:    ret i32 [[RETVAL_2]]
    151 ;
    152 entry:
    153   br label %do.body
    154 
    155 do.body:                                          ; preds = %do.cond, %entry
    156   %a.0 = phi i32 [ 100, %entry ], [ %rem, %do.cond ]
    157   %0 = load i32, i32* %l, align 4
    158   %tobool = icmp eq i32 %0, 0
    159   br i1 %tobool, label %cleanup, label %do.cond
    160 
    161 cleanup:                                          ; preds = %do.body
    162   %a.0.lcssa = phi i32 [ %a.0, %do.body ]
    163   store i32 10, i32* %l, align 4
    164   br label %cleanup2
    165 
    166 do.cond:                                          ; preds = %do.body
    167   %mul = mul nsw i32 %0, 13
    168   %rem = srem i32 %mul, 27
    169   %1 = load i32, i32* %l, align 4
    170   %tobool1 = icmp eq i32 %1, 0
    171   br i1 %tobool1, label %cleanup2.loopexit, label %do.body
    172 
    173 cleanup2.loopexit:                                ; preds = %do.cond
    174   br label %cleanup2
    175 
    176 cleanup2:                                         ; preds = %cleanup2.loopexit, %cleanup
    177   %retval.2 = phi i32 [ %a.0.lcssa, %cleanup ], [ 0, %cleanup2.loopexit ]
    178   ret i32 %retval.2
    179 }
    180 
    181 define i32 @no_rotate(i32* %l) {
    182 ; CHECK-LABEL: @no_rotate(
    183 ; CHECK-NEXT:  entry:
    184 ; CHECK-NEXT:    br label [[DO_BODY:%.*]]
    185 ; CHECK:       do.body:
    186 ; CHECK-NEXT:    [[A_0:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[REM:%.*]], [[DO_COND:%.*]] ]
    187 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[L:%.*]], align 4
    188 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
    189 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[CLEANUP:%.*]], label [[DO_COND]]
    190 ; CHECK:       cleanup:
    191 ; CHECK-NEXT:    [[A_0_LCSSA:%.*]] = phi i32 [ [[A_0]], [[DO_BODY]] ]
    192 ; CHECK-NEXT:    store i32 10, i32* [[L]], align 4
    193 ; CHECK-NEXT:    br label [[CLEANUP2:%.*]]
    194 ; CHECK:       do.cond:
    195 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[A_0]], 13
    196 ; CHECK-NEXT:    [[REM]] = srem i32 [[MUL]], 27
    197 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[L]], align 4
    198 ; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[TMP1]], 0
    199 ; CHECK-NEXT:    br i1 [[TOBOOL1]], label [[CLEANUP2_LOOPEXIT:%.*]], label [[DO_BODY]]
    200 ; CHECK:       cleanup2.loopexit:
    201 ; CHECK-NEXT:    br label [[CLEANUP2]]
    202 ; CHECK:       cleanup2:
    203 ; CHECK-NEXT:    [[RETVAL_2:%.*]] = phi i32 [ [[A_0_LCSSA]], [[CLEANUP]] ], [ 0, [[CLEANUP2_LOOPEXIT]] ]
    204 ; CHECK-NEXT:    ret i32 [[RETVAL_2]]
    205 ;
    206 entry:
    207   br label %do.body
    208 
    209 do.body:                                          ; preds = %do.cond, %entry
    210   %a.0 = phi i32 [ 100, %entry ], [ %rem, %do.cond ]
    211   %0 = load i32, i32* %l, align 4
    212   %tobool = icmp eq i32 %0, 0
    213   br i1 %tobool, label %cleanup, label %do.cond
    214 
    215 cleanup:                                          ; preds = %do.body
    216   %a.0.lcssa = phi i32 [ %a.0, %do.body ]
    217   store i32 10, i32* %l, align 4
    218   br label %cleanup2
    219 
    220 do.cond:                                          ; preds = %do.body
    221   %mul = mul nsw i32 %a.0, 13
    222   %rem = srem i32 %mul, 27
    223   %1 = load i32, i32* %l, align 4
    224   %tobool1 = icmp eq i32 %1, 0
    225   br i1 %tobool1, label %cleanup2.loopexit, label %do.body
    226 
    227 cleanup2.loopexit:                                ; preds = %do.cond
    228   br label %cleanup2
    229 
    230 cleanup2:                                         ; preds = %cleanup2.loopexit, %cleanup
    231   %retval.2 = phi i32 [ %a.0.lcssa, %cleanup ], [ 0, %cleanup2.loopexit ]
    232   ret i32 %retval.2
    233 }
    234 
    235