diff --git a/llvm/test/Transforms/FunctionSpecialization/identical-specializations.ll b/llvm/test/Transforms/FunctionSpecialization/identical-specializations.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/FunctionSpecialization/identical-specializations.ll @@ -0,0 +1,79 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=function-specialization -force-function-specialization -S < %s | FileCheck %s + +define i64 @main(i64 %x, i64 %y, i1 %flag) { +; CHECK-LABEL: @main( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[PLUS:%.*]], label [[MINUS:%.*]] +; CHECK: plus: +; CHECK-NEXT: [[CMP0:%.*]] = call i64 @compute.1(i64 [[X:%.*]], i64 [[Y:%.*]], i64 (i64, i64)* @plus, i64 (i64, i64)* @minus) +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: minus: +; CHECK-NEXT: [[CMP1:%.*]] = call i64 @compute.2(i64 [[X]], i64 [[Y]], i64 (i64, i64)* @minus, i64 (i64, i64)* @plus) +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: [[PH:%.*]] = phi i64 [ [[CMP0]], [[PLUS]] ], [ [[CMP1]], [[MINUS]] ] +; CHECK-NEXT: [[CMP2:%.*]] = call i64 @compute.1(i64 [[PH]], i64 42, i64 (i64, i64)* @plus, i64 (i64, i64)* @minus) +; CHECK-NEXT: ret i64 [[CMP2]] +; +entry: + br i1 %flag, label %plus, label %minus + +plus: + %cmp0 = call i64 @compute(i64 %x, i64 %y, i64 (i64, i64)* @plus, i64 (i64, i64)* @minus) + br label %merge + +minus: + %cmp1 = call i64 @compute(i64 %x, i64 %y, i64 (i64, i64)* @minus, i64 (i64, i64)* @plus) + br label %merge + +merge: + %ph = phi i64 [ %cmp0, %plus ], [ %cmp1, %minus] + %cmp2 = call i64 @compute(i64 %ph, i64 42, i64 (i64, i64)* @plus, i64 (i64, i64)* @minus) + ret i64 %cmp2 +} + +define internal i64 @compute(i64 %x, i64 %y, i64 (i64, i64)* %binop1, i64 (i64, i64)* %binop2) { +entry: + %op0 = call i64 %binop1(i64 %x, i64 %y) + %op1 = call i64 %binop2(i64 %x, i64 %y) + %op2 = call i64 @compute(i64 %x, i64 %y, i64 (i64, i64)* %binop1, i64 (i64, i64)* @plus) + %add0 = add i64 %op0, %op1 + %add1 = add i64 %add0, %op2 + %div = sdiv i64 %add1, %x + %sub = sub i64 %div, %y + %mul = mul i64 %sub, 2 + ret i64 %mul +} + +define internal i64 @plus(i64 %x, i64 %y) { +; CHECK-LABEL: @plus( +entry: + %add = add i64 %x, %y + ret i64 %add +} + +define internal i64 @minus(i64 %x, i64 %y) { +; CHECK-LABEL: @minus( +entry: + %sub = sub i64 %x, %y + ret i64 %sub +} + +; CHECK-LABEL: @compute.1 +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP0:%.*]] = call i64 @plus(i64 [[X:%.*]], i64 [[Y:%.*]]) +; CHECK-NEXT: [[CMP1:%.*]] = call i64 @minus(i64 [[X]], i64 [[Y]]) +; CHECK-NEXT: [[CMP2:%.*]] = call i64 @compute(i64 [[X]], i64 [[Y]], i64 (i64, i64)* @plus, i64 (i64, i64)* @plus) + +; CHECK-LABEL: @compute.2 +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP0:%.*]] = call i64 @minus(i64 [[X:%.*]], i64 [[Y:%.*]]) +; CHECK-NEXT: [[CMP1:%.*]] = call i64 @plus(i64 [[X]], i64 [[Y]]) +; CHECK-NEXT: [[CMP2:%.*]] = call i64 @compute(i64 [[X]], i64 [[Y]], i64 (i64, i64)* @minus, i64 (i64, i64)* @plus) + +; CHECK-LABEL: @compute.3 +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP0:%.*]] = call i64 @plus(i64 [[X:%.*]], i64 [[Y:%.*]]) +; CHECK-NEXT: [[CMP1:%.*]] = call i64 @minus(i64 [[X]], i64 [[Y]]) +; CHECK-NEXT: [[CMP2:%.*]] = call i64 @compute(i64 [[X]], i64 [[Y]], i64 (i64, i64)* @plus, i64 (i64, i64)* @plus)