; RUN: llc -mtriple=thumbv7m -arm-disable-cgp=false %s -o - | FileCheck %s --check-prefix=CHECK-COMMON ; RUN: llc -mtriple=thumbv8m.main -arm-disable-cgp=false %s -o - | FileCheck %s --check-prefix=CHECK-COMMON ; RUN: llc -mtriple=thumbv8m.main -arm-disable-cgp=false -arm-enable-scalar-dsp=true -mcpu=cortex-m33 %s -o - | FileCheck %s --check-prefix=CHECK-COMMON ; RUN: llc -mtriple=thumbv7em %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -arm-enable-scalar-dsp-imms=true -o - | FileCheck %s --check-prefix=CHECK-COMMON ; Test that ARMCodeGenPrepare can handle: ; - loops ; - call operands ; - call return values ; - ret instructions ; We use nuw on the arithmetic instructions to avoid complications. ; Check that the arguments are extended but then nothing else is. ; This also ensures that the pass can handle loops. ; CHECK-COMMON-LABEL: phi_feeding_phi_args ; CHECK-COMMON: uxtb ; CHECK-COMMON: uxtb ; CHECK-NOT: uxtb define void @phi_feeding_phi_args(i8 %a, i8 %b) { entry: %0 = icmp ugt i8 %a, %b br i1 %0, label %preheader, label %empty empty: br label %preheader preheader: %1 = phi i8 [ %a, %entry ], [ %b, %empty ] br label %loop loop: %val = phi i8 [ %1, %preheader ], [ %inc2, %if.end ] %cmp = icmp ult i8 %val, 254 br i1 %cmp, label %if.then, label %if.else if.then: %inc = sub nuw i8 %val, 2 br label %if.end if.else: %inc1 = shl nuw i8 %val, 1 br label %if.end if.end: %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ] %cmp1 = icmp eq i8 %inc2, 255 br i1 %cmp1, label %exit, label %loop exit: ret void } ; Same as above, but as the args are zeroext, we shouldn't see any uxts. ; CHECK-COMMON-LABEL: phi_feeding_phi_zeroext_args ; CHECK-COMMON-NOT: uxt define void @phi_feeding_phi_zeroext_args(i8 zeroext %a, i8 zeroext %b) { entry: %0 = icmp ugt i8 %a, %b br i1 %0, label %preheader, label %empty empty: br label %preheader preheader: %1 = phi i8 [ %a, %entry ], [ %b, %empty ] br label %loop loop: %val = phi i8 [ %1, %preheader ], [ %inc2, %if.end ] %cmp = icmp ult i8 %val, 254 br i1 %cmp, label %if.then, label %if.else if.then: %inc = sub nuw i8 %val, 2 br label %if.end if.else: %inc1 = shl nuw i8 %val, 1 br label %if.end if.end: %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ] %cmp1 = icmp eq i8 %inc2, 255 br i1 %cmp1, label %exit, label %loop exit: ret void } ; Just check that phis also work with i16s. ; CHECK-COMMON-LABEL: phi_i16: ; CHECK-COMMON-NOT: uxt define void @phi_i16() { entry: br label %loop loop: %val = phi i16 [ 0, %entry ], [ %inc2, %if.end ] %cmp = icmp ult i16 %val, 128 br i1 %cmp, label %if.then, label %if.else if.then: %inc = add nuw i16 %val, 2 br label %if.end if.else: %inc1 = add nuw i16 %val, 1 br label %if.end if.end: %inc2 = phi i16 [ %inc, %if.then], [ %inc1, %if.else ] %cmp1 = icmp ult i16 %inc2, 253 br i1 %cmp1, label %loop, label %exit exit: ret void } ; CHECK-COMMON-LABEL: ret_i8 ; CHECK-COMMON-NOT: uxt define i8 @ret_i8() { entry: br label %loop loop: %val = phi i8 [ 0, %entry ], [ %inc2, %if.end ] %cmp = icmp ult i8 %val, 128 br i1 %cmp, label %if.then, label %if.else if.then: %inc = add nuw i8 %val, 2 br label %if.end if.else: %inc1 = add nuw i8 %val, 1 br label %if.end if.end: %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ] %cmp1 = icmp ult i8 %inc2, 253 br i1 %cmp1, label %exit, label %loop exit: ret i8 %inc2 } ; CHECK-COMMON-LABEL: phi_multiple_undefs ; CHECK-COMMON-NOT: uxt define i16 @phi_multiple_undefs(i16 zeroext %arg) { entry: br label %loop loop: %val = phi i16 [ undef, %entry ], [ %inc2, %if.end ] %cmp = icmp ult i16 %val, 128 br i1 %cmp, label %if.then, label %if.else if.then: %inc = add nuw i16 %val, 2 br label %if.end if.else: %inc1 = add nuw i16 %val, 1 br label %if.end if.end: %inc2 = phi i16 [ %inc, %if.then], [ %inc1, %if.else ] %unrelated = phi i16 [ undef, %if.then ], [ %arg, %if.else ] %cmp1 = icmp ult i16 %inc2, 253 br i1 %cmp1, label %loop, label %exit exit: ret i16 %unrelated } ; CHECK-COMMON-LABEL: promote_arg_return ; CHECK-COMMON-NOT: uxt ; CHECK-COMMON: strb define i16 @promote_arg_return(i16 zeroext %arg1, i16 zeroext %arg2, i8* %res) { %add = add nuw i16 %arg1, 15 %mul = mul nuw nsw i16 %add, 3 %cmp = icmp ult i16 %mul, %arg2 %conv = zext i1 %cmp to i8 store i8 %conv, i8* %res ret i16 %arg1 }