1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4; Check that we don't create two redundant phi nodes when %val is used in a 5; form where we can't rewrite it in terms of the new phi node. 6 7; Use %val in an instruction type not supported by optimizeBitCastFromPhi. 8define float @sitofp(float %x) { 9; CHECK-LABEL: @sitofp( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 12; CHECK: loop_header: 13; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL_INCR_CASTED:%.*]], [[LOOP:%.*]] ] 14; CHECK-NEXT: [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float 15; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[VAL_CASTED]], [[X:%.*]] 16; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[LOOP]] 17; CHECK: loop: 18; CHECK-NEXT: [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00 19; CHECK-NEXT: [[VAL_INCR_CASTED]] = bitcast float [[VAL_INCR]] to i32 20; CHECK-NEXT: br label [[LOOP_HEADER]] 21; CHECK: end: 22; CHECK-NEXT: [[RESULT:%.*]] = sitofp i32 [[VAL]] to float 23; CHECK-NEXT: ret float [[RESULT]] 24; 25entry: 26 br label %loop_header 27loop_header: 28 %val = phi i32 [ 0, %entry ], [ %val_incr_casted, %loop ] 29 %val_casted = bitcast i32 %val to float 30 %cmp = fcmp ogt float %val_casted, %x 31 br i1 %cmp, label %end, label %loop 32loop: 33 %val_incr = fadd float %val_casted, 1.0 34 %val_incr_casted = bitcast float %val_incr to i32 35 br label %loop_header 36end: 37 %result = sitofp i32 %val to float 38 ret float %result 39} 40 41; Use %val in an incompatible bitcast. 42define <2 x i16> @bitcast(float %x) { 43; CHECK-LABEL: @bitcast( 44; CHECK-NEXT: entry: 45; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 46; CHECK: loop_header: 47; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL_INCR_CASTED:%.*]], [[LOOP:%.*]] ] 48; CHECK-NEXT: [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float 49; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[VAL_CASTED]], [[X:%.*]] 50; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[LOOP]] 51; CHECK: loop: 52; CHECK-NEXT: [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00 53; CHECK-NEXT: [[VAL_INCR_CASTED]] = bitcast float [[VAL_INCR]] to i32 54; CHECK-NEXT: br label [[LOOP_HEADER]] 55; CHECK: end: 56; CHECK-NEXT: [[RESULT:%.*]] = bitcast i32 [[VAL]] to <2 x i16> 57; CHECK-NEXT: ret <2 x i16> [[RESULT]] 58; 59entry: 60 br label %loop_header 61loop_header: 62 %val = phi i32 [ 0, %entry ], [ %val_incr_casted, %loop ] 63 %val_casted = bitcast i32 %val to float 64 %cmp = fcmp ogt float %val_casted, %x 65 br i1 %cmp, label %end, label %loop 66loop: 67 %val_incr = fadd float %val_casted, 1.0 68 %val_incr_casted = bitcast float %val_incr to i32 69 br label %loop_header 70end: 71 %result = bitcast i32 %val to <2 x i16> 72 ret <2 x i16> %result 73} 74 75@global = global i32 0 76 77; Use %val with a volatile store. 78define void @store_volatile(float %x) { 79; CHECK-LABEL: @store_volatile( 80; CHECK-NEXT: entry: 81; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 82; CHECK: loop_header: 83; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL_INCR_CASTED:%.*]], [[LOOP:%.*]] ] 84; CHECK-NEXT: [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float 85; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[VAL_CASTED]], [[X:%.*]] 86; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[LOOP]] 87; CHECK: loop: 88; CHECK-NEXT: [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00 89; CHECK-NEXT: [[VAL_INCR_CASTED]] = bitcast float [[VAL_INCR]] to i32 90; CHECK-NEXT: br label [[LOOP_HEADER]] 91; CHECK: end: 92; CHECK-NEXT: store volatile i32 [[VAL]], i32* @global, align 4 93; CHECK-NEXT: ret void 94; 95entry: 96 br label %loop_header 97loop_header: 98 %val = phi i32 [ 0, %entry ], [ %val_incr_casted, %loop ] 99 %val_casted = bitcast i32 %val to float 100 %cmp = fcmp ogt float %val_casted, %x 101 br i1 %cmp, label %end, label %loop 102loop: 103 %val_incr = fadd float %val_casted, 1.0 104 %val_incr_casted = bitcast float %val_incr to i32 105 br label %loop_header 106end: 107 store volatile i32 %val, i32* @global 108 ret void 109} 110 111; Use %val with a store where it's actually the address. 112define void @store_address(i32 %x) { 113; CHECK-LABEL: @store_address( 114; CHECK-NEXT: entry: 115; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 116; CHECK: loop_header: 117; CHECK-NEXT: [[VAL:%.*]] = phi i32* [ @global, [[ENTRY:%.*]] ], [ [[VAL_INCR1:%.*]], [[LOOP:%.*]] ] 118; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0 119; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[LOOP]] 120; CHECK: loop: 121; CHECK-NEXT: [[VAL_INCR1]] = getelementptr i32, i32* [[VAL]], i64 1 122; CHECK-NEXT: br label [[LOOP_HEADER]] 123; CHECK: end: 124; CHECK-NEXT: store i32 0, i32* [[VAL]], align 4 125; CHECK-NEXT: ret void 126; 127entry: 128 br label %loop_header 129loop_header: 130 %val = phi i32* [ @global, %entry ], [ %val_incr_casted, %loop ] 131 %i = phi i32 [ 0, %entry ], [ %i_incr, %loop ] 132 %val_casted = bitcast i32* %val to float* 133 %cmp = icmp sgt i32 %i, %x 134 br i1 %cmp, label %end, label %loop 135loop: 136 %i_incr = add i32 %i, 0 137 %val_incr = getelementptr float, float* %val_casted, i32 1 138 %val_incr_casted = bitcast float* %val_incr to i32* 139 br label %loop_header 140end: 141 store i32 0, i32* %val 142 ret void 143} 144 145; Test where a phi (%val2) other than the original one (%val) has an 146; incompatible use. 147define i32 @multiple_phis(float %x) { 148; CHECK-LABEL: @multiple_phis( 149; CHECK-NEXT: entry: 150; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 151; CHECK: loop_header: 152; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL2:%.*]], [[LOOP_END:%.*]] ] 153; CHECK-NEXT: [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float 154; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[VAL_CASTED]], [[X:%.*]] 155; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[LOOP:%.*]] 156; CHECK: loop: 157; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[VAL_CASTED]], 2.000000e+00 158; CHECK-NEXT: br i1 [[CMP2]], label [[IF:%.*]], label [[LOOP_END]] 159; CHECK: if: 160; CHECK-NEXT: [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00 161; CHECK-NEXT: [[VAL_INCR_CASTED:%.*]] = bitcast float [[VAL_INCR]] to i32 162; CHECK-NEXT: br label [[LOOP_END]] 163; CHECK: loop_end: 164; CHECK-NEXT: [[VAL2]] = phi i32 [ [[VAL]], [[LOOP]] ], [ [[VAL_INCR_CASTED]], [[IF]] ] 165; CHECK-NEXT: store volatile i32 [[VAL2]], i32* @global, align 4 166; CHECK-NEXT: br label [[LOOP_HEADER]] 167; CHECK: end: 168; CHECK-NEXT: ret i32 [[VAL]] 169; 170entry: 171 br label %loop_header 172loop_header: 173 %val = phi i32 [ 0, %entry ], [ %val2, %loop_end ] 174 %val_casted = bitcast i32 %val to float 175 %cmp = fcmp ogt float %val_casted, %x 176 br i1 %cmp, label %end, label %loop 177loop: 178 %cmp2 = fcmp ogt float %val_casted, 2.0 179 br i1 %cmp2, label %if, label %loop_end 180if: 181 %val_incr = fadd float %val_casted, 1.0 182 %val_incr_casted = bitcast float %val_incr to i32 183 br label %loop_end 184loop_end: 185 %val2 = phi i32 [ %val, %loop ], [ %val_incr_casted, %if ] 186 store volatile i32 %val2, i32* @global ; the incompatible use 187 br label %loop_header 188end: 189 ret i32 %val 190} 191