; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt %s -S -riscv-promote-const -mtriple=riscv64 -mattr=+d | FileCheck %s ; No promotion should take place, as the pass skips floats. define float @multiple_floats(float %a, float %b) { ; CHECK-LABEL: define float @multiple_floats( ; CHECK-SAME: float [[A:%.*]], float [[B:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[ADD1:%.*]] = fadd float [[A]], 1.000000e+00 ; CHECK-NEXT: [[ADD2:%.*]] = fadd float [[B]], 2.000000e+00 ; CHECK-NEXT: [[SUM_F:%.*]] = fadd float [[ADD1]], [[ADD2]] ; CHECK-NEXT: ret float [[SUM_F]] ; entry: %add1 = fadd float %a, 1.0 %add2 = fadd float %b, 2.0 %sum_f = fadd float %add1, %add2 ret float %sum_f } ; No promotion should take place as cases with a single constant are skipped. define double @single_double(double %a) { ; CHECK-LABEL: define double @single_double( ; CHECK-SAME: double [[A:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[A]], 4.210000e+01 ; CHECK-NEXT: ret double [[ADD]] ; entry: %add = fadd double %a, 42.1 ret double %add } ; Promotion should happen as we have at least two unique constants that would ; otherwise go in the constant pool. define double @multiple_doubles(double %a, double %b) { ; CHECK-LABEL: define double @multiple_doubles( ; CHECK-SAME: double [[A:%.*]], double [[B:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[DOUBLE_VAL1:%.*]] = load double, ptr getelementptr inbounds ([2 x double], ptr @.promoted_doubles.multiple_doubles, i64 0, i64 1), align 8 ; CHECK-NEXT: [[ADD3:%.*]] = load double, ptr @.promoted_doubles.multiple_doubles, align 8 ; CHECK-NEXT: [[ADD2:%.*]] = fadd double [[A]], [[ADD3]] ; CHECK-NEXT: [[ADD4:%.*]] = fadd double [[B]], [[DOUBLE_VAL1]] ; CHECK-NEXT: [[SUM:%.*]] = fadd double [[ADD2]], [[ADD3]] ; CHECK-NEXT: [[SUM1:%.*]] = fadd double [[ADD4]], [[SUM]] ; CHECK-NEXT: ret double [[SUM1]] ; entry: %add1 = fadd double %a, 2.718 %add2 = fadd double %b, 42.1 %add3 = fadd double %add1, 2.718 %sum = fadd double %add2, %add3 ret double %sum } ; Promotion should not happen as the constants will be materialised rather ; than using the constant pool. define double @multiple_doubles_no_promote(double %a, double %b) { ; CHECK-LABEL: define double @multiple_doubles_no_promote( ; CHECK-SAME: double [[A:%.*]], double [[B:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[A]], 1.000000e+00 ; CHECK-NEXT: [[ADD2:%.*]] = fadd double [[B]], 2.000000e+00 ; CHECK-NEXT: [[ADD3:%.*]] = fadd double [[ADD1]], 1.000000e+00 ; CHECK-NEXT: [[SUM:%.*]] = fadd double [[ADD2]], [[ADD3]] ; CHECK-NEXT: ret double [[SUM]] ; entry: %add1 = fadd double %a, 1.0 %add2 = fadd double %b, 2.0 %add3 = fadd double %add1, 1.0 %sum = fadd double %add2, %add3 ret double %sum } ; The same constant shouldn't be loaded more than once per BB. define double @multiple_doubles_multi_bb(double %a, i1 %cond) { ; CHECK-LABEL: define double @multiple_doubles_multi_bb( ; CHECK-SAME: double [[A:%.*]], i1 [[COND:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: br i1 [[COND]], label %[[IF_TRUE:.*]], label %[[IF_FALSE:.*]] ; CHECK: [[IF_TRUE]]: ; CHECK-NEXT: [[DOUBLE_VAL2:%.*]] = load double, ptr getelementptr inbounds ([2 x double], ptr @.promoted_doubles.multiple_doubles_multi_bb, i64 0, i64 1), align 8 ; CHECK-NEXT: [[DOUBLE_VAL:%.*]] = load double, ptr @.promoted_doubles.multiple_doubles_multi_bb, align 8 ; CHECK-NEXT: [[ADD_T:%.*]] = fadd double [[A]], [[DOUBLE_VAL]] ; CHECK-NEXT: [[MUL_T:%.*]] = fmul double [[ADD_T]], [[DOUBLE_VAL2]] ; CHECK-NEXT: [[SUB_T:%.*]] = fsub double [[MUL_T]], [[DOUBLE_VAL]] ; CHECK-NEXT: br label %[[IF_END:.*]] ; CHECK: [[IF_FALSE]]: ; CHECK-NEXT: [[DOUBLE_VAL3:%.*]] = load double, ptr getelementptr inbounds ([2 x double], ptr @.promoted_doubles.multiple_doubles_multi_bb, i64 0, i64 1), align 8 ; CHECK-NEXT: [[DOUBLE_VAL1:%.*]] = load double, ptr @.promoted_doubles.multiple_doubles_multi_bb, align 8 ; CHECK-NEXT: [[ADD_F:%.*]] = fadd double [[A]], [[DOUBLE_VAL1]] ; CHECK-NEXT: [[MUL_F:%.*]] = fmul double [[ADD_F]], [[DOUBLE_VAL3]] ; CHECK-NEXT: [[SUB_F:%.*]] = fsub double [[MUL_F]], [[DOUBLE_VAL1]] ; CHECK-NEXT: br label %[[IF_END]] ; CHECK: [[IF_END]]: ; CHECK-NEXT: [[PHI_RES:%.*]] = phi double [ [[SUB_T]], %[[IF_TRUE]] ], [ [[SUB_F]], %[[IF_FALSE]] ] ; CHECK-NEXT: ret double [[PHI_RES]] ; entry: br i1 %cond, label %if.true, label %if.false if.true: %add.t = fadd double %a, 1.23 %mul.t = fmul double %add.t, 4.56 %sub.t = fsub double %mul.t, 1.23 br label %if.end if.false: %add.f = fadd double %a, 1.23 %mul.f = fmul double %add.f, 4.56 %sub.f = fsub double %mul.f, 1.23 br label %if.end if.end: %phi.res = phi double [ %sub.t, %if.true ], [ %sub.f, %if.false ] ret double %phi.res } ; Check the insertion point in the case we have a phi taking a constant C and ; the source block also uses that same constant. define double @multiple_doubles_phi(double %a, i1 %cond) { ; CHECK-LABEL: define double @multiple_doubles_phi( ; CHECK-SAME: double [[A:%.*]], i1 [[COND:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] ; CHECK: [[IF_THEN]]: ; CHECK-NEXT: [[DOUBLE_VAL:%.*]] = load double, ptr @.promoted_doubles.multiple_doubles_phi, align 8 ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[A]], [[DOUBLE_VAL]] ; CHECK-NEXT: br label %[[IF_END]] ; CHECK: [[IF_END]]: ; CHECK-NEXT: [[PHI_VAL:%.*]] = phi double [ [[DOUBLE_VAL]], %[[IF_THEN]] ], [ [[A]], %[[ENTRY]] ] ; CHECK-NEXT: [[DOUBLE_VAL1:%.*]] = load double, ptr getelementptr inbounds ([2 x double], ptr @.promoted_doubles.multiple_doubles_phi, i64 0, i64 1), align 8 ; CHECK-NEXT: [[RES:%.*]] = fadd double [[PHI_VAL]], [[DOUBLE_VAL1]] ; CHECK-NEXT: ret double [[RES]] ; entry: br i1 %cond, label %if.then, label %if.end if.then: %mul = fmul double %a, 1.23 br label %if.end if.end: %phi.val = phi double [ 1.23, %if.then ], [ %a, %entry ] %res = fadd double %phi.val, 4.56 ret double %res }