@@ -1064,3 +1064,160 @@ define i8 @smul_7(i8 %x, ptr %p) {
10641064 store i1 %ov , ptr %p
10651065 ret i8 %r
10661066}
1067+
1068+ define i8 @uadd_assume_no_overflow (i8 noundef %a , i8 noundef %b ) {
1069+ ; CHECK-LABEL: @uadd_assume_no_overflow(
1070+ ; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1071+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1072+ ; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1073+ ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1074+ ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1075+ ; CHECK-NEXT: ret i8 [[CALL]]
1076+ ;
1077+ %call = call { i8 , i1 } @llvm.uadd.with.overflow.i8 (i8 %a , i8 %b )
1078+ %overflow = extractvalue { i8 , i1 } %call , 1
1079+ %ret = extractvalue { i8 , i1 } %call , 0
1080+ %not = xor i1 %overflow , true
1081+ call void @llvm.assume (i1 %not )
1082+ ret i8 %ret
1083+ }
1084+
1085+ define i8 @sadd_assume_no_overflow (i8 noundef %a , i8 noundef %b ) {
1086+ ; CHECK-LABEL: @sadd_assume_no_overflow(
1087+ ; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1088+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1089+ ; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1090+ ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1091+ ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1092+ ; CHECK-NEXT: ret i8 [[CALL]]
1093+ ;
1094+ %call = call { i8 , i1 } @llvm.sadd.with.overflow.i8 (i8 %a , i8 %b )
1095+ %overflow = extractvalue { i8 , i1 } %call , 1
1096+ %ret = extractvalue { i8 , i1 } %call , 0
1097+ %not = xor i1 %overflow , true
1098+ call void @llvm.assume (i1 %not )
1099+ ret i8 %ret
1100+ }
1101+
1102+ define i8 @usub_assume_no_overflow (i8 noundef %a , i8 noundef %b ) {
1103+ ; CHECK-LABEL: @usub_assume_no_overflow(
1104+ ; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1105+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1106+ ; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1107+ ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1108+ ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1109+ ; CHECK-NEXT: ret i8 [[CALL]]
1110+ ;
1111+ %call = call { i8 , i1 } @llvm.usub.with.overflow.i8 (i8 %a , i8 %b )
1112+ %overflow = extractvalue { i8 , i1 } %call , 1
1113+ %ret = extractvalue { i8 , i1 } %call , 0
1114+ %not = xor i1 %overflow , true
1115+ call void @llvm.assume (i1 %not )
1116+ ret i8 %ret
1117+ }
1118+
1119+ define i8 @ssub_assume_no_overflow (i8 noundef %a , i8 noundef %b ) {
1120+ ; CHECK-LABEL: @ssub_assume_no_overflow(
1121+ ; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1122+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1123+ ; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1124+ ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1125+ ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1126+ ; CHECK-NEXT: ret i8 [[CALL]]
1127+ ;
1128+ %call = call { i8 , i1 } @llvm.ssub.with.overflow.i8 (i8 %a , i8 %b )
1129+ %overflow = extractvalue { i8 , i1 } %call , 1
1130+ %ret = extractvalue { i8 , i1 } %call , 0
1131+ %not = xor i1 %overflow , true
1132+ call void @llvm.assume (i1 %not )
1133+ ret i8 %ret
1134+ }
1135+
1136+ define i8 @umul_assume_no_overflow (i8 noundef %a , i8 noundef %b ) {
1137+ ; CHECK-LABEL: @umul_assume_no_overflow(
1138+ ; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1139+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1140+ ; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1141+ ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1142+ ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1143+ ; CHECK-NEXT: ret i8 [[CALL]]
1144+ ;
1145+ %call = call { i8 , i1 } @llvm.umul.with.overflow.i8 (i8 %a , i8 %b )
1146+ %overflow = extractvalue { i8 , i1 } %call , 1
1147+ %ret = extractvalue { i8 , i1 } %call , 0
1148+ %not = xor i1 %overflow , true
1149+ call void @llvm.assume (i1 %not )
1150+ ret i8 %ret
1151+ }
1152+
1153+ define i8 @smul_assume_no_overflow (i8 noundef %a , i8 noundef %b ) {
1154+ ; CHECK-LABEL: @smul_assume_no_overflow(
1155+ ; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1156+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1157+ ; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1158+ ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1159+ ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1160+ ; CHECK-NEXT: ret i8 [[CALL]]
1161+ ;
1162+ %call = call { i8 , i1 } @llvm.smul.with.overflow.i8 (i8 %a , i8 %b )
1163+ %overflow = extractvalue { i8 , i1 } %call , 1
1164+ %ret = extractvalue { i8 , i1 } %call , 0
1165+ %not = xor i1 %overflow , true
1166+ call void @llvm.assume (i1 %not )
1167+ ret i8 %ret
1168+ }
1169+
1170+ define i1 @ephemeral_call_assume_no_overflow (i8 noundef %a , i8 noundef %b ) {
1171+ ; CHECK-LABEL: @ephemeral_call_assume_no_overflow(
1172+ ; CHECK-NEXT: [[CALL:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1173+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL]], 1
1174+ ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1175+ ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1176+ ; CHECK-NEXT: ret i1 [[NOT]]
1177+ ;
1178+ %call = call { i8 , i1 } @llvm.smul.with.overflow.i8 (i8 %a , i8 %b )
1179+ %overflow = extractvalue { i8 , i1 } %call , 1
1180+ %not = xor i1 %overflow , true
1181+ call void @llvm.assume (i1 %not )
1182+ ret i1 %not
1183+ }
1184+
1185+ define i8 @neg_assume_overflow (i8 noundef %a , i8 noundef %b ) {
1186+ ; CHECK-LABEL: @neg_assume_overflow(
1187+ ; CHECK-NEXT: [[CALL:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1188+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL]], 1
1189+ ; CHECK-NEXT: [[RET:%.*]] = extractvalue { i8, i1 } [[CALL]], 0
1190+ ; CHECK-NEXT: call void @llvm.assume(i1 [[OVERFLOW]])
1191+ ; CHECK-NEXT: ret i8 [[RET]]
1192+ ;
1193+ %call = call { i8 , i1 } @llvm.smul.with.overflow.i8 (i8 %a , i8 %b )
1194+ %overflow = extractvalue { i8 , i1 } %call , 1
1195+ %ret = extractvalue { i8 , i1 } %call , 0
1196+ call void @llvm.assume (i1 %overflow )
1197+ ret i8 %ret
1198+ }
1199+
1200+ define i8 @neg_assume_not_guaranteed_to_execute (i8 noundef %a , i8 noundef %b , i1 %cond ) {
1201+ ; CHECK-LABEL: @neg_assume_not_guaranteed_to_execute(
1202+ ; CHECK-NEXT: [[CALL:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1203+ ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
1204+ ; CHECK: bb1:
1205+ ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL]], 1
1206+ ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1207+ ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1208+ ; CHECK-NEXT: br label [[BB2]]
1209+ ; CHECK: bb2:
1210+ ; CHECK-NEXT: [[RET:%.*]] = extractvalue { i8, i1 } [[CALL]], 0
1211+ ; CHECK-NEXT: ret i8 [[RET]]
1212+ ;
1213+ %call = call { i8 , i1 } @llvm.smul.with.overflow.i8 (i8 %a , i8 %b )
1214+ %overflow = extractvalue { i8 , i1 } %call , 1
1215+ %ret = extractvalue { i8 , i1 } %call , 0
1216+ br i1 %cond , label %bb1 , label %bb2
1217+ bb1:
1218+ %not = xor i1 %overflow , true
1219+ call void @llvm.assume (i1 %not )
1220+ br label %bb2
1221+ bb2:
1222+ ret i8 %ret
1223+ }
0 commit comments